Saturday, March 24, 2012

Creating a Flex AIR Annotator app: Part 34

In this tutorial we continue working on resizing the images. Specifically, we improve the image resizing anchors behaviour.

First of all, go to the createAnchors() function and change the newAnchor object's class from Group to SpriteVisualElement. Add 2 mouse event listeners to it - listen for roll_over and roll_out events, set handlers to anchorOver and anchorOut.

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);
}
}
/* Layout:
0 1 2
3 - 4
5 6 7*/
}

Now we're going to update the enableResize() and disableResize() functions. Set mouseChildren to true/false in them, and also add a conditional in the second function which checks if the currently selected tool has an index of 1 (the image tool):

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

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

We did this because we are not going to call disableResize from imgOut() anymore, but we'll listen to rollOut events of each annotation (annOver() handler) and the annHitArea.

So go to imgOut() function and remove that line that calls disableResize():

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

Add it in annOver():

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

And find the annHitArea box to add a rollOut event listener with the handler set to disableResize():

<mx:Box id="annHitArea" alpha="0" backgroundColor="#000000" click="openAnnotation(drawArea.mouseX, drawArea.mouseY);" rollOver="disableResize();"  />

Now let's create these anchorOver() and anchorOut() functions. The first one checks if the anchors are visible, and if they are, it checks which image anchor the user is currently hovering over to set the cursor to the approporiate resize cursor:

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;
}
}
}

The second function just removes all cursors.

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

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: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 preferences:SharedObject = SharedObject.getLocal("kirannotatorPreferences");
private var selectedFormat:String;
private var selectedQuality:int;

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 {
// 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 {
// 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) {
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);
}
}
/* 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 enableResize():void {
anchors.alpha = 0.8;
anchors.mouseEnabled = true;
anchors.mouseChildren = true;
}

private function disableResize():void {
if(toolbarStack.selectedIndex==1){
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