Monday, March 26, 2012

Creating a Flex AIR Annotator app: Part 36

Today we will make it possible to hold shift to keep proportions when resizing images and make it possible to change depth of images.

First of all, let's cover the depth feature. It is quite simple - when the user starts moving an image - put it on top of everything else. This will let the user do whatever he wants and arrange images in the desired order.

Go to imgMove() and add a line that sets element index of currentlyDragging object:

private function imgMove(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 1 && currentlyDragging && !drawHitArea.mouseEnabled) {
images.setElementIndex(currentlyDragging, images.numElements - 1);
cursorManager.setCursor(moveCursor, 2, -10, -10);
drawHitArea.mouseEnabled = true;
drawHitArea.x = -1;
drawHitArea.y = 0;
drawHitArea.width = content.width;
drawHitArea.height = content.height;
}
}

Now we'll do the proportion resizing functionality.

Declare a variable called currentRatio first:

private var currentRatio:Number;

Go to anchorDown() and set this variable's value to width divided by height of the currently selected image.

private function anchorDown(evt:MouseEvent):void {
currentRatio = currentImage.width / currentImage.height;
img_rectangle = [currentImage.x, currentImage.y, currentImage.width, currentImage.height];
switch(evt.currentTarget) {
case imageAnchors[0]: img_currentDir = "upLeft"; img_anchorY = img_rectangle[1] + img_rectangle[3]; img_anchorX = img_rectangle[0] + img_rectangle[2]; break;
case imageAnchors[1]: img_currentDir = "up"; img_anchorY = img_rectangle[1] + img_rectangle[3]; break;
case imageAnchors[2]: img_currentDir = "upRight"; img_anchorY = img_rectangle[1] + img_rectangle[3]; img_anchorX = img_rectangle[0]; break;
case imageAnchors[3]: img_currentDir = "left"; img_anchorX = img_rectangle[0] + img_rectangle[2]; break;
case imageAnchors[4]: img_currentDir = "right"; img_anchorX = img_rectangle[0]; break;
case imageAnchors[5]: img_currentDir = "downLeft"; img_anchorY = img_rectangle[1]; img_anchorX = img_rectangle[0] + img_rectangle[2]; break;
case imageAnchors[6]: img_currentDir = "down"; img_anchorY = img_rectangle[1]; break;
case imageAnchors[7]: img_currentDir = "downRight"; img_anchorY = img_rectangle[1]; img_anchorX = img_rectangle[0]; break;
}
img_resizing = true;
drawHitArea.mouseEnabled = true;
drawHitArea.width = content.width;
drawHitArea.height = content.height;
drawHitArea.x = -1;
drawHitArea.y = 1;
}

Now we'll go to imageResize() and edit the last 4 conditionals - we'll only need to check if shift is held down if the direction is upLeft, upRight, downLeft or downRight.

Instead of calculating height as usual when the shift is held, set it to current width divided by the ratio to get the new height.

if (img_currentDir == "upLeft" && mouseY >= 0 && mouseY < img_anchorY && mouseX >= 0 && mouseX < img_anchorX) { 
if (!isShift) img_rectangle = [mouseX, mouseY - 1, img_anchorX - mouseX, img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
if (isShift) img_rectangle = [mouseX, img_anchorY - (img_anchorX - mouseX)/currentRatio, img_anchorX - mouseX, (img_anchorX - mouseX)/currentRatio]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
}
if (img_currentDir == "upRight" && mouseY >= 0 && mouseY < img_anchorY && mouseX < content.width && mouseX > img_anchorX) { 
if (!isShift) img_rectangle = [img_anchorX, mouseY - 1, mouseX - img_anchorX, img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
if (isShift) img_rectangle = [img_anchorX, img_anchorY - (mouseX - img_anchorX)/currentRatio, mouseX - img_anchorX, (mouseX - img_anchorX)/currentRatio]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
}
if (img_currentDir == "downLeft" && mouseY < content.height && mouseY > img_anchorY && mouseX >= 0 && mouseX < img_anchorX) { 
if (!isShift) img_rectangle = [mouseX, img_anchorY, img_anchorX - mouseX, mouseY - img_anchorY]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
if (isShift) img_rectangle = [mouseX, img_anchorY, img_anchorX - mouseX, (img_anchorX - mouseX)/currentRatio]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
}
if (img_currentDir == "downRight" && mouseY < content.height && mouseY > img_anchorY && mouseX < content.width && mouseX > img_anchorX) { 
if (!isShift) img_rectangle = [img_anchorX, img_anchorY, mouseX - img_anchorX, mouseY - img_anchorY]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
if (isShift) img_rectangle = [img_anchorX, img_anchorY, mouseX - img_anchorX, (mouseX - img_anchorX)/currentRatio]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
}

This can lead to the images stretching outside of the drawing area. To prevent this, add a conditional before calling updateImage() or positionResize():

if(img_rectangle[0]>=0 && img_rectangle[1]>=0 && img_rectangle[2] + img_rectangle[0]<=content.width && img_rectangle[3] + img_rectangle[1]<=content.height){
updateImage();
positionResize();
}

Full imageResize() function:

private function imageResize():void {
if (img_resizing) {
cursorManager.removeAllCursors();
var prevRect:Array = img_rectangle;
var mouseX:Number = drawArea.mouseX;
var mouseY:Number = drawArea.mouseY;
if (img_currentDir == "up" && mouseY >= 0 && mouseY < img_anchorY) {
img_rectangle = [prevRect[0], mouseY - 1, prevRect[2], img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10);
}
if (img_currentDir == "down" && mouseY < content.height && mouseY > img_anchorY) { 
img_rectangle = [prevRect[0], img_anchorY, prevRect[2], mouseY - img_anchorY]; cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10);
}
if (img_currentDir == "left" && mouseX >= 0 && mouseX < img_anchorX) { 
img_rectangle = [mouseX, prevRect[1], img_anchorX - mouseX, prevRect[3]]; cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10);
}
if (img_currentDir == "right" && mouseX < content.width && mouseX > img_anchorX) { 
img_rectangle = [img_anchorX, prevRect[1], mouseX - img_anchorX, prevRect[3]]; cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10);
}
if (img_currentDir == "upLeft" && mouseY >= 0 && mouseY < img_anchorY && mouseX >= 0 && mouseX < img_anchorX) { 
if (!isShift) img_rectangle = [mouseX, mouseY - 1, img_anchorX - mouseX, img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
if (isShift) img_rectangle = [mouseX, img_anchorY - (img_anchorX - mouseX)/currentRatio, img_anchorX - mouseX, (img_anchorX - mouseX)/currentRatio]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
}
if (img_currentDir == "upRight" && mouseY >= 0 && mouseY < img_anchorY && mouseX < content.width && mouseX > img_anchorX) { 
if (!isShift) img_rectangle = [img_anchorX, mouseY - 1, mouseX - img_anchorX, img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
if (isShift) img_rectangle = [img_anchorX, img_anchorY - (mouseX - img_anchorX)/currentRatio, mouseX - img_anchorX, (mouseX - img_anchorX)/currentRatio]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
}
if (img_currentDir == "downLeft" && mouseY < content.height && mouseY > img_anchorY && mouseX >= 0 && mouseX < img_anchorX) { 
if (!isShift) img_rectangle = [mouseX, img_anchorY, img_anchorX - mouseX, mouseY - img_anchorY]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
if (isShift) img_rectangle = [mouseX, img_anchorY, img_anchorX - mouseX, (img_anchorX - mouseX)/currentRatio]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
}
if (img_currentDir == "downRight" && mouseY < content.height && mouseY > img_anchorY && mouseX < content.width && mouseX > img_anchorX) { 
if (!isShift) img_rectangle = [img_anchorX, img_anchorY, mouseX - img_anchorX, mouseY - img_anchorY]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
if (isShift) img_rectangle = [img_anchorX, img_anchorY, mouseX - img_anchorX, (mouseX - img_anchorX)/currentRatio]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
}

if(img_rectangle[0]>=0 && img_rectangle[1]>=0 && img_rectangle[2] + img_rectangle[0]<=content.width && img_rectangle[3] + img_rectangle[1]<=content.height){
updateImage();
positionResize();
}
}
}

A problem with anchors might occur if the user draws his mouse outside and back inside the drawing box while resizing an image - the anchors just disappear. To prevent this, check if img_resizing is false in disableResize():

private function disableResize():void {
if(toolbarStack.selectedIndex==1 && !img_resizing){
anchors.alpha = 0;
anchors.mouseEnabled = false;
anchors.mouseChildren = false;
}
}

And that's it!

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();" 
   applicationComplete="listeners();"
   minWidth="800" minHeight="400"
   width="800" height="500">

<fx:Script>
<![CDATA[
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.FocusDirection;
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.filesystem.File;
import flash.filesystem.FileStream;
import flash.filters.DropShadowFilter;
import flash.geom.Matrix;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.net.FileFilter;
import flash.net.URLRequest;
import flash.text.TextField;
import flash.utils.ByteArray;
import mx.controls.Alert;
import flash.filesystem.FileMode;
import mx.controls.Image;
import mx.controls.Label;
import mx.controls.TextArea;
import mx.core.FlexGlobals;
import mx.events.CloseEvent;
import mx.graphics.codec.IImageEncoder;
import mx.graphics.codec.JPEGEncoder;
import mx.graphics.codec.PNGEncoder;
import spark.components.Group;
import spark.core.SpriteVisualElement;
import spark.primitives.Rect;
import flash.text.TextFieldAutoSize;
import mx.managers.PopUpManager;
import mx.utils.ObjectUtil;

private var bitmapData:BitmapData;
private var content:*;
[Bindable]
private var buttonsEnabled:Boolean = false;
[Bindable]
private var lineThickness:int = 5;
[Bindable]
private var lineColor:uint = 0xff0000;
[Bindable]
private var aBodyColor:uint = 0xffff88;
[Bindable]
private var aTextColor:uint = 0x000000;

[Embed(source="../lib/cursor_cross.png")]
private var crossCursor:Class;
[Embed(source="../lib/cursor_move.png")]
private var moveCursor:Class;
[Embed(source="../lib/ic_eyedropper.png")]
private var pickerCursor: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 drawMode:String = "";
private var anchorX:Number;
private var anchorY:Number;
private var lastX:Number;
private var lastY:Number;
private var isShift:Boolean = false;
private var temporaryBitmap:BitmapData;
private var currentlyEditing:*;
private var currentlyDragging:*;
private var dragOffsetX:Number;
private var dragOffsetY:Number;
private var currentImage:*;
private var imageAnchors:Array;
private var currentRatio:Number;

private var preferences:SharedObject = SharedObject.getLocal("kirannotatorPreferences");
private var selectedFormat:String;
private var selectedQuality:int;

private var img_resizing:Boolean = false;
private var img_currentDir:String = "";
private var img_anchorX:Number;
private var img_anchorY:Number;
private var img_rectangle:Array;

private var crop_rectangle:Array;
private var crop_anchorX:Number;
private var crop_anchorY:Number;
private var crop_drawing:Boolean = false;
private var crop_selectionType:Boolean;
private var crop_inSelection:Boolean = false;
private var crop_offsetX:Number;
private var crop_offsetY:Number;
private var crop_dragging:Boolean = false;
private var crop_inResize:Boolean = false;
private var crop_resizing:Boolean = false;
private var crop_resizeDir:String = "";
private var crop_resizeRadius:Number = 6;

private function init():void {
/* Uncomment this line to reset locally saved preferences: */
//preferences.data.firsttime = null;

// Set preferences if loaded for the first time
if (preferences.data.firsttime == null) {
preferences.data.firsttime = true;
preferences.data.selectedFormat = 'jpg';
preferences.data.selectedQuality = 70;
preferences.data.selectionType = true;
preferences.flush();
}

// Set preferences loaded from local storage
selectedFormat = preferences.data.selectedFormat;
selectedQuality = preferences.data.selectedQuality;
crop_selectionType = preferences.data.selectionType;

drawArea.filters = [new DropShadowFilter(4, 60, 0, 0.7, 10, 10, 1, 3)];
}

private function listeners():void {
addEventListener(MouseEvent.MOUSE_UP, drawUp);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, keyUp);
addEventListener(Event.ENTER_FRAME, everyFrame);
}

private function keyDown(evt:KeyboardEvent):void {
if (evt.keyCode == 16) {
isShift = true;
}
}

private function keyUp(evt:KeyboardEvent):void {
if (evt.keyCode == 16) {
isShift = false;
}
}

private function everyFrame(evt:Event):void {
if (toolbarStack.selectedIndex == 2 && focusManager.getFocus() != saveBtn) {
focusManager.setFocus(saveBtn);
}
}

private function canvasOver():void {
if ((toolbarStack.selectedIndex == 3 || toolbarStack.selectedIndex == 1) && currentlyDragging != null) {
cursorManager.setCursor(moveCursor, 2, -9, -10);
}
if (toolbarStack.selectedIndex == 2 && drawTools) {
if(drawTools.selectedIndex < 5){
cursorManager.setCursor(crossCursor, 2, -10, -10);
} else {
cursorManager.setCursor(pickerCursor, 2, 0, -18);
}
}
if (toolbarStack.selectedIndex == 4) {
if (!crop_dragging && !crop_resizing) cursorManager.setCursor(crossCursor, 2, -9, -10);
if (crop_dragging) cursorManager.setCursor(moveCursor, 2, -9, -10);
if (crop_resizing) {
switch(crop_resizeDir) {
case "up": case "down": cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10); break;
case "right": case "left": cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10); break;
case "upLeft": case "downRight": cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10); break;
case "upRight": case "downLeft": cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10); break;
}
};
};
}

private function canvasOut():void {
cursorManager.removeAllCursors();
}

private function drawDown():void {
// cropping
if(toolbarStack.selectedIndex == 4) crop_mouseDown(drawArea.mouseX, drawArea.mouseY);

// drawing
if (toolbarStack.selectedIndex == 2 && drawTools.selectedIndex == 0) {
drawMode = "pen";
drawSprite.graphics.moveTo(drawArea.mouseX, drawArea.mouseY);
}
if (toolbarStack.selectedIndex == 2 && drawTools.selectedIndex == 3) {
drawMode = "line";
tempSprite.graphics.moveTo(drawArea.mouseX, drawArea.mouseY);
anchorX = drawArea.mouseX;
anchorY = drawArea.mouseY;
}
if (toolbarStack.selectedIndex == 2 && drawTools.selectedIndex == 2) {
drawMode = "rect";
anchorX = drawArea.mouseX;
anchorY = drawArea.mouseY;
}
if (toolbarStack.selectedIndex == 2 && drawTools.selectedIndex == 1) {
drawMode = "ellipse";
anchorX = drawArea.mouseX;
anchorY = drawArea.mouseY;
}
if (toolbarStack.selectedIndex == 2 && drawTools.selectedIndex == 4) {
drawMode = "arrow";
tempSprite.graphics.moveTo(drawArea.mouseX, drawArea.mouseY);
anchorX = drawArea.mouseX;
anchorY = drawArea.mouseY;
lastX = drawArea.mouseX;
lastY = drawArea.mouseY;
}
if (toolbarStack.selectedIndex == 2 && drawTools.selectedIndex == 5) {
drawMode = "picker";
drawTempBitmap();
getPickerColor();
}
}

private function drawUp(evt:MouseEvent):void {
img_resizing = false;
// cropping
if (toolbarStack.selectedIndex == 4) crop_stopDraw();

// drawing
if (drawMode == "line") {
tempSprite.graphics.clear();
drawSprite.graphics.lineStyle(lineThickness, lineColor);
drawSprite.graphics.moveTo(anchorX, anchorY);
drawSprite.graphics.lineTo(lastX, lastY);
}
if (drawMode == "rect") {
tempSprite.graphics.clear();
drawSprite.graphics.lineStyle(lineThickness, lineColor);
var newRectValues:Array;
if (!isShift) {
newRectValues = calculateRectValues(lastX, lastY, anchorX, anchorY);
}
if(isShift){
newRectValues = calculateSquareValues(lastX, lastY, anchorX, anchorY);
}
drawSprite.graphics.drawRect(newRectValues[0], newRectValues[1], newRectValues[2], newRectValues[3]);
}
if (drawMode == "ellipse") {
tempSprite.graphics.clear();
drawSprite.graphics.lineStyle(lineThickness, lineColor);
var newEllipseValues:Array;
if (!isShift) {
newEllipseValues = calculateRectValues(lastX, lastY, anchorX, anchorY);
}
if(isShift){
newEllipseValues = calculateSquareValues(lastX, lastY, anchorX, anchorY);
}
drawSprite.graphics.drawEllipse(newEllipseValues[0], newEllipseValues[1], newEllipseValues[2], newEllipseValues[3]);
}
if (drawMode == "arrow") {
tempSprite.graphics.clear();
var angle:Number = Math.atan2(anchorY - lastY, anchorX - lastX);
var armlength:Number = 10 + 2.5 * lineThickness;
var offset:Number = (24 - 0.5 * lineThickness) * Math.PI / 180;
var arm1x:Number = armlength * Math.cos(angle + offset) + lastX;
var arm1y:Number = armlength * Math.sin(angle + offset) + lastY;
var arm2x:Number = armlength * Math.cos(angle - offset) + lastX;
var arm2y:Number = armlength * Math.sin(angle - offset) + lastY;

if (arm1x > 0 + lineThickness / 2 && arm1x < drawArea.width - lineThickness / 2 &&
arm1y > 0 + lineThickness / 2 && arm1y < drawArea.height - lineThickness / 2 &&
arm2x > 0 + lineThickness / 2 && arm2x < drawArea.width - lineThickness / 2 &&
arm2y > 0 + lineThickness / 2 && arm2y < drawArea.height - lineThickness / 2 &&
lastX > 9 + lineThickness / 2 && lastX < drawArea.width - lineThickness / 2 - 9 &&
lastY > 9 + lineThickness / 2 && lastY < drawArea.height - lineThickness / 2 - 9){
drawSprite.graphics.lineStyle(lineThickness, lineColor, 1, false, "normal", CapsStyle.NONE, JointStyle.MITER);
drawSprite.graphics.moveTo(anchorX, anchorY);
drawSprite.graphics.lineTo(lastX, lastY);

drawSprite.graphics.beginFill(lineColor, 1);
drawSprite.graphics.moveTo(arm1x, arm1y);
drawSprite.graphics.lineTo(lastX, lastY);
drawSprite.graphics.lineTo(arm2x, arm2y);
drawSprite.graphics.lineTo(arm1x, arm1y);
drawSprite.graphics.endFill();
}
}
drawMode = "";
currentlyDragging = null;
if (toolbarStack.selectedIndex == 3 || toolbarStack.selectedIndex == 1) {
drawHitArea.mouseEnabled = false;
cursorManager.removeAllCursors();
disableResize();
updateDrawHitArea();
}
}

private function drawMove():void {
// image resizing
imageResize();

// cropping
if(toolbarStack.selectedIndex == 4) crop_moveDraw(drawArea.mouseX, drawArea.mouseY);

// drawing
if (drawMode == "pen") {
drawSprite.graphics.lineStyle(lineThickness, lineColor);
drawSprite.graphics.lineTo(drawArea.mouseX, drawArea.mouseY);
}
if (drawMode == "line") {
if (!isShift) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
tempSprite.graphics.moveTo(anchorX, anchorY);
tempSprite.graphics.lineTo(drawArea.mouseX, drawArea.mouseY);
lastX = drawArea.mouseX;
lastY = drawArea.mouseY;
}
if (isShift) {
var straightLinePoint:Point = straightLine(drawArea.mouseX, drawArea.mouseY, anchorX, anchorY);
if (straightLinePoint.x > lineThickness / 2 && straightLinePoint.x < drawArea.width - lineThickness / 2 &&
straightLinePoint.y > lineThickness/2 && straightLinePoint.y < drawArea.height - lineThickness /2) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
tempSprite.graphics.moveTo(anchorX, anchorY);
tempSprite.graphics.lineTo(straightLinePoint.x, straightLinePoint.y);
lastX = straightLinePoint.x;
lastY = straightLinePoint.y;
}
}
}
if (drawMode == "rect") {
var newRectValues:Array;
if (!isShift) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
newRectValues = calculateRectValues(drawArea.mouseX, drawArea.mouseY, anchorX, anchorY);
}
if(isShift){
newRectValues = calculateSquareValues(drawArea.mouseX, drawArea.mouseY, anchorX, anchorY);
}
tempSprite.graphics.drawRect(newRectValues[0], newRectValues[1], newRectValues[2], newRectValues[3]);
lastX = drawArea.mouseX;
lastY = drawArea.mouseY;
}
if (drawMode == "ellipse") {
var newEllipseValues:Array;
if (!isShift) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
newEllipseValues = calculateRectValues(drawArea.mouseX, drawArea.mouseY, anchorX, anchorY);
}
if(isShift){
newEllipseValues = calculateSquareValues(drawArea.mouseX, drawArea.mouseY, anchorX, anchorY);
}
tempSprite.graphics.drawEllipse(newEllipseValues[0], newEllipseValues[1], newEllipseValues[2], newEllipseValues[3]);
lastX = drawArea.mouseX;
lastY = drawArea.mouseY;
}
if (drawMode == "arrow") {
var mouseX:Number = (isShift)?(straightLine(drawArea.mouseX, drawArea.mouseY, anchorX, anchorY).x):(drawArea.mouseX);
var mouseY:Number = (isShift)?(straightLine(drawArea.mouseX, drawArea.mouseY, anchorX, anchorY).y):(drawArea.mouseY);
var angle:Number = Math.atan2(anchorY - mouseY, anchorX - mouseX);
var armlength:Number = 10 + 2.5 * lineThickness;
var offset:Number = (24 - 0.5 * lineThickness) * Math.PI / 180;
var arm1x:Number = armlength * Math.cos(angle + offset) + mouseX;
var arm1y:Number = armlength * Math.sin(angle + offset) + mouseY;
var arm2x:Number = armlength * Math.cos(angle - offset) + mouseX;
var arm2y:Number = armlength * Math.sin(angle - offset) + mouseY;

if (arm1x > 0 + lineThickness / 2 && arm1x < drawArea.width - lineThickness / 2 &&
arm1y > 0 + lineThickness / 2 && arm1y < drawArea.height - lineThickness / 2 &&
arm2x > 0 + lineThickness / 2 && arm2x < drawArea.width - lineThickness / 2 &&
arm2y > 0 + lineThickness / 2 && arm2y < drawArea.height - lineThickness / 2 &&
mouseX > 9 + lineThickness / 2 && mouseX < drawArea.width - lineThickness / 2 - 9 &&
mouseY > 9 + lineThickness / 2 && mouseY < drawArea.height - lineThickness / 2 - 9){
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor, 1, false, "normal", CapsStyle.NONE, JointStyle.MITER);
tempSprite.graphics.moveTo(anchorX, anchorY);
tempSprite.graphics.lineTo(mouseX, mouseY);

tempSprite.graphics.beginFill(lineColor, 1);
tempSprite.graphics.moveTo(arm1x, arm1y);
tempSprite.graphics.lineTo(mouseX, mouseY);
tempSprite.graphics.lineTo(arm2x, arm2y);
tempSprite.graphics.lineTo(arm1x, arm1y);
tempSprite.graphics.endFill();

lastX = mouseX;
lastY = mouseY;
}
}
if (drawMode == "picker") {
getPickerColor();
}
if ((toolbarStack.selectedIndex == 3 || toolbarStack.selectedIndex == 1) && currentlyDragging != null) {
var nextDragX:Number = drawArea.mouseX - dragOffsetX;
var nextDragY:Number = drawArea.mouseY - dragOffsetY;
if (nextDragX >= 0 && nextDragX + currentlyDragging.width <= content.width) currentlyDragging.x = nextDragX;
if (nextDragY >= 0 && nextDragY + currentlyDragging.height <= content.height) currentlyDragging.y = nextDragY;
if (nextDragX < 0) currentlyDragging.x = 0;
if (nextDragY < 0) currentlyDragging.y = 0;
if (nextDragX + currentlyDragging.width > content.width) currentlyDragging.x = content.width - currentlyDragging.width;
if (nextDragY + currentlyDragging.height > content.height) currentlyDragging.y = content.height - currentlyDragging.height;
positionResize();
}
}

private function straightLine(mouseX:Number, mouseY:Number, anchX:Number, anchY:Number):Point {
var p:Point = new Point(0, 0);
var rotation:Number = Math.atan2(mouseY - anchY, mouseX - anchX) * 180 / Math.PI;
if (rotation<-35 && rotation>-55) {
p = new Point(mouseX, anchY - (mouseX - anchX));
}else
if (rotation<-125 && rotation>-145) {
p = new Point(mouseX, (mouseX - anchX) + anchY);
}else
if (rotation>35 && rotation<55) {
p = new Point(mouseX, (mouseX - anchX) + anchY);
}else
if (rotation>125 && rotation<145) {
p = new Point(mouseX, anchY - (mouseX - anchX));
}else
if (Math.abs(mouseX - anchX) > Math.abs(mouseY - anchY)) {
p = new Point(mouseX, anchY);
}else
if (Math.abs(mouseX - anchX) < Math.abs(mouseY - anchY)) {
p = new Point(anchX, mouseY);
}
return p;
}

private function calculateRectValues(currentX:Number, currentY:Number, anchX:Number, anchY:Number):Array {
var newrect:Array = [0, 0, 0, 0];
// bottom - right
if (currentX > anchX  && currentY > anchY) {
newrect[0] = anchX;
newrect[1] = anchY-1;
newrect[2] = currentX - anchX;
newrect[3] = currentY - anchY;
}
// bottom - left
if (currentX < anchX  && currentY > anchY) {
newrect[0] = currentX;
newrect[1] = anchY-1;
newrect[2] = anchX - currentX;
newrect[3] = currentY - anchY;
}
// top - right
if (currentX > anchX  && currentY < anchY) {
newrect[0] = anchX;
newrect[1] = currentY-1;
newrect[2] = currentX - anchX;
newrect[3] = anchY - currentY;
}
// top - left
if (currentX < anchX  && currentY < anchY) {
newrect[0] = currentX;
newrect[1] = currentY-1;
newrect[2] = anchX - currentX;
newrect[3] = anchY - currentY;
}
return newrect;
}

private function calculateSquareValues(currentX:Number, currentY:Number, anchX:Number, anchY:Number):Array {
var newrect:Array = [0, 0, 0, 0];
// bottom - right
if (currentX > anchX  && currentY > anchY) {
currentY = (currentX - anchX) + anchY;
if (currentY > 0 + lineThickness/2 && currentY < drawArea.height - lineThickness/2) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
newrect[0] = anchX;
newrect[1] = anchY-1;
newrect[2] = currentX - anchX;
newrect[3] = currentY - anchY;
}
}
// bottom - left
if (currentX < anchX  && currentY > anchY) {
currentY = anchY - (currentX - anchX);
if (currentY > 0 + lineThickness/2 && currentY < drawArea.height - lineThickness/2) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
newrect[0] = currentX;
newrect[1] = anchY-1;
newrect[2] = anchX - currentX;
newrect[3] = currentY - anchY;
}
}
// top - right
if (currentX > anchX  && currentY < anchY) {
currentY = anchY - (currentX - anchX);
if (currentY > 0 + lineThickness/2 && currentY < drawArea.height - lineThickness/2) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
newrect[0] = anchX;
newrect[1] = currentY-1;
newrect[2] = currentX - anchX;
newrect[3] = anchY - currentY;
}
}
// top - left
if (currentX < anchX  && currentY < anchY) {
currentY = (currentX - anchX) + anchY;
if (currentY > 0 + lineThickness/2 && currentY < drawArea.height - lineThickness/2) {
tempSprite.graphics.clear();
tempSprite.graphics.lineStyle(lineThickness, lineColor);
newrect[0] = currentX;
newrect[1] = currentY-1;
newrect[2] = anchX - currentX;
newrect[3] = anchY - currentY;
}
}
return newrect;
}

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);
stackChange(); // needed if selectedIndex was already 1 when the function was called
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;
cropDraw.width = content.width;
cropDraw.height = content.height;
buttonsEnabled = true;
drawSprite.graphics.clear();
var anns:Number = annotations.numChildren;
for (var i:int = 0; i < anns; i++){
annotations.removeElementAt(0);
}
var imgs:Number = images.numChildren;
for (var u:int = 0; u < imgs; u++){
images.removeElementAt(0);
}
drawTempBitmap();
updateDrawHitArea();
crop_deselect();
}
}

private function toolbarChange():void {
if (toolbarStack.selectedIndex == 2) {
updateLineExample();
drawHitArea.mouseEnabled = true;
}else if 
(toolbarStack.selectedIndex == 4) {
drawHitArea.mouseEnabled = true;
drawHitArea.width = content.width;
drawHitArea.height = content.height;
drawHitArea.x = -1;
drawHitArea.y = 1;
}else {
drawHitArea.mouseEnabled = false;
}
}

private function updateLineExample():void{
lineExample.graphics.clear();
lineExample.graphics.lineStyle(lineThickness, lineColor);
lineExample.graphics.moveTo(10, 10);
lineExample.graphics.lineTo(30, 10);

updateDrawHitArea();
}

private function updateDrawHitArea():void {
drawHitArea.width = content.width - lineThickness;
drawHitArea.height = content.height - lineThickness;
drawHitArea.x = lineThickness / 2;
drawHitArea.y = lineThickness / 2;

annHitArea.width = content.width;
annHitArea.height = content.height;
annHitArea.x = 0;
annHitArea.y = 0;
}

private function drawTempBitmap():void {
temporaryBitmap = new BitmapData(content.width, content.height, false, 0xffffff);
temporaryBitmap.draw(drawArea);
}

private function getPickerColor():void {
lineColor = temporaryBitmap.getPixel(drawArea.mouseX, drawArea.mouseY);
}

private function openAnnotation(createX:Number = 0, createY:Number = 0):void {
if(toolbarStack.selectedIndex==3){
PopUpManager.addPopUp(annotationWindow, this, true);
PopUpManager.centerPopUp(annotationWindow);
annText.text = "Enter text here";
annotationWindow.title = "Create new annotation";
annWidth.maximum = drawArea.width;
annWidth.value = 200;
annX.value = createX;
annY.value = createY;
updateAnnCoordLimits();
baNew.enabled = true;
baEdit.enabled = false;
baDelete.enabled = false;
}
}

private function closeAnnotation():void {
PopUpManager.removePopUp(annotationWindow);
}

private function addAnnotation():void {
var newAnn:spark.components.TextArea = new spark.components.TextArea();
newAnn.text = annText.text;
newAnn.width = annWidth.value;
newAnn.setStyle("contentBackgroundColor", aBodyColor);
newAnn.setStyle("color", aTextColor);
newAnn.setStyle("borderVisible", annBorder.selected);
newAnn.editable = false;
newAnn.selectable = false;
annotations.addElement(newAnn);
newAnn.validateNow();
newAnn.heightInLines = NaN;
newAnn.x = annX.value;
newAnn.y = annY.value;
newAnn.addEventListener(MouseEvent.ROLL_OVER, annOver);
newAnn.addEventListener(MouseEvent.ROLL_OUT, annOut);
newAnn.addEventListener(MouseEvent.DOUBLE_CLICK, annClick);
newAnn.addEventListener(MouseEvent.MOUSE_DOWN, annDown);
newAnn.addEventListener(MouseEvent.MOUSE_MOVE, annMove);
newAnn.buttonMode = true;
}

private function editAnnotation():void {
var editAnn:* = currentlyEditing;
editAnn.text = annText.text;
editAnn.width = annWidth.value;
editAnn.setStyle("contentBackgroundColor", aBodyColor);
editAnn.setStyle("borderVisible", annBorder.selected);
editAnn.setStyle("color", aTextColor);
editAnn.heightInLines = NaN;
editAnn.x = annX.value;
editAnn.y = annY.value;
}

private function deleteAnnotation():void {
annotations.removeElement(currentlyEditing);
}

private function annOver(evt:MouseEvent):void {
disableResize();
if (toolbarStack.selectedIndex == 3) {
evt.target.alpha = 0.8;
}
}

private function annOut(evt:MouseEvent):void{
evt.target.alpha = 1;
if (toolbarStack.selectedIndex == 3 && currentlyDragging == null) {
cursorManager.removeAllCursors();
}
}

private function annClick(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 3) {
currentlyEditing = evt.currentTarget;
PopUpManager.addPopUp(annotationWindow, this, true);
PopUpManager.centerPopUp(annotationWindow);
annText.text = currentlyEditing.text;
annotationWindow.title = "Edit annotation";
annWidth.maximum = drawArea.width;
annWidth.value = currentlyEditing.width;
aBodyColor = currentlyEditing.getStyle("contentBackgroundColor");
aTextColor = currentlyEditing.getStyle("color");
annBorder.selected = currentlyEditing.getStyle("borderVisible");
annX.value = currentlyEditing.x;
annY.value = currentlyEditing.y;
updateAnnCoordLimits();
baNew.enabled = false;
baEdit.enabled = true;
baDelete.enabled = true;
}
}

private function annDown(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 3) {
currentlyDragging = evt.currentTarget;
dragOffsetX = evt.currentTarget.mouseX;
dragOffsetY = evt.currentTarget.mouseY;
}
}

private function annMove(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 3 && currentlyDragging && !drawHitArea.mouseEnabled) {
cursorManager.setCursor(moveCursor, 2, -10, -10);
drawHitArea.mouseEnabled = true;
drawHitArea.x = -1;
drawHitArea.y = 0;
drawHitArea.width = content.width;
drawHitArea.height = content.height;
}
}

private function updateAnnCoordLimits():void{
annX.maximum = content.width - annWidth.value;
annY.maximum = content.height;
}

private function newFile():void {
PopUpManager.addPopUp(newfileWindow, this, true);
PopUpManager.centerPopUp(newfileWindow);
newfileStack.selectedIndex = 0;
newfileWindow.width = 200;
newfileWindow.height = 100;
}

private function closeNewfile():void {
PopUpManager.removePopUp(newfileWindow);
}

private function blankPicture():void {
content = new Image();
bitmapData = new BitmapData(newWidth.value, newHeight.value, false, newColor.selectedColor);
content.width = newWidth.value;
content.height = newHeight.value;
stackChange();
stack.selectedIndex = 1;
}

private function saveFile():void {
PopUpManager.addPopUp(saveWindow, this, true);
PopUpManager.centerPopUp(saveWindow);
if (selectedFormat == 'jpg') {
radioJPG.selected = true;
}
if (selectedFormat == 'png') {
radioPNG.selected = true;
}
sliderJPG.value = selectedQuality;
}

private function closeSave():void {
PopUpManager.removePopUp(saveWindow);
}

private function changeSelectedFormat(format:String):void {
selectedFormat = format;
preferences.data.selectedFormat = selectedFormat;
preferences.flush();
}

private function changeSelectedQuality():void {
selectedQuality = sliderJPG.value;
preferences.data.selectedQuality = selectedQuality;
preferences.flush();
}

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

if (selectedFormat == "jpg") {
encoder = new JPEGEncoder(selectedQuality);
}
if (selectedFormat == "png") {
encoder = new PNGEncoder();
}

if(crop_rectangle[2]==0 || crop_rectangle[3]==0){
bd = new BitmapData(content.width, content.height, false);
bd.draw(drawArea);
}else {
cropDraw.visible = false;
cropDraw.validateNow();
bd = new BitmapData(crop_rectangle[2] + 1, crop_rectangle[3] + 1, false);
bd.draw(drawArea, new Matrix(1, 0, 0, 1, -crop_rectangle[0], -crop_rectangle[1]));
cropDraw.visible = true;
}

byteArray = encoder.encode(bd);
file = File.documentsDirectory.resolvePath("annotation");
file.browseForSave("Save annotated image");
file.addEventListener(Event.SELECT, saveSelect);

function saveSelect():void {
file.nativePath += "." + selectedFormat;
if(!file.exists){
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(byteArray);
fileStream.close();
} else {
Alert.show("File already exists. Overwrite?", "Hey!", Alert.YES | Alert.NO, null, onCloseOverwrite);
}
}

function onCloseOverwrite(evt:CloseEvent):void {
if (evt.detail == Alert.YES) {
fileStream = new FileStream();
fileStream.open(file, FileMode.WRITE);
fileStream.writeBytes(byteArray);
fileStream.close();
}
}
}

private function crop_mouseDown(mouseX:Number, mouseY:Number):void {
if (!crop_inSelection && !crop_inResize) crop_startDraw(mouseX, mouseY);
if (crop_inSelection && !crop_inResize) crop_startDrag(mouseX - crop_rectangle[0], mouseY - crop_rectangle[1]);
if (crop_inResize) crop_startResize();
}

private function crop_startDraw(mouseX:Number, mouseY:Number):void {
crop_anchorX = mouseX;
crop_anchorY = mouseY;
crop_drawing = true;

crop_rectangle = [crop_anchorX, crop_anchorY, 0, 0];
crop_updateDraw();
}

private function crop_startDrag(offX:Number, offY:Number):void {
crop_offsetX = offX;
crop_offsetY = offY;
crop_dragging = true;
}

private function crop_startResize():void {
crop_resizing = true;
if (crop_resizeDir == "up" || crop_resizeDir == "upLeft" || crop_resizeDir == "upRight") crop_anchorY = crop_rectangle[1] + crop_rectangle[3];
if (crop_resizeDir == "down" || crop_resizeDir == "downLeft" || crop_resizeDir == "downRight") crop_anchorY = crop_rectangle[1];
if (crop_resizeDir == "left" || crop_resizeDir == "upLeft" || crop_resizeDir == "downLeft") crop_anchorX = crop_rectangle[0] + crop_rectangle[2];
if (crop_resizeDir == "right" || crop_resizeDir == "upRight" || crop_resizeDir == "downRight") crop_anchorX = crop_rectangle[0];
}

private function crop_stopDraw():void {
crop_drawing = false;
crop_dragging = false;
crop_resizing = false;
if (new Rectangle(drawArea.x, drawArea.y, content.width, content.height).containsPoint(new Point(canvas.mouseX, canvas.mouseY)) == false && mouseY>=canvas.y){
cursorManager.removeAllCursors();
cursorManager.setCursor(crossCursor, 2, -9, -10);
}
}

private function crop_areaRollOut():void {
if(!crop_drawing && !crop_dragging && !crop_resizing && toolbarStack.selectedIndex == 4){
cursorManager.removeAllCursors();
cursorManager.setCursor(crossCursor, 2, -9, -10);
}
}

private function crop_moveDraw(mouseX:Number, mouseY:Number):void {
if(!crop_drawing && !crop_resizing && !crop_dragging){
cursorManager.removeAllCursors();
crop_inSelection = new Rectangle(crop_rectangle[0], crop_rectangle[1], crop_rectangle[2], crop_rectangle[3]).containsPoint(new Point(mouseX, mouseY));
if (new Rectangle(crop_rectangle[0] - crop_resizeRadius, crop_rectangle[1] - crop_resizeRadius, crop_resizeRadius * 2, crop_resizeRadius * 2).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "upLeft";
crop_inResize = true;
cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10)
}else
if (new Rectangle(crop_rectangle[0] + crop_rectangle[2] - crop_resizeRadius, crop_rectangle[1] - crop_resizeRadius, crop_resizeRadius * 2, crop_resizeRadius * 2).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "upRight";
crop_inResize = true;
cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10)
}else
if (new Rectangle(crop_rectangle[0] - crop_resizeRadius, crop_rectangle[1] + crop_rectangle[3] - crop_resizeRadius, crop_resizeRadius * 2, crop_resizeRadius * 2).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "downLeft";
crop_inResize = true;
cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10)
}else
if (new Rectangle(crop_rectangle[0] + crop_rectangle[2] - crop_resizeRadius, crop_rectangle[1] + crop_rectangle[3] - crop_resizeRadius, crop_resizeRadius * 2, crop_resizeRadius * 2).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "downRight";
crop_inResize = true;
cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10)
}else
if (new Rectangle(crop_rectangle[0], crop_rectangle[1] - crop_resizeRadius, crop_rectangle[2], crop_resizeRadius * 2).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "up";
crop_inResize = true;
cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10)
}else
if (new Rectangle(crop_rectangle[0], crop_rectangle[1] + crop_rectangle[3] - crop_resizeRadius, crop_rectangle[2], crop_resizeRadius * 2).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "down";
crop_inResize = true;
cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10)
}else
if (new Rectangle(crop_rectangle[0] - crop_resizeRadius, crop_rectangle[1], crop_resizeRadius * 2, crop_rectangle[3]).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "left";
crop_inResize = true;
cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10)
}else
if (new Rectangle(crop_rectangle[0] + crop_rectangle[2] - crop_resizeRadius, crop_rectangle[1], crop_resizeRadius * 2, crop_rectangle[3]).containsPoint(new Point(mouseX, mouseY))) {
crop_resizeDir = "right";
crop_inResize = true;
cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10)
}else
{crop_inResize = false; }
if (crop_inSelection && !crop_inResize) cursorManager.setCursor(moveCursor, 2, -9, -10);
if (!crop_inSelection && !crop_inResize) cursorManager.setCursor(crossCursor, 2, -9, -10);
}
if (crop_drawing) {
crop_rectangle = calculateRectValues(mouseX, mouseY, crop_anchorX, crop_anchorY);
crop_updateDraw();
}
if (crop_dragging) {
var newX:Number = mouseX - crop_offsetX;
var newY:Number = mouseY - crop_offsetY;
if (newX >= 0 && newX + crop_rectangle[2] < content.width) crop_rectangle[0] = newX;
if (newX < 0) crop_rectangle[0] = 0;
if (newX + crop_rectangle[2] >= content.width) crop_rectangle[0] = content.width - crop_rectangle[2] - 1;
if (newY >= 0 && newY + crop_rectangle[3] < content.height) crop_rectangle[1] = newY;
if (newY < 0) crop_rectangle[1] = 0;
if (newY + crop_rectangle[3] >= content.height) crop_rectangle[1] = content.height - crop_rectangle[3] - 1;
crop_updateDraw();
}
if (crop_resizing) {
var prevRect:Array = crop_rectangle;
if (crop_resizeDir == "up" && mouseY >= 0 && mouseY < crop_anchorY) crop_rectangle = [prevRect[0], mouseY - 1, prevRect[2], crop_anchorY - mouseY + 1];
if (crop_resizeDir == "down" && mouseY < content.height && mouseY > crop_anchorY) crop_rectangle = [prevRect[0], crop_anchorY, prevRect[2], mouseY - crop_anchorY];
if (crop_resizeDir == "left" && mouseX >= 0 && mouseX < crop_anchorX) crop_rectangle = [mouseX, prevRect[1], crop_anchorX - mouseX, prevRect[3]];
if (crop_resizeDir == "right" && mouseX < content.width && mouseX > crop_anchorX) crop_rectangle = [crop_anchorX, prevRect[1], mouseX - crop_anchorX, prevRect[3]];
if (crop_resizeDir == "upLeft" && mouseY >= 0 && mouseY < crop_anchorY && mouseX >= 0 && mouseX < crop_anchorX) crop_rectangle = [mouseX, mouseY - 1, crop_anchorX - mouseX, crop_anchorY - mouseY + 1];
if (crop_resizeDir == "upRight" && mouseY >= 0 && mouseY < crop_anchorY && mouseX < content.width && mouseX > crop_anchorX) crop_rectangle = [crop_anchorX, mouseY - 1, mouseX - crop_anchorX, crop_anchorY - mouseY + 1];
if (crop_resizeDir == "downLeft" && mouseY < content.height && mouseY > crop_anchorY && mouseX >= 0 && mouseX < crop_anchorX) crop_rectangle = [mouseX, crop_anchorY, crop_anchorX - mouseX, mouseY - crop_anchorY];
if (crop_resizeDir == "downRight" && mouseY < content.height && mouseY > crop_anchorY && mouseX < content.width && mouseX > crop_anchorX) crop_rectangle = [crop_anchorX, crop_anchorY, mouseX - crop_anchorX, mouseY - crop_anchorY];
crop_updateDraw();
}
}

private function crop_updateDraw():void {
cropDraw.graphics.clear();
if(!crop_selectionType){
cropDraw.graphics.lineStyle(1, 0xff0000);
cropDraw.graphics.beginFill(0x00ff00, 0.2);
cropDraw.graphics.drawRect(crop_rectangle[0] - 1, crop_rectangle[1] - 1, crop_rectangle[2] + 2, crop_rectangle[3] + 2);
}
if(crop_selectionType){
cropDraw.graphics.beginFill(0x000000, 0.4);
cropDraw.graphics.lineStyle(1, 0x000000, 0);
cropDraw.graphics.drawRect(0, 0, content.width, crop_rectangle[1]);
cropDraw.graphics.drawRect(0, crop_rectangle[1], crop_rectangle[0], crop_rectangle[3] + 1);
cropDraw.graphics.drawRect(crop_rectangle[0] + crop_rectangle[2] + 1, crop_rectangle[1], content.width - crop_rectangle[0] - crop_rectangle[2] - 1, crop_rectangle[3] + 1);
cropDraw.graphics.drawRect(0, crop_rectangle[1] + crop_rectangle[3] + 1, content.width, content.height - crop_rectangle[1] - crop_rectangle[3] - 1);
}
if (crop_rectangle[2] == 0 || crop_rectangle[3] == 0) cropDraw.graphics.clear();
}

private function crop_deselect():void {
crop_rectangle = [0, 0, 0, 0];
cropDraw.graphics.clear();
}

private function crop_changeSelectionType():void {
crop_selectionType = !crop_selectionType;
preferences.data.selectionType = crop_selectionType;
preferences.flush();
crop_updateDraw();
}

private function openImage():void {
if(toolbarStack.selectedIndex==1){
PopUpManager.addPopUp(imageWindow, this, true);
PopUpManager.centerPopUp(imageWindow);
imageWindow.title = "Add new image";
biNew.enabled = false;
biUpdate.enabled = false;
biDelete.enabled = false;
iPath.text = "";
iPreview.source = null;
iWidth.value = 10;
iHeight.value = 10;
iX.value = 0;
iY.value = 0;
updateImgLimits();
}
}

private function closeImage():void {
PopUpManager.removePopUp(imageWindow);
}

private function imageBrowse():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, fileSel);

function fileSel(evt:Event):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComp);
loader.load(new URLRequest(file.url));
}

function loadComp(evt:Event):void {
iPreview.source = evt.target.content;
iPreviewHidden.source = evt.target.content;
iPath.text = file.nativePath;
updatePreviewImage();
}
}

private function updatePreviewImage():void {
var ratio:Number;
smoothImage(iPreview);
iPreviewHidden.validateNow();
iWidth.value = iPreviewHidden.contentWidth;
iHeight.value = iPreviewHidden.contentHeight;
if (iWidth.value > content.width) {
ratio = iHeight.value / iWidth.value;
iWidth.value = content.width;
iHeight.value = content.width * ratio;
}
if (iHeight.value > content.height) {
ratio = iWidth.value / iHeight.value;
iHeight.value = content.height;
iWidth.value = content.height * ratio;
}
imgOriginal.text = "Original size: " + iPreviewHidden.contentWidth + "x" + iPreviewHidden.contentHeight;
if (!biUpdate.enabled) biNew.enabled = true;
}

private function smoothImage(target:Image):void{
var bitmap:Bitmap = ((target as Image).content as Bitmap);
if (bitmap != null) {
bitmap.smoothing = true;
}
}

private function addImage():void {
var newImg:Image = new Image();
newImg.source = new Bitmap(Bitmap(iPreview.content).bitmapData);
newImg.toolTip = iPath.text;
newImg.maintainAspectRatio = false;
newImg.scaleContent = true;
newImg.width = iWidth.value;
newImg.height = iHeight.value;
images.addElement(newImg);
smoothImage(newImg);
newImg.validateNow();
newImg.x = iX.value;
newImg.y = iY.value;
newImg.doubleClickEnabled = true;
newImg.addEventListener(MouseEvent.ROLL_OVER, imgOver);
newImg.addEventListener(MouseEvent.ROLL_OUT, imgOut);
newImg.addEventListener(MouseEvent.DOUBLE_CLICK, imgClick);
newImg.addEventListener(MouseEvent.MOUSE_DOWN, imgDown);
newImg.addEventListener(MouseEvent.MOUSE_MOVE, imgMove);
newImg.buttonMode = true;
}

private function editImage():void {
var editImg:* = currentlyEditing;
editImg.source = new Bitmap(Bitmap(iPreview.content).bitmapData);
editImg.toolTip = iPath.text;
editImg.width = iWidth.value;
editImg.height = iHeight.value;
editImg.x = iX.value;
editImg.y = iY.value;
updateImgLimits();
}

private function deleteImage():void {
images.removeElement(currentlyEditing);
}

private function imgOver(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 1) {
evt.target.alpha = 0.7;
currentImage = evt.currentTarget;
createAnchors();
enableResize();
positionResize();
}
}

private function imgOut(evt:MouseEvent):void{
evt.target.alpha = 1;
if (toolbarStack.selectedIndex == 1 && currentlyDragging == null) {
cursorManager.removeAllCursors();
}
}

private function imgClick(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 1) {
currentlyEditing = evt.currentTarget;
PopUpManager.addPopUp(imageWindow, this, true);
PopUpManager.centerPopUp(imageWindow);
imageWindow.title = "Edit image";
iPath.text = evt.currentTarget.toolTip;
iPreview.source = new Bitmap(Bitmap(evt.currentTarget.content).bitmapData);
iWidth.value = evt.currentTarget.width;
iHeight.value = evt.currentTarget.height;
iX.value = evt.currentTarget.x;
iY.value = evt.currentTarget.y;
iX.maximum = content.width;
iY.maximum = content.height;
biNew.enabled = false;
biUpdate.enabled = true;
biDelete.enabled = true;
}
}

private function imgDown(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 1) {
currentlyDragging = evt.currentTarget;
dragOffsetX = evt.currentTarget.mouseX;
dragOffsetY = evt.currentTarget.mouseY;
}
}

private function imgMove(evt:MouseEvent):void {
if (toolbarStack.selectedIndex == 1 && currentlyDragging && !drawHitArea.mouseEnabled) {
images.setElementIndex(currentlyDragging, images.numElements - 1);
cursorManager.setCursor(moveCursor, 2, -10, -10);
drawHitArea.mouseEnabled = true;
drawHitArea.x = -1;
drawHitArea.y = 0;
drawHitArea.width = content.width;
drawHitArea.height = content.height;
}
}

private function updateImgLimits():void {
iX.maximum = content.width - iWidth.value;
iY.maximum = content.height - iHeight.value;
iWidth.maximum = content.width;
iHeight.maximum = content.height;
}

private function createAnchors():void {
if (imageAnchors == null) {
imageAnchors = [];
for (var i:int = 0; i < 8; i++) {
var newAnchor:SpriteVisualElement = new SpriteVisualElement();
newAnchor.width = 10;
newAnchor.height = 10;
newAnchor.graphics.lineStyle(2, 0x000000);
newAnchor.graphics.beginFill(0xffffff);
newAnchor.graphics.drawRect(0, 0, 10, 10);
anchors.addElement(newAnchor);
imageAnchors.push(newAnchor);
newAnchor.addEventListener(MouseEvent.ROLL_OVER, anchorOver);
newAnchor.addEventListener(MouseEvent.ROLL_OUT, anchorOut);
newAnchor.addEventListener(MouseEvent.MOUSE_DOWN, anchorDown);
}
}
/* Layout:
0 1 2
3 - 4
5 6 7*/
}

private function anchorOver(evt:MouseEvent):void {
if(anchors.alpha>0){
switch(evt.currentTarget) {
case imageAnchors[0]: case imageAnchors[7]: cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10); break;
case imageAnchors[2]: case imageAnchors[5]: cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10); break;
case imageAnchors[1]: case imageAnchors[6]: cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10); break;
case imageAnchors[3]: case imageAnchors[4]: cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10); break;
}
}
}

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

private function anchorDown(evt:MouseEvent):void {
currentRatio = currentImage.width / currentImage.height;
img_rectangle = [currentImage.x, currentImage.y, currentImage.width, currentImage.height];
switch(evt.currentTarget) {
case imageAnchors[0]: img_currentDir = "upLeft"; img_anchorY = img_rectangle[1] + img_rectangle[3]; img_anchorX = img_rectangle[0] + img_rectangle[2]; break;
case imageAnchors[1]: img_currentDir = "up"; img_anchorY = img_rectangle[1] + img_rectangle[3]; break;
case imageAnchors[2]: img_currentDir = "upRight"; img_anchorY = img_rectangle[1] + img_rectangle[3]; img_anchorX = img_rectangle[0]; break;
case imageAnchors[3]: img_currentDir = "left"; img_anchorX = img_rectangle[0] + img_rectangle[2]; break;
case imageAnchors[4]: img_currentDir = "right"; img_anchorX = img_rectangle[0]; break;
case imageAnchors[5]: img_currentDir = "downLeft"; img_anchorY = img_rectangle[1]; img_anchorX = img_rectangle[0] + img_rectangle[2]; break;
case imageAnchors[6]: img_currentDir = "down"; img_anchorY = img_rectangle[1]; break;
case imageAnchors[7]: img_currentDir = "downRight"; img_anchorY = img_rectangle[1]; img_anchorX = img_rectangle[0]; break;
}
img_resizing = true;
drawHitArea.mouseEnabled = true;
drawHitArea.width = content.width;
drawHitArea.height = content.height;
drawHitArea.x = -1;
drawHitArea.y = 1;
}

private function imageResize():void {
if (img_resizing) {
cursorManager.removeAllCursors();
var prevRect:Array = img_rectangle;
var mouseX:Number = drawArea.mouseX;
var mouseY:Number = drawArea.mouseY;
if (img_currentDir == "up" && mouseY >= 0 && mouseY < img_anchorY) {
img_rectangle = [prevRect[0], mouseY - 1, prevRect[2], img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10);
}
if (img_currentDir == "down" && mouseY < content.height && mouseY > img_anchorY) { 
img_rectangle = [prevRect[0], img_anchorY, prevRect[2], mouseY - img_anchorY]; cursorManager.setCursor(resizeVerticalCursor, 2, -9, -10);
}
if (img_currentDir == "left" && mouseX >= 0 && mouseX < img_anchorX) { 
img_rectangle = [mouseX, prevRect[1], img_anchorX - mouseX, prevRect[3]]; cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10);
}
if (img_currentDir == "right" && mouseX < content.width && mouseX > img_anchorX) { 
img_rectangle = [img_anchorX, prevRect[1], mouseX - img_anchorX, prevRect[3]]; cursorManager.setCursor(resizeHorizontalCursor, 2, -9, -10);
}
if (img_currentDir == "upLeft" && mouseY >= 0 && mouseY < img_anchorY && mouseX >= 0 && mouseX < img_anchorX) { 
if (!isShift) img_rectangle = [mouseX, mouseY - 1, img_anchorX - mouseX, img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
if (isShift) img_rectangle = [mouseX, img_anchorY - (img_anchorX - mouseX)/currentRatio, img_anchorX - mouseX, (img_anchorX - mouseX)/currentRatio]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
}
if (img_currentDir == "upRight" && mouseY >= 0 && mouseY < img_anchorY && mouseX < content.width && mouseX > img_anchorX) { 
if (!isShift) img_rectangle = [img_anchorX, mouseY - 1, mouseX - img_anchorX, img_anchorY - mouseY + 1]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
if (isShift) img_rectangle = [img_anchorX, img_anchorY - (mouseX - img_anchorX)/currentRatio, mouseX - img_anchorX, (mouseX - img_anchorX)/currentRatio]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
}
if (img_currentDir == "downLeft" && mouseY < content.height && mouseY > img_anchorY && mouseX >= 0 && mouseX < img_anchorX) { 
if (!isShift) img_rectangle = [mouseX, img_anchorY, img_anchorX - mouseX, mouseY - img_anchorY]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
if (isShift) img_rectangle = [mouseX, img_anchorY, img_anchorX - mouseX, (img_anchorX - mouseX)/currentRatio]; cursorManager.setCursor(resizeDiag1Cursor, 2, -9, -10);
}
if (img_currentDir == "downRight" && mouseY < content.height && mouseY > img_anchorY && mouseX < content.width && mouseX > img_anchorX) { 
if (!isShift) img_rectangle = [img_anchorX, img_anchorY, mouseX - img_anchorX, mouseY - img_anchorY]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
if (isShift) img_rectangle = [img_anchorX, img_anchorY, mouseX - img_anchorX, (mouseX - img_anchorX)/currentRatio]; cursorManager.setCursor(resizeDiag2Cursor, 2, -9, -10);
}

if(img_rectangle[0]>=0 && img_rectangle[1]>=0 && img_rectangle[2] + img_rectangle[0]<=content.width && img_rectangle[3] + img_rectangle[1]<=content.height){
updateImage();
positionResize();
}
}
}

private function updateImage():void {
currentImage.x = img_rectangle[0];
currentImage.y = img_rectangle[1];
currentImage.width = img_rectangle[2];
currentImage.height = img_rectangle[3];
}

private function enableResize():void {
anchors.alpha = 0.8;
anchors.mouseEnabled = true;
anchors.mouseChildren = true;
}

private function disableResize():void {
if(toolbarStack.selectedIndex==1 && !img_resizing){
anchors.alpha = 0;
anchors.mouseEnabled = false;
anchors.mouseChildren = false;
}
}

private function positionResize():void {
var cX:Number = currentImage.x;
var cY:Number = currentImage.y;
var cW:Number = currentImage.width;
var cH:Number = currentImage.height;
imageAnchors[0].x = cX - 5;
imageAnchors[0].y = cY - 5;
imageAnchors[1].x = cX + cW/2 - 5;
imageAnchors[1].y = cY - 5;
imageAnchors[2].x = cX + cW - 5;
imageAnchors[2].y = cY - 5;
imageAnchors[3].x = cX - 5;
imageAnchors[3].y = cY + cH/2 - 5;
imageAnchors[4].x = cX + cW - 5;
imageAnchors[4].y = cY + cH/2 - 5;
imageAnchors[5].x = cX - 5;
imageAnchors[5].y = cY + cH - 5;
imageAnchors[6].x = cX + cW/2 - 5;
imageAnchors[6].y = cY + cH - 5;
imageAnchors[7].x = cX + cW - 5;
imageAnchors[7].y = cY + cH - 5;
}
]]>
</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')"/>
<fx:Object icon="@Embed('../lib/ic_arrow.png')"/>
<fx:Object icon="@Embed('../lib/ic_eyedropper.png')"/>
</mx:ArrayCollection>
<s:TitleWindow id="imageWindow" width="450" height="370" close="closeImage();" >
<s:VGroup width="500" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
<s:HGroup width="100%">
<s:TextInput editable="false" width="350" id="iPath" />
<s:Button label="Browse.." click="imageBrowse();" />
</s:HGroup>
<mx:Box backgroundColor="#dddddd" width="430" height="180" verticalAlign="middle" horizontalAlign="center" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Image id="iPreview" scaleContent="true" maxWidth="430" maxHeight="180" maintainAspectRatio="true" smoothBitmapContent="true"/>
</mx:Box>
<s:HGroup verticalAlign="middle">
<s:Label>Width:</s:Label>
<s:NumericStepper minimum="10" maximum="2000" id="iWidth" change="updateImgLimits();" />
<s:Label>Height:</s:Label>
<s:NumericStepper minimum="10" maximum="2000" id="iHeight" change="updateImgLimits();" />
<s:Label id="imgOriginal" />
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label>Coordinates: X</s:Label>
<s:NumericStepper minimum="0" id="iX" change="updateImgLimits();" />
<s:Label>Y</s:Label>
<s:NumericStepper minimum="0" id="iY" change="updateImgLimits();" />
</s:HGroup>
<s:HGroup>
<s:Button label="Add image" click="addImage(); closeImage();" id="biNew" />
<s:Button label="Update image" click="editImage(); closeImage();" id="biUpdate" />
<s:Button label="Delete image" click="deleteImage(); closeImage();" id="biDelete" />
</s:HGroup>
<mx:Image id="iPreviewHidden" scaleContent="false" visible="false" maintainAspectRatio="true" smoothBitmapContent="true"/>
</s:VGroup>
</s:TitleWindow>
<s:TitleWindow id="saveWindow" title="Save picture" width="200" height="120" close="closeSave();" >
<s:VGroup width="200" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
<s:HGroup verticalAlign="middle">
<s:Label>Export format:</s:Label>
<s:RadioButton id="radioJPG" label="JPG" groupName="saveFormat" change="changeSelectedFormat('jpg');" /> 
<s:RadioButton id="radioPNG" label="PNG" groupName="saveFormat" change="changeSelectedFormat('png');" /> 
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label enabled="{radioJPG.selected}">JPG quality:</s:Label>
<s:HSlider id="sliderJPG" minimum="1" maximum="100" enabled="{radioJPG.selected}" change="changeSelectedQuality();" />
</s:HGroup>
<s:Button label="Export file" width="100%" click="closeSave(); startExport();" />
</s:VGroup>
</s:TitleWindow>
<s:TitleWindow id="newfileWindow" title="Start new..." width="200" height="100" close="closeNewfile();" >
<mx:ViewStack id="newfileStack">
<s:NavigatorContent>
<s:VGroup width="200" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
<s:Button label="Import new picture" width="100%" click="closeNewfile(); importPicture();" />
<s:Button label="Create blank page" width="100%" click="newfileStack.selectedIndex = 1; newfileWindow.height = 160;" />
</s:VGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="200" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
<s:HGroup verticalAlign="middle">
<s:Label>Width:</s:Label>
<s:NumericStepper minimum="10" maximum="2000" value="400" id="newWidth" />
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label>Height:</s:Label>
<s:NumericStepper minimum="10" maximum="2000" value="300" id="newHeight" />
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label>Background color:</s:Label>
<mx:ColorPicker id="newColor" selectedColor="0xffffff" />
</s:HGroup>
<s:Button label="Create blank" width="100%" click="closeNewfile(); blankPicture();" />
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>
</s:TitleWindow>
<s:TitleWindow id="annotationWindow" width="500" height="340" close="closeAnnotation();" >
<s:VGroup width="500" paddingTop="10" paddingLeft="10" paddingRight="10" paddingBottom="10">
<s:Label>Text:</s:Label>
<s:TextArea width="100%" height="100" id="annText"/>
<s:HGroup verticalAlign="middle">
<s:Label>Rectangle color:</s:Label>
<mx:ColorPicker selectedColor="@{aBodyColor}" toolTip="Annotation body color" />
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label>Text color:</s:Label>
<mx:ColorPicker selectedColor="@{aTextColor}" toolTip="Annotation text color" />
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label>Annotation width:</s:Label>
<s:NumericStepper minimum="10" id="annWidth" change="updateAnnCoordLimits();" />
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:Label>Coordinates: X</s:Label>
<s:NumericStepper minimum="0" id="annX"/>
<s:Label>Y</s:Label>
<s:NumericStepper minimum="0" id="annY" />
</s:HGroup>
<s:HGroup verticalAlign="middle">
<s:CheckBox label="Enable border?" id="annBorder" />
</s:HGroup>
<s:HGroup>
<s:Button label="Create annotation" click="addAnnotation(); closeAnnotation();" id="baNew" />
<s:Button label="Edit annotation" click="editAnnotation(); closeAnnotation();" id="baEdit" />
<s:Button label="Delete annotation" click="deleteAnnotation(); closeAnnotation();" id="baDelete" />
</s:HGroup>
</s:VGroup>
</s:TitleWindow>
</fx:Declarations>

<s:VGroup width="100%" height="100%" gap="0">
<mx:HBox backgroundColor="#ccccdd" width="100%" height="60">
<s:VGroup gap="0" width="100%" height="100%">
<s:HGroup gap="0">
<custom:IconButton icon="@Embed('../lib/new.png')" toolTip="New" enabled="{buttonsEnabled}" buttonMode="true" click="newFile();" />
<custom:IconButton icon="@Embed('../lib/images.png')" toolTip="Move" enabled="{buttonsEnabled}" buttonMode="true" click="toolbarStack.selectedIndex=1;" />
<custom:IconButton icon="@Embed('../lib/draw.png')" toolTip="Draw" enabled="{buttonsEnabled}" buttonMode="true" click="toolbarStack.selectedIndex=2;" />
<custom:IconButton icon="@Embed('../lib/bubble.png')" toolTip="Annotation" enabled="{buttonsEnabled}" buttonMode="true" click="toolbarStack.selectedIndex=3;" />
<custom:IconButton icon="@Embed('../lib/cut.png')" toolTip="Cut" enabled="{buttonsEnabled}" buttonMode="true" click="toolbarStack.selectedIndex=4;" />
<custom:IconButton id="saveBtn" icon="@Embed('../lib/save.png')" toolTip="Save" enabled="{buttonsEnabled}" buttonMode="true" click="saveFile();" />
<mx:ViewStack id="toolbarStack" width="100%" height="100%" change="toolbarChange();">
<s:NavigatorContent>

</s:NavigatorContent>
<s:NavigatorContent>
<s:VGroup width="100%" height="44" top="4">
<s:Label fontSize="18" color="#333333">Selected: Images</s:Label>
<s:HGroup verticalAlign="middle">
<s:Label>Move and resize images with mouse, double-click to edit.</s:Label>
<custom:SmallButton label="Add a new image" icon="@Embed('../lib/bubble_add.png')" click="openImage();"/>
</s:HGroup>
</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="130" id="drawTools" />
<mx:ColorPicker selectedColor="@{lineColor}" change="updateLineExample();" />
<mx:Slider minimum="1" maximum="10" change="updateLineExample();" value="@{lineThickness}" width="80" liveDragging="true"/>
<s:SpriteVisualElement width="40" height="20" id="lineExample"/>
<s:Button click="drawSprite.graphics.clear();" label="Clear all" />
</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 verticalAlign="middle">
<s:Label>Move annotations by dragging them, double-click to edit.</s:Label>
<custom:SmallButton label="Add a new annotation" icon="@Embed('../lib/bubble_add.png')" click="openAnnotation();"/>
</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 verticalAlign="middle">
<s:Label>Select an area to crop.</s:Label>
<custom:SmallButton label="Deselect" icon="@Embed('../lib/cross.png')" click="crop_deselect();"/>
<custom:SmallButton label="Change selection display" icon="@Embed('../lib/shape_handles.png')" click="crop_changeSelectionType();"/>
</s:HGroup>
</s:VGroup>
</s:NavigatorContent>
</mx:ViewStack>
</s:HGroup>
<mx:Box backgroundColor="#bbbbcc" width="100%" height="100%">
<s:Group width="100%" height="100%">
<mx:Box backgroundColor="#ffffff" width="52" height="100%" left="{52 * toolbarStack.selectedIndex}" visible="{buttonsEnabled}" />
</s:Group>
</mx:Box>
</s:VGroup>
</mx:HBox>
<mx:Canvas width="100%" height="100%" horizontalScrollPolicy="on" verticalScrollPolicy="on" rollOver="canvasOver();" rollOut="canvasOut();" id="canvas">
<mx:Box backgroundColor="#eeeeee" width="100%" height="100%" verticalAlign="middle" horizontalAlign="center" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Box id="drawArea" backgroundColor="#ffffff" width="400" height="200" horizontalScrollPolicy="off" verticalScrollPolicy="off" rollOut="crop_areaRollOut();">
<mx:ViewStack id="stack" change="stackChange();">
<s:NavigatorContent>
<s:HGroup gap="0">
<custom:BigButton icon="@Embed('../lib/folder.png')" subtext="Import picture" toolTip="Open file" enabled="true" buttonMode="true" bWidth="200" bHeight="200" click="importPicture();" />
<custom:BigButton icon="@Embed('../lib/blank.png')" subtext="Create blank" toolTip="Blank page" enabled="true" buttonMode="true" bWidth="200" bHeight="200" click="newFile(); newfileStack.selectedIndex = 1; newfileWindow.height = 160;" />
</s:HGroup>
</s:NavigatorContent>
<s:NavigatorContent>
<mx:Image id="imgHolder" />
<s:Group id="drawGroup">
<s:Group id="drawSprite" />
<s:Group id="tempSprite" />
</s:Group>
<mx:Box id="annHitArea" alpha="0" backgroundColor="#000000" click="openAnnotation(drawArea.mouseX, drawArea.mouseY);" rollOver="disableResize();"  />
<s:Group id="images" />
<s:Group id="annotations" />
<s:Group id="cropDraw" mouseEnabled="false" />
<s:Group id="anchors"/>
<mx:Box id="drawHitArea" alpha="0" backgroundColor="#000000" mouseDown="drawDown();" mouseMove="drawMove();"/>
</s:NavigatorContent>
</mx:ViewStack>
</mx:Box>
</mx:Box>
</mx:Canvas>
</s:VGroup>

</s:WindowedApplication>

Thanks for reading!

No comments:

Post a Comment