DAN ZEN EXPO - CODE EXHIBIT - HIPSTER!
package {	
	
	import com.danzen.interfaces.Cropper;
	import com.danzen.interfaces.ImageSend;
	import com.danzen.interfaces.MobileCamRoll;
	import com.danzen.interfaces.Rotator;
	import com.danzen.interfaces.TextScroll;
	import com.greensock.TweenLite;
	import com.greensock.easing.*;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageAspectRatio;
	import flash.display.StageOrientation;
	import flash.display.StageScaleMode;
	import flash.events.*;
	import flash.events.TransformGestureEvent;
	import flash.filters.*;
	import flash.geom.Matrix;
	import flash.geom.Rectangle;
	import flash.net.URLRequest;
	import flash.net.navigateToURL;
	import flash.sensors.Accelerometer;
	import flash.ui.Multitouch;
	import flash.ui.MultitouchInputMode;
	import flash.utils.Timer;
	
	public class Hipster extends Sprite	{
		
		private var localCheck:Boolean = false; 	
		//private var platform:String = "blackberry";
		private var platform:String = "all";
		
		private var photo:MobileCamRoll;
		private var assets:MovieClip;
		private var sW:Number;
		private var sH:Number;
		private var scale:Number;	
		private var rotator:Rotator;
		private var cropper:Cropper;
		private var rotateTimer:Timer;
		private var myData:Data;
		
		// pages
		private var splash:MovieClip;
		private var home:MovieClip;
		private var hunt:MovieClip;
		private var post:MovieClip;
		private var comment:MovieClip;	
		private var rotate:MovieClip;
		private var crop:MovieClip;
		private var tag:MovieClip;
		private var full:MovieClip;
		private var win:MovieClip;
		private var account:MovieClip;
		private var search:MovieClip;
		private var top:MovieClip;
		private var pageList:Array = ["splash", "home", "hunt", "post", "tag", "full", "win", "rotate", "crop", "comment", "account", "search", "top"];
		private var picNum:Number = 0;
		private var currentPic:Number;
		
		// splash page
		private var touchyTweenCheck:Boolean = true;
		
		// tag page
		private var imageHeight:Number;
		private var urlRoot:String = "http://s3.amazonaws.com/hipstermobi/";
		private var nextLoader:Loader;		
		private var nextPic:MovieClip;
		private var nextDirection:String;
		private var deepBreath:MovieClip;
		private var malfunction:MovieClip;
		private var gutter:Number = 40;
		private var orientation:String = "portrait";
		private var thanksTimer:Timer;
		private var infoScroller:TextScroll;
		private var rankScroller:TextScroll;
		private var messageCheck:Boolean = false;
				
		// full page
		private var fullStartScale:Number;
		private var fullTimer:Timer;
		private var fullDownStartTime:Number;
		
		// account page
		private var lastAccount:Object = new Object();
		
		// comment page
		private var commentTimer:Timer;		
		
		// win page
		private var currentWin:Number;
		private var winnerTopic:String;		
		
		// search page
		private var searchCheck:Boolean = false;
		private var currentSearch:Number;
		private var resultsTimer:Timer;
				
		public function Hipster() {
			trace ("hi from Hipster - local: " + localCheck);	
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;
			stage.autoOrients = false;
			addEventListener(Event.ADDED_TO_STAGE, init);			
		}
		private function init(e:Event):void {
			initScale();
			assets = new Assets();
			for (var i:uint=0; i 0) {
					comment.image.removeChildAt(0);
				}
				comment.image.addChild(new Bitmap(bm));
				fitImage(comment.image, 0, comment.imageBacking.y, sW/scale, comment.imageBacking.height);
			}
			
			//-------------- FULL
			if (clip.to == full) {				
				doFull();				
			}			
		}			
		
		private function doAd(e:MouseEvent):void {
			if (platform == "blackberry") {
				navigateToURL(new URLRequest("http://hangy.mobi"));
			} else {
				navigateToURL(new URLRequest("http://touchy.mobi"));
			}				
		}
		
		private function goSplash(e:MouseEvent):void {
			removeChildAt(0);
			addChild(splash);
		}		
		
		//////////////////////////  TAG PAGE  ////////////////////////////
		
		private function prepareTagPage():void {
			Multitouch.inputMode = MultitouchInputMode.GESTURE;
			if (tag.contains(tag.info)) {
				tag.removeChild(tag.info);
				tag.addChild(tag.tags);
			}
			
			if (tag.contains(tag.rank)) {tag.removeChild(tag.rank);}
			if (tag.contains(tag.rankInfo)) {tag.removeChild(tag.rankInfo);}
			if (tag.contains(tag.winBut)) {
				tag.removeChild(tag.winBut);
				tag.removeChild(tag.headerWin);
				tag.addChildAt(tag.tagBut, 0);
				tag.addChild(tag.tags);
				tag.addChild(tag.header);
			}
			
			if (myData.pics.length > 0) {				
				// check to see if there is a pic loaded
				// if not then load the pic and store the current pic
				// if there is then just load the tag page
				var num:Number = myData.pics[picNum];
				if (num != currentPic || tag.image.contains(deepBreath)) {
					currentPic = num;
					var myLoader:Loader = new Loader();
					myData.getInfo(String(currentPic));
					myLoader.load(new URLRequest(urlRoot + currentPic + ".jpg"));
					myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, tagImageReady);	
					myLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, tagImageError);
				}
			} else {
				showMalfunction();					
			}	
		}
		
		private function doAbout(e:MouseEvent):void {			
			navigateToURL(new URLRequest("http://hipster.mobi/hipster/about.html"));
		}
		
		private function doTag(e:MouseEvent):void {
			trace("do Tag");
			tag.addChild(tag.tags);
			tag.removeChild(tag.info);
		}
				
		private function doInfo(e:MouseEvent):void {
			trace("do Info");
			trace (myData.info.screen);	
			if (tag.contains(tag.tags)) {
				tag.addChild(tag.info);
				tag.removeChild(tag.tags);
			} else {
				tag.addChild(tag.rankInfo);
				tag.removeChild(tag.rank);
			}
			setInfo();			
		}		

		private function getInfo(e:Event):void {
			setInfo();
		}
		
		private function setInfo():void {
			var root:MovieClip;
			var scroller:TextScroll;
			if (tag.contains(tag.info)) {
				root = tag.info;
				scroller = infoScroller;
			} else {
				root = tag.rankInfo;
				scroller = rankScroller;
			}
			if (!myData.info.screen) {return;} // I may have deleted an entry while in their memory
			root.hunterText.text = myData.info.screen;
			root.myText.text = myData.info.comment;
			if (root.contains(root.facebook)) {root.removeChild(root.facebook);}
			if (root.contains(root.flickr)) {root.removeChild(root.flickr);}
			if (root.contains(root.twitter)) {root.removeChild(root.twitter);}
			if (myData.info.facebook && myData.info.facebook != "") {
				root.addChild(root.facebook);	
			}
			if (myData.info.flickr && myData.info.flickr != "") {
				root.addChild(root.flickr);	
			}
			if (myData.info.twitter && myData.info.twitter != "") {
				root.addChild(root.twitter);	
			}			
			if (myData.info.tags && myData.info.tags.length > 0) {
				root.myText.appendText("\n———————————");
				for (var i:uint=0; i 0) {
				MovieClip(full.image.inner).removeChildAt(0);
			}
			var newImage:Bitmap = new Bitmap(bmf);
			full.image.inner.addChild(newImage);				
			
			stage.autoOrients = true;
			
			if (platform == "blackberry") {
				accel.addEventListener(AccelerometerEvent.UPDATE, accelUpdate);
			}
			
			
			Multitouch.inputMode = MultitouchInputMode.GESTURE;
			// meld is the information screen that disappears after a certain time
			full.addChild(full.meld);
			full.meld.y = (sH/scale - full.meld.backing.box.height)/2-20;
			full.meld.alpha = 1;
			TweenLite.to(full.meld, .6, {delay:3.5, alpha:0, ease:Quad.easeInOut, onComplete:meldDone});
			// for full we scale a centered outer clip (full.image)
			// and we pan a scaled inner clip (full.image.inner)
			// so we want to center the outer and initially scale the inner
			// make sure the outer clip's scale is reset to start
			full.image.scaleX = full.image.scaleY = 1;
			fitImage(full.image.inner, 0, 0, sW/scale, sH/scale);
			full.image.x = sW / 2 / scale;
			full.image.y = sH / 2 / scale;
			full.image.inner.x = -full.image.inner.width/2;
			full.image.inner.y = -full.image.inner.height/2;
		}
		
		private var lastOrientation:String = "vertical";
		private var orientTimer:Timer;
		private var orientCheck:Boolean = true;
		
		private function accelUpdate(e:AccelerometerEvent):void {	
			if (orientation == "portrait") {
				if( e.accelerationX > 0.5 || e.accelerationX < -0.5 ) {
					orientation = "landscape";				
				} else if( e.accelerationY > 0.5 || e.accelerationY < -0.5 ) {
					orientation = "portrait";				
				} 
			} else {
				if( e.accelerationX > 0.5 || e.accelerationX < -0.5 ) {
					orientation = "portrait";				
				} else if( e.accelerationY > 0.5 || e.accelerationY < -0.5 ) {
					orientation = "landscape";				
				} 				
			}
			if (lastOrientation == orientation) {return;}			
			if (!orientCheck) {return;}
			orientCheck = false;
			orientTimer.reset();
			orientTimer.start();
			lastOrientation = orientation;
			if (orientation == "landscape") {
				trace ("landscape");
				stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
				landscapeView();
			} else {
				trace ("portrait");
				stage.setAspectRatio(StageAspectRatio.PORTRAIT);
				portraitView();
			}			
		}
		
		private function setOrientCheck(e:TimerEvent):void {
			orientCheck = true;
		}
		
		private function doZoom(e:TransformGestureEvent):void {
			// multitouch method for full screen pic zoom (on tag page)
			if (e.phase == GesturePhase.BEGIN) {				
				full.image.removeEventListener(MouseEvent.MOUSE_DOWN, doDown);				
				full.image.stopDrag();				
			}
			var newScale:Number = (e.scaleX + e.scaleY) / 2;
			e.target.scaleX *= newScale;
			e.target.scaleY *= newScale;
			e.target.scaleX = Math.max(e.target.scaleX, 1);
			e.target.scaleY = Math.max(e.target.scaleY, 1);
			e.target.scaleX = Math.min(e.target.scaleX, 6);
			e.target.scaleY = Math.min(e.target.scaleY, 6);
			if(e.phase == GesturePhase.END) {				
				full.image.addEventListener(MouseEvent.MOUSE_DOWN, doDown);				
			}
		}
		
		private function doDown(e:MouseEvent):void {
			var d:Date = new Date();
			fullDownStartTime = d.getTime();
			stage.addEventListener(MouseEvent.MOUSE_UP, doUp);	
			stage.addEventListener(MouseEvent.MOUSE_MOVE, doMove);	
			full.image.offsetX = full.image.mouseX - full.image.inner.x;
			full.image.offsetY = full.image.mouseY - full.image.inner.y;
		}
		
		private function doMove(e:MouseEvent):void {	
			full.image.inner.x = full.image.mouseX - full.image.offsetX;
			full.image.inner.y = full.image.mouseY - full.image.offsetY;			
			// don't let any of the four edges go past center which is 0,0
			full.image.inner.x = Math.min(full.image.inner.x, 0);
			full.image.inner.y = Math.min(full.image.inner.y, 0);
			full.image.inner.x = Math.max(full.image.inner.x, -full.image.inner.width);
			full.image.inner.y = Math.max(full.image.inner.y, -full.image.inner.height);
		}
		
		private function doUp(e:MouseEvent):void {			
			stage.removeEventListener(MouseEvent.MOUSE_UP, doUp);	
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, doMove);
			full.image.stopDrag();			
		}			
		
		private function fullResize(e:MouseEvent):void {
			var d:Date = new Date();
			if (d.getTime() - fullDownStartTime > 300) {return;}			
			fullTimer.start();
		}
		
		private function fullExit(e:MouseEvent):void {
			fullTimer.stop();
			removeChildAt(0);
			addChild(tag);
			stage.autoOrients = false;	
			if (platform == "blackberry") {				
				accel.removeEventListener(AccelerometerEvent.UPDATE, accelUpdate);				
				stage.setAspectRatio(StageAspectRatio.PORTRAIT);
			} else {
				stage.setOrientation(StageOrientation.DEFAULT);
			}
			Multitouch.inputMode = MultitouchInputMode.GESTURE;
		}
		
		private function singleClickHandler(e:TimerEvent):void {		
			full.image.scaleX = full.image.scaleY = 1;			
			if (orientation == "portrait") {
				fitImage(full.image.inner, 0, 0, sW/scale, sH/scale);
				portraitView();				
			} else {
				fitImage(full.image.inner, 0, 0, sH/scale, sW/scale);
				landscapeView();
			}	
			
			full.image.inner.x = -full.image.inner.width/2;
			full.image.inner.y = -full.image.inner.height/2;
		}	
		
		private function doOrientation(e:StageOrientationEvent):void {
			if (platform == "blackberry") {	
				/*
				if (stage.fullScreenWidth > 0) {
					if (stage.fullScreenWidth > stage.fullScreenHeight) {
						trace ("orient horizontal");
						orientation = "horizontal";
						landscapeView();
					} else {
						trace ("orient vertical");
						orientation = "vertical";
						portraitView();
					}
				} else {
					if (stage.stageWidth > stage.stageHeight) {
						orientation = "horizontal";
						landscapeView();
					} else {
						orientation = "vertical";
						portraitView();
					}			
				}
				*/				
			} else {
				switch (e.afterOrientation) {
					case StageOrientation.DEFAULT:
						orientation = "portrait";
						portraitView();
						break;
					case StageOrientation.ROTATED_RIGHT:
						orientation = "landscape";
						landscapeView();
						break;
					case StageOrientation.ROTATED_LEFT:
						orientation = "landscape";
						landscapeView();
						break;
					case StageOrientation.UPSIDE_DOWN:
						orientation = "portrait";
						portraitView();
						break;
				}
			}
		}
		
		private function portraitView():void {
			full.image.x = sW/2/scale;
			full.image.y = sH/2/scale;
		}
		
		private function landscapeView():void {
			full.image.x = sH/2/scale;
			full.image.y = sW/2/scale;
		}
		
		
		////////////////////   SWIPING   //////////////////  
		
		private var swipeCheck:Boolean = true;
		private var swipeTimer:Timer;
		
		private function nextImageSwipe(e:TransformGestureEvent):void {	
			trace ("swipe");
			if (myData.pics.length == 0) {return;}
			if (!swipeCheck) {return;}
			if (e.offsetX < 0) { // swipe left (forward)	
				getNextImage();
			} else { // right (back)		
				getPrevImage();
			}				
			swipeCheck = false;
			swipeTimer.reset();
			swipeTimer.start();
		}
		
		private function setSwipeCheck(e:TimerEvent):void {
			swipeCheck = true;
		}
		
		private function getNextImage():void {
			picNum++;
			if (picNum >= myData.pics.length) {picNum = 0;}	
			deepBreath.arrow.rotation = 180;
			if (tag.contains(tag.rank) || tag.contains(tag.rankInfo)) {
				currentWin++;
				if (currentWin >= myData.winners.length) {
					currentWin = 0;
				}
				tag.rank.myText.text = String(currentWin+1);
				picNum = myData.picNums[myData.winners[currentWin]];
			}
			if (searchCheck) {
				currentSearch++;
				if (currentSearch >= myData.search.length) {
					currentSearch = 0;
				}
				picNum = myData.picNums[myData.search[currentSearch]];
			}
			getImage();
		}
		private function getPrevImage():void {
			picNum--;
			if (picNum < 0) {picNum = myData.pics.length-1;}
			deepBreath.arrow.rotation = 0;
			if (tag.contains(tag.rank) || tag.contains(tag.rankInfo)) {
				currentWin--;
				if (currentWin < 0) {
					currentWin = myData.winners.length-1;
				}
				tag.rank.myText.text = String(currentWin+1);
				picNum = myData.picNums[myData.winners[currentWin]];
			}
			if (searchCheck) {
				currentSearch--;
				if (currentSearch < 0) {
					currentSearch = myData.search.length-1;
				}
				picNum = myData.picNums[myData.search[currentSearch]];
			}
			getImage();
		}
		
		private function getPics(e:Event):void {
			trace ("----------------------------"+myData.pics[1]);
		}
		
		private function getImage():void {			
			tag.info.hunterText.text = "...";
			tag.info.myText.text = "...";
			tag.image.removeChildAt(0);
			tag.image.addChild(deepBreath);
			deepBreath.arrow.visible = true;
			fitImage(tag.image, gutter/2/scale, tag.imageBacking.y, (sW-gutter)/scale, tag.imageBacking.height);
			currentPic = myData.pics[picNum];
			myData.getInfo(String(currentPic));
			nextLoader.load(new URLRequest(urlRoot + currentPic + ".jpg"));		
		}
		
		private function nextImage(e:MouseEvent):void {						
			trace ("nextImage");
			if (myData.pics.length == 0) {return;}
			getNextImage();
		}
		
		private function nextWinImage(e:MouseEvent):void {		
			if (myData.pics.length == 0) {return;}
			getNextImage();
		}
		
		private function prevWinImage(e:MouseEvent):void {
			if (myData.pics.length == 0) {return;}
			getPrevImage();
		}
		
		private function nextImageReady(e:Event):void {			
			tag.image.removeChildAt(0);
			deepBreath.arrow.visible = false;
			var bmd:BitmapData = new BitmapData(nextLoader.content.width, nextLoader.content.height, false, 0);
			bmd.draw(nextLoader.content);
			tag.image.addChild(new Bitmap(bmd));
			fitImage(tag.image, gutter/2/scale, tag.imageBacking.y, (sW-gutter)/scale, tag.imageBacking.height);
		}
		
		/*
		private var swipeDownStartTime:Number;
		private function swiperDown(e:MouseEvent):void {
			// set timer to differentiate swipe and press on pic
			var d:Date = new Date();
			swipeDownStartTime = d.getTime();			
		}
		
		private function gotoFull(e:MouseEvent):void {
			// called from clicking on image (swiper)
			// will conflict with swipe unless manage
			var d:Date = new Date();
			if (d.getTime() - swipeDownStartTime > 300) {return;}
			stage.autoOrients = false;	
			stage.setOrientation(StageOrientation.DEFAULT);
			removeChildAt(0);			
			addChildAt(full, 0);
			doFull();			
		}	
		*/
		
		
		///////////////////////////  SEARCH  ///////////////////////////////////
		
		private function showSearch():void {
			addChild(search);
		}
		
		private function doSearchCancel(e:MouseEvent):void {			
			removeChild(search);
		}
		
		private function doTopCancel(e:MouseEvent):void {			
			removeChild(top);
		}
		
		private function doSearch(e:MouseEvent):void {				
			myData.doSearch(search.pane.screenText.text, search.pane.tagText.text, search.pane.commentText.text);						
		}
		
		private function doNewest(e:MouseEvent):void {				
			myData.doSearch("", "newest", "");						
		}
		
		private function doOldest(e:MouseEvent):void {				
			myData.doSearch("", "oldest", "");						
		}
		
		private function showResults():void {
			search.removeChild(search.pane);
			search.results.addChild(search.results.target);
			search.results.addChild(search.results.targets);
			if (myData.search.length == 1) {
				search.results.removeChild(search.results.targets);
			} else {
				search.results.removeChild(search.results.target);
			}
			search.results.resultText.text = String(myData.search.length);
			search.addChild(search.results);
			resultsTimer.start();			
		}
			
		private function doResultTimer(e:TimerEvent):void {
			resultsTimer.reset();
			if (contains(search)) {
				removeChild(search);
			}
			if (contains(top)) {
				removeChild(top);
			}
			if (search.contains(search.results)) {
				search.removeChild(search.results);
				search.addChild(search.pane);
			}
		}
		
		private function getSearch(e:Event):void {			
			
			showResults();
			
			if (myData.search.length <= 0) {return;}
			
			searchCheck = true;				
				
			tag.header.removeChild(tag.header.searchBut);
			tag.header.addChild(tag.header.clearBut);
						
			tag.image.removeChildAt(0);
			tag.image.addChild(deepBreath);
			fitImage(tag.image, gutter/2/scale, tag.imageBacking.y, (sW-gutter)/scale, tag.imageBacking.height);			
			
			currentSearch = 0;
			picNum = myData.picNums[myData.search[currentSearch]];			
			prepareTagPage();		
			
		}	
		
		private function doSearchClear(e:MouseEvent):void {			
			tag.header.removeChild(tag.header.clearBut);
			tag.header.addChild(tag.header.searchBut);
			searchCheck = false;	
		}
		
		private function searchOff():void {
			searchCheck = false;
			if (tag.header.contains(tag.header.clearBut)) {				
				tag.header.removeChild(tag.header.clearBut);
				tag.header.addChild(tag.header.searchBut);
			}
		}
		
		//////////////////////  ACCOUNT   ///////////////////////////
		
		private function showAccount():void {
			addChild(account);
			lastAccount.screen = account.pane.screenText.text;
			lastAccount.facebook = account.pane.facebookText.text;
			lastAccount.twitter = account.pane.twitterText.text;
		}
		
		private function doAccountCancel(e:MouseEvent):void {
			account.pane.screenText.text = lastAccount.screen;
			account.pane.facebookText.text = lastAccount.facebook;
			account.pane.twitterText.text = lastAccount.twitter;
			removeChild(account);
		}
		
		private function doAccountSave(e:MouseEvent):void {
			lastAccount.screen = account.pane.screenText.text;
			lastAccount.facebook = account.pane.facebookText.text;
			lastAccount.twitter = account.pane.twitterText.text;
			removeChild(account);
			if (getChildAt(0) == post && lastAccount.screen != "") {
				post.addChild(post.processing);
				photo.getPhoto();	
			}
			if (getChildAt(0) == comment && lastAccount.screen != "") {
				uploadImage(null);				
			}
		}
		
		/////////////////////////  UPLOAD  //////////////////////////////
		
		private function uploadImage(e:MouseEvent):void {
			if (lastAccount.screen == undefined || lastAccount.screen == "") {
				showAccount();				
				return;
			}			
			if (comment.myText.text == "" || comment.myText.text == "Doing?  Saying?  Thinking?" || comment.myText.text == "Please type a few words...") {
				comment.myText.text = "Please type a few words...";
				return;
			}
			comment.waitMessage.alpha = 1;
			
			
			// delay to make sure message activates before upload processes
			// there is no animation, etc. as image is uploading - we are frozen
			commentTimer.reset();
			commentTimer.start();
		}
		
		private function uploadImage2(e:TimerEvent):void {
			
			var now:Date = new Date();
			var imageID:String = now.getTime() + "" + Math.round(Math.random()*1000);
			
			// create a jpg from cropper bitmapData and send to php which will write to Amazon
			if (!localCheck) {
				new ImageSend(cropper.getBitmapData(), "http://danzen.com/hipster/image.php?id="+imageID);
			}
			
			// write URL and info to database
			var obj:Object = {};
			obj.pid = imageID;
			obj.screen = account.pane.screenText.text;
			account.pane.facebookText.text = account.pane.facebookText.text.replace(/^(.*)facebook\.com\//i, "");
			account.pane.twitterText.text = account.pane.twitterText.text.replace(/^(.*)twitter\.com\//i, "");			
			obj.facebook = account.pane.facebookText.text;
			obj.twitter = account.pane.twitterText.text;
			obj.comment = comment.myText.text;	
						
			if (!localCheck) {
				myData.newPic(obj);				
			}
			
			removeChildAt(0);	
			
			// set the tag picture to the cropped pic			
			tag.image.removeChildAt(0);
			tag.image.addChild(new Bitmap(cropper.getBitmapData()));
			fitImage(tag.image, gutter/2/scale, tag.imageBacking.y, (sW-gutter)/scale, tag.imageBacking.height);
			
			// insert new picture ID into pics array
			myData.pics.splice(picNum,0,imageID);
			myData.setPicNums();
			currentPic = Number(imageID);			
			prepareTagPage();	
			
			// new stuff
			if (messageCheck == false) {
				tag.addChild(tag.message);				
			} else if (tag.contains(tag.message)) {
				tag.removeChild(tag.message);
			}
			
			searchOff();
			addChild(tag);
			myData.info = {screen:obj.screen, facebook:obj.facebook, twitter:obj.twitter, comment:obj.comment};
			setInfo();	
			tag.setChildIndex(tag.swiper, tag.numChildren-1);
			trace ("input mode = " + Multitouch.inputMode);
			if (!tag.swiper.hasEventListener(TransformGestureEvent.GESTURE_SWIPE)) {
				tag.swiper.removeEventListener(TransformGestureEvent.GESTURE_SWIPE, nextImageSwipe);
			}
			tag.swiper.addEventListener(TransformGestureEvent.GESTURE_SWIPE, nextImageSwipe);
		}
		
		private function photoCancel(e:Event):void {
			trace("canceled photo");
			// just stay on upload page
			post.removeChild(post.processing);
		}
		
		private function photoLoaded(e:Event):void {
			post.removeChild(post.processing);
			if (e.target.error != "success") {
				// error getting photo
				trace ("photo not accepted");
				showMalfunction();
				return;
			}		
			removeChildAt(0);
			// take out placeholder inner image and add Bitmap from cam roll bitmapData
			rotate.image.removeChildAt(0);
			rotate.image.addChild(new Bitmap(e.target.bitmapData as BitmapData));
			fitImage(rotate.image, 0, rotate.imageBacking.y, sW/scale, rotate.imageBacking.height);
			setRotator();
			addChild(rotate);
		}
		
		
		private function doCropBack(e:MouseEvent):void {
			// unique handler to avoid getting new cam roll picture
			removeChildAt(0);
			addChild(rotate);
		}
		
		private function doCommentBack(e:MouseEvent):void {
			// unique handler to avoid resetting the crop position
			removeChildAt(0);
			addChild(crop);
		}
		
		private function setRotator():void {
			if (rotator) {					
				rotator.dispose();
				rotator = null;
			}	
			// Rotator adds an event handler to rotation button
			// then handles rotating the image making a new bitmapData property each time
			// in the end, the bitmapData property is used to feed the crop screen image
			rotator = new Rotator(rotate.image.getChildAt(0), rotate.rotateBut);
			rotator.addEventListener(Rotator.ROTATE, doRotate);			
		}
		
		private function doRotate(e:Event):void {
			// center pic again	
			fitImage(rotate.image, 0, rotate.imageBacking.y, sW/scale, rotate.imageBacking.height);
		}
		
		private function setCropper():void {
			if (cropper) {				
				crop.removeChild(cropper);
				cropper.dispose();
				cropper = null;
			}
			// Cropper adds multitouch events to the crop handles
			// it also dynamically draws the crop rectangle joining the handles
			// and it provides a method to get the bitmapData of the pic in the crop rectangle
			// this bitmapData is then used to draw the pic in the comment page
			if (platform == "blackberry") {
				cropper = new Cropper(crop.image, crop.cropLeft, crop.cropRight, false);
			} else {
				cropper = new Cropper(crop.image, crop.cropLeft, crop.cropRight);
			}
			crop.addChild(cropper);			
		}		
		
		private function meldDone():void {
			// method to remove the information screen on the fullscreen page once the tween is done
			if (full.contains(full.meld)) {				
				full.removeChild(full.meld);
			}
		}
		
		
		private function setComment(e:FocusEvent):void {
			comment.myText.text = "";
			comment.myText.removeEventListener(FocusEvent.FOCUS_IN, setComment);				
		}
		

		
		
		/////////////////////////  WINNERS  ///////////////////////////////////////////////
		
		
		private function doWin(e:MouseEvent):void {
			winnerTopic = e.target.name.substr(2,e.target.name.length-2);			
			myData.getWinners(winnerTopic);
		}
		
		private function getWinners(e:Event):void {			
			
			var topic:String = (winnerTopic.match(/0s/)) ? winnerTopic : winnerTopic.toUpperCase();		
			
			top.results.addChild(top.results.target);
			top.results.addChild(top.results.targets);
			if (myData.winners.length == 1) {
				top.results.removeChild(top.results.targets);
			} else {
				top.results.removeChild(top.results.target);
			}
			top.results.resultText.text = String(myData.winners.length);
			resultsTimer.start();
			
			
			if (myData.winners.length <= 0) {
				// pop no-tag-yet message
				addChild(top);
				return;
			}
			
			tag.image.removeChildAt(0);
			tag.image.addChild(deepBreath);
			fitImage(tag.image, gutter/2/scale, tag.imageBacking.y, (sW-gutter)/scale, tag.imageBacking.height);
			
			currentWin = 0;
			picNum = myData.picNums[myData.winners[currentWin]];			
			
			removeChild(win);
			searchOff();
			prepareTagPage();
			
			tag.addChildAt(tag.winBut, 0);
			tag.addChild(tag.rank);
			tag.addChild(tag.headerWin);		
						
			tag.rank.tagText.text = topic;
			tag.rank.myText.text = String(currentWin+1);
			
			if (tag.contains(tag.info)) {tag.removeChild(tag.info);}
			if (tag.contains(tag.tags)) {tag.removeChild(tag.tags);}
			if (tag.contains(tag.tagBut)) {tag.removeChild(tag.tagBut);}
			
			addChild(tag);	
			addChild(top);			
		}
		
		private function doRank(e:MouseEvent):void {
			trace("do Rank");
			tag.addChild(tag.rank);
			tag.removeChild(tag.rankInfo);
		}				
	
		
		///////////////////////////////// SCALE FUNCTIONS /////////////////////////////////////
		
		private function adjustForResolutions():void {
			// for this app, we are locked on vertical (portrait)
			// all pages are anchored to the top with enough background to handle iPod 5 (narrow)
			
			// SPLASH PAGE - Button
			// position splash button at bottom
			// this button is inside a scaled clip
			// convert it to the stage scale by x scale - make desired change
			// convert the answer back to the local scale by / scale
			splash.gogoBut.y = (sH - splash.gogoBut.height/2 * scale * 1.5) / scale;
			
			// TAG PAGE - Tags
			// on tag page need to put tags at bottom of page and then set picture height
			// tags is the pannel of tags - with the registration point set at the bottom
			var tagsStartY:Number = tag.tags.y;
			tag.tags.y = sH / scale;
			tag.info.y = sH / scale;
			tag.tagTool.y = sH / scale;
			tag.rankInfo.y = sH / scale;
			tag.rank.y = sH / scale;
			
			// ipad
			var iPadScale:Number = 1;
			if (sW / sH > .7 && sW / sH < .8 && sW > 700) {
				iPadScale = .75;
			} 
			
			var startPadH:Number = tag.tags.height;
			tag.tags.scaleX = tag.tags.scaleY = tag.tags.scaleX * iPadScale;
			tag.tags.x = (1-iPadScale) * sW / scale / 2;
			tag.info.scaleX = tag.info.scaleY = tag.info.scaleX * iPadScale;
			tag.info.x = (1-iPadScale) * sW / scale / 2;
			tag.rankInfo.scaleX = tag.rankInfo.scaleY = tag.rankInfo.scaleX * iPadScale;
			tag.rankInfo.x = (1-iPadScale) * sW / scale / 2;
			tag.rank.scaleX = tag.rank.scaleY = tag.rank.scaleX * iPadScale;
			tag.rank.x = (1-iPadScale) * sW / scale / 2;
			var iPadAdded:Number = (startPadH - tag.tags.height) / scale / 1.1;
			var dif:Number = tagsStartY - tag.tags.y;
			imageHeight = tag.imageBacking.height - dif + iPadAdded;
			tag.imageBacking.height = imageHeight;
			fitImage(tag.image, gutter/2/scale, tag.imageBacking.y, (sW-gutter)/scale, tag.imageBacking.height);
									
			// HUNT PAGE - ergone			
			if ((hunt.ergone.y + hunt.ergone.height + 20) * scale > sH) {
				hunt.removeChild(hunt.ergone);				
			}
			
			// ROTATE PAGE - image (not needed on mobile)		
			fitImage(rotate.image, 0, rotate.imageBacking.y, sW/scale, rotate.imageBacking.height);
			
			// MENU PAGE - Ad			
			var adSpace:Number = sH / scale - (home.tagBut.y + home.tagBut.height);
			
			if (home.ad.contains(home.ad.big)) {
				home.ad.removeChild(home.ad.big);
			}
			if (home.ad.contains(home.ad.small)) {
				home.ad.removeChild(home.ad.small);
			}
			if (home.ad.contains(home.ad.bigHangy)) {
				home.ad.removeChild(home.ad.bigHangy);
			}
			if (home.ad.contains(home.ad.smallHangy)) {
				home.ad.removeChild(home.ad.smallHangy);
			}
			
			if (home.ad.big.height > adSpace * .8) {				
				if (platform == "blackberry") {
					home.ad.addChild(home.ad.smallHangy);
				} else {
					home.ad.addChild(home.ad.small);
				}
			} else {
				if (platform == "blackberry") {
					home.ad.addChild(home.ad.bigHangy);
				} else {
					home.ad.addChild(home.ad.big);
				}
			}
			fitImage(home.ad, 0, 0, sW / scale *.8, adSpace * .8);
			home.ad.y = sH / scale - adSpace / 2;
			home.ad.x = sW / scale;
			
			/*
			// MENU PAGE - Ad			
			if ((home.ad.y + home.ad.big.y + home.ad.big.height) * scale > sH) {				
				home.ad.removeChild(home.ad.big);
				trace ("here2");				
			} else {				
				home.ad.removeChild(home.ad.small);
				return;
			}
			if ((home.ad.y+20) * scale > sH) {
				home.ad.removeChild(home.ad.small);
			} else {
				var startH:Number = home.ad.small.height;
				var startW:Number = home.ad.small.width;
				var scaleAd:Number = (sH - (home.ad.y+20) * scale) / scale / startH;	
				home.ad.scaleX = home.ad.scaleY = scaleAd;
				if (home.ad.width > sW / scale - 40) {
					home.ad.scaleX = home.ad.scaleY = 1;
					scaleAd = home.ad.width / (sW / scale - 40);
					home.ad.scaleX = home.ad.scaleY = scaleAd;
				}
				if (platform == "apple") {
					home.ad.y += (sH - home.ad.y*scale) / 2.5;
					if (home.ad.y + home.ad.height > sH / scale) {
						home.ad.y = - home.ad.height + sH / scale - 5;
					}	
				} else {					
					home.ad.y += (sH - home.ad.y*scale) / 2.5;
					if (home.ad.y + home.ad.height > sH / scale) {
						home.ad.y = - home.ad.height + sH / scale - 5;
					}						
				}
				home.ad.x = sW / scale - home.ad.width - 20;
			}
			*/
			
		}			
		
		private function fitImage(img:MovieClip, minX:Number, minY:Number, maxWidth:Number, maxHeight:Number):void {	
			// generic function to fit a clip in a rectangle and center it
			img.scaleX = img.scaleY = 1;
			var imageScale:Number = maxHeight / img.height;
			img.scaleX = img.scaleY = imageScale;			
			if (img.width > maxWidth) {				
				img.scaleX = img.scaleY = 1;
				imageScale = maxWidth / img.width;
				img.scaleX = img.scaleY = imageScale;	
				img.x = minX;
				img.y = minY + (maxHeight - img.height) / 2;
			} else {		
				img.x = minX + (maxWidth - img.width) / 2;
				img.y = minY;
			}			
		}		
		
		private function initScale():void {
			if (stage.fullScreenWidth > 0) {
				sW = stage.fullScreenWidth;
				sH = stage.fullScreenHeight;
			} else {
				sW = stage.stageWidth;
				sH = stage.stageHeight;				
			}
			if (sW > sH) {
				var temp:Number = sW;
				sW = sH; sH = temp;
			}			
			scale = sW / 640; // hardcoded due to dropshadow messing up width
		}
		private function setScale(w:MovieClip):void {			
			w.scaleX = w.scaleY = scale;
		}
	}
}

package com.danzen.interfaces {
	
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.events.*;
	import flash.geom.Matrix;
	
	public class Cropper extends MovieClip	{
		
		private var image:MovieClip;
		private var leftHandle:MovieClip;
		private var rightHandle:MovieClip;
		private var startGutter:Number = 40;
		private var downCheck:Boolean = false;
		private var dragLeftCheck:Boolean = false;
		private var dragRightCheck:Boolean = false;
		private var scale:Number;
		private var touches:Object = new Object();
		private var multitouch:Boolean;
		
		public function Cropper(theImage:MovieClip, theLeftHandle:MovieClip, theRightHandle:MovieClip, theMultitouch:Boolean=true) {
			trace ("hi from Cropper");
			image = theImage;
			scale = image.scaleX;
			leftHandle = theLeftHandle;	rightHandle = theRightHandle;
			leftHandle.mouseChildren = false;
			rightHandle.mouseChildren = false;
			leftHandle.x = image.x + startGutter; leftHandle.y = image.y + startGutter;
			rightHandle.x = image.x + image.width - startGutter; rightHandle.y = image.y + image.height - startGutter;
			multitouch = theMultitouch;
			drawCropRect();
			if (multitouch) {
				leftHandle.addEventListener(TouchEvent.TOUCH_BEGIN, doDown);	
				rightHandle.addEventListener(TouchEvent.TOUCH_BEGIN, doDown);
			} else {
				leftHandle.addEventListener(MouseEvent.MOUSE_DOWN, doDown2);	
				rightHandle.addEventListener(MouseEvent.MOUSE_DOWN, doDown2);		
			}
			leftHandle.buttonMode = rightHandle.buttonMode = true;			
		}
		
		// single touch
		
		private function doDown2(e:MouseEvent):void {
			if (!downCheck) {
				image.stage.addEventListener(MouseEvent.MOUSE_MOVE, setBounds2);
				image.stage.addEventListener(MouseEvent.MOUSE_UP, doUp2);
			}
			if (e.target == leftHandle) {
				dragLeftCheck = true;
			}
			if (e.target == rightHandle) {
				dragRightCheck = true;
			}
			e.target.offsetX = image.parent.mouseX - e.target.x;
			e.target.offsetY = image.parent.mouseY - e.target.y;
		}
		
		private function doUp2(e:MouseEvent):void {
			image.stage.removeEventListener(MouseEvent.MOUSE_MOVE, setBounds2);
			image.stage.removeEventListener(MouseEvent.MOUSE_UP, doUp2);
			downCheck = false;
			dragLeftCheck = false;
			dragRightCheck = false;
		}
		
		private function setBounds2(e:Event):void {
			if (dragLeftCheck) {
				leftHandle.x = image.parent.mouseX - leftHandle.offsetX;
				leftHandle.y = image.parent.mouseY - leftHandle.offsetY;
			}
			bounds(leftHandle);
			if (dragRightCheck) {
				rightHandle.x = image.parent.mouseX - rightHandle.offsetX;
				rightHandle.y = image.parent.mouseY - rightHandle.offsetY;
			}
			bounds(rightHandle);
			drawCropRect();
		}		
		
		// multitouch
				
		private function doDown(e:TouchEvent):void {			
			if (!downCheck) {
				downCheck = true;
				image.stage.addEventListener(TouchEvent.TOUCH_MOVE, setBounds);
				image.stage.addEventListener(TouchEvent.TOUCH_END, doUp);
			}
			touches[e.touchPointID] = e.target;		
			e.target.offsetX = e.stageX - e.target.x;
			e.target.offsetY = e.stageY - e.target.y;
		}
		
		private function doUp(e:TouchEvent):void {
			delete touches[e.touchPointID];
			for each (var prop:Object in touches) {var full:Boolean=true; break;}
			if (!full) {
				image.stage.removeEventListener(TouchEvent.TOUCH_MOVE, setBounds);
				image.stage.removeEventListener(TouchEvent.TOUCH_END, doUp);
				downCheck = false;
			}
		}
		
		private function setBounds(e:TouchEvent):void {			
			var t:MovieClip = MovieClip(touches[e.touchPointID]);
			t.x = e.stageX - t.offsetX;
			t.y = e.stageY - t.offsetY;			
			bounds(t);			
			drawCropRect();
		}
		
		private function drawCropRect():void {
			graphics.clear();
			graphics.lineStyle(4,0x000000,1,false);
			graphics.drawRect(leftHandle.x, leftHandle.y, rightHandle.x - leftHandle.x, rightHandle.y - leftHandle.y);
			graphics.lineStyle(4,0xfffffff,1,false);
			graphics.drawRect(leftHandle.x+4, leftHandle.y+4, rightHandle.x - leftHandle.x - 8, rightHandle.y - leftHandle.y - 8);
		}
		
		private function bounds(w:MovieClip):void {
			if (w.x < image.x) {
				w.x = image.x;
			}
			if (w.y < image.y) {
				w.y = image.y;
			}
			if (w.x > image.x + image.width) {
				w.x = image.x + image.width;
			}
			if (w.y > image.y + image.height) {
				w.y = image.y + image.height;
			}
			if (w == leftHandle) {
				if (w.x + leftHandle.width * 1.5 > rightHandle.x) {
					w.x = rightHandle.x - leftHandle.width * 1.5;
				}
				if (w.y + leftHandle.height * 1.5 > rightHandle.y) {
					w.y = rightHandle.y - leftHandle.height * 1.5;
				}
			} else if (w == rightHandle) {
				if (w.x - rightHandle.width * 1.5 < leftHandle.x) {
					w.x = leftHandle.x + rightHandle.width * 1.5;
				}
				if (w.y - rightHandle.height * 1.5 < leftHandle.y) {
					w.y = leftHandle.y + rightHandle.height * 1.5;
				}
			}			
		}
		
		public function getBitmapData():BitmapData {			
			var bmData:BitmapData = new BitmapData((rightHandle.x - leftHandle.x)/scale, (rightHandle.y - leftHandle.y)/scale, false);
			var matrix:Matrix = new Matrix();
			matrix.translate((image.x-leftHandle.x)/scale, (image.y-leftHandle.y)/scale);			
			bmData.draw(image, matrix);
			return bmData;			
		}
		
		public function dispose():void {
			leftHandle.removeEventListener(TouchEvent.TOUCH_BEGIN, doDown);	
			rightHandle.removeEventListener(TouchEvent.TOUCH_BEGIN, doDown);	
			if (downCheck) {
				image.stage.removeEventListener(TouchEvent.TOUCH_MOVE, setBounds);
				image.stage.removeEventListener(TouchEvent.TOUCH_END, doUp);
			}
		}
		
	}
}

package com.danzen.interfaces {
	
	import com.adobe.images.JPGEncoder;
	
	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.events.*;
	import flash.geom.Matrix;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	import flash.net.navigateToURL;
	import flash.utils.ByteArray;
	
	
	// ImageSend - Dan Zen 2010
	// create jpg and send image to url
	
	
	public class ImageSend extends MovieClip {
		
		private var bitmapData:BitmapData;
		private var url:String;
		
		public function ImageSend(theBitmapData:BitmapData, theURL:String, max:Number=1024)	{
			trace ("hi from ImageSend");
			
			bitmapData = theBitmapData;
			url = theURL;
			
			if (bitmapData.height > max || bitmapData.width > max) {
				var newW:Number;
				var newH:Number;
				var scale:Number;
				if (bitmapData.height / bitmapData.width > 1) {
					scale = max / bitmapData.height;
					newW = bitmapData.width * scale;
					newH = max;					
				} else {
					scale = max / bitmapData.width
					newH = bitmapData.height * scale;
					newW = max;
				}
				var m:Matrix = new Matrix();
				m.scale(scale,scale);
				var bm:BitmapData = new BitmapData(newW, newH, false, 0);
				bm.draw(bitmapData, m);
				bitmapData = bm;
			}
			
			var myEncoder:JPGEncoder = new JPGEncoder(80);
			var stream:ByteArray = myEncoder.encode(bitmapData);			
			var header:URLRequestHeader = new URLRequestHeader("Content-type", "application/octet-stream");
			var jpgURLRequest:URLRequest;
			var urlLoader:URLLoader;			
			
			jpgURLRequest = new URLRequest(url);
			jpgURLRequest.requestHeaders.push(header);
			jpgURLRequest.method = URLRequestMethod.POST;
			jpgURLRequest.data = stream;
			
			urlLoader = new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE, imageComplete);
			urlLoader.load(jpgURLRequest);			
		}
		
		private function imageComplete(e:Event):void {
			dispatchEvent(new Event(Event.COMPLETE));	
		}
		
	}
}


package com.danzen.interfaces {

	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.events.*;
	import flash.geom.Matrix;
	import flash.media.CameraRoll;
	import flash.media.MediaPromise;
	import flash.utils.Timer;
	
	// MobileCamRoll - compiled from code on the web and wrapped by Dan Zen 2012
	// tested with iOS, Android and Blackberry 10 (Playbook) used first on hangy.mobi then on hipster.mobi
	
	// MobileCamRoll opens the camera roll on Mobile when you call getPhoto	
	// it then gives an Event.COMPLETE event with an error of "success" if no error 
	// and you can get the bitmapData property to get the picture data
	// an Event.CANCEL is dispatched if cancelled	
	
	public class MobileCamRoll extends MovieClip	{
		
		public var bitmapData:BitmapData;	
		public var error:String;
		private var max:Number;
		
		public function MobileCamRoll()	{
			trace ("hi from MobileCamRoll");
		}
		
		public function getPhoto(theMax:Number=1024):void {
			max = theMax
			var t:Timer = new Timer(100,1);
			t.addEventListener(TimerEvent.TIMER, go);
			t.start();			
		}
		
		private function go(e:TimerEvent):void {
			var cr:CameraRoll=new CameraRoll();	
			var loader:Loader;
			
			if (CameraRoll.supportsBrowseForImage == false) {				
				error = "Sorry, photo browsing not supported";
				dispatchEvent(new Event(Event.COMPLETE));
				return;
			}					
		
			addBrowseListeners();			
			cr.browseForImage();
			
			function addBrowseListeners():void {				
				cr.addEventListener(MediaEvent.SELECT, onImgSelect);
				cr.addEventListener(Event.CANCEL, onCancel);
				cr.addEventListener(ErrorEvent.ERROR, onError);				
			}
			
			function removeBrowseListeners():void {				
				cr.removeEventListener(MediaEvent.SELECT, onImgSelect);
				cr.removeEventListener(Event.CANCEL, onCancel);
				cr.removeEventListener(ErrorEvent.ERROR, onError);				
			}			
			
			function onCancel(event:Event):void {				
				removeBrowseListeners();				
				dispatchEvent(new Event(Event.CANCEL));	
			}
			
			function onError(event:ErrorEvent):void {	
				removeBrowseListeners();				
				error = "Sorry, error loading pic";
				dispatchEvent(new Event(Event.COMPLETE));			
			}			
			
			function onImgSelect(event:MediaEvent):void {				
				var promise:MediaPromise = event.data as MediaPromise;				
				removeBrowseListeners();				
				loader = new Loader();
				loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
				loader.contentLoaderInfo.addEventListener(ErrorEvent.ERROR, onError);
				loader.loadFilePromise(promise);				
			}			
						
			function onImageLoaded(event:Event):void {				
				bitmapData = Bitmap(event.currentTarget.content).bitmapData;	
				
				if (bitmapData.height > max || bitmapData.width > max) {
					var newW:Number;
					var newH:Number;
					var scale:Number;
					if (bitmapData.height / bitmapData.width > 1) {
						scale = max / bitmapData.height;
						newW = bitmapData.width * scale;
						newH = max;					
					} else {
						scale = max / bitmapData.width
						newH = bitmapData.height * scale;
						newW = max;
					}
					var m:Matrix = new Matrix();
					m.scale(scale,scale);
					var bm:BitmapData = new BitmapData(newW, newH, false, 0);
					bm.draw(bitmapData, m);
					bitmapData = bm;
				}
				
				loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onImageLoaded);				
				loader.contentLoaderInfo.removeEventListener(ErrorEvent.ERROR, onError);
				error = "success";
				dispatchEvent(new Event(Event.COMPLETE));
			}			
		}
	}
} 


package com.danzen.interfaces {
		
	import flash.display.BitmapData;
	import flash.display.Bitmap;
	import flash.display.MovieClip;
	import flash.display.DisplayObject;
	import flash.events.*;
	import flash.geom.Matrix;
	
	public class Rotator extends MovieClip	{
		
		private var image:DisplayObject;
		private var button:MovieClip;
		private var holder:MovieClip;		
		
		public static const ROTATE:String = "rotate";
		public var bitmapData:BitmapData;
		
		public function Rotator(theImage:DisplayObject, theButton:MovieClip) {
			trace ("hi from Rotator");
			image = theImage;
			holder = MovieClip(image.parent);
			button = theButton;
			button.buttonMode = true;
			button.addEventListener(MouseEvent.CLICK, doRotate);
			bitmapData = new BitmapData(image.width, image.height, false, 0);
			bitmapData.draw(image);
			
		}
		
		private function doRotate(e:MouseEvent):void {
			
			// grab bitmapData from sample - would be the image complete
			// rotate it with matrix removeChild old Bitmap and set to null
			// add new Bitmap
			// store the bitmapData to create the crop pic			
		
			var matrix:Matrix = new Matrix();
			matrix.translate(-bitmapData.width / 2, -bitmapData.height / 2);
			matrix.rotate(90 * (Math.PI / 180));
			matrix.translate(bitmapData.height / 2, bitmapData.width / 2);
			
			var bmd:BitmapData = new BitmapData(bitmapData.height, bitmapData.width, false, 0x00000000);
			bmd.draw(bitmapData, matrix);
			bitmapData = bmd;			
			var temp:DisplayObject = holder.getChildAt(0);
			holder.removeChild(temp);
			temp = null;			
			holder.addChild(new Bitmap(bitmapData));
			
			dispatchEvent(new Event(Rotator.ROTATE));
		}	
		
		public function dispose():void {
			button.removeEventListener(MouseEvent.CLICK, doRotate);		
			bitmapData = null;
		}
	}
}


package com.danzen.interfaces {
	
	import flash.display.MovieClip;
	import flash.events.*;
	import flash.text.TextField;
	
	public class TextScroll extends MovieClip {
		
		// scrolls a text field based on swipe type movement
		private var t:TextField;
		private var startY:Number;
		private var lastY:Number;
		private var startS:Number;	
		private var lastD:Number;
		private var sensitivity:Number; // 1 mobile, .05 web
		
		public function TextScroll(theTextField:TextField, theSensitivity:Number = 1):void {		
			sensitivity = theSensitivity;
			t = theTextField;			
			t.addEventListener(MouseEvent.MOUSE_DOWN, doDown);
			t.addEventListener(Event.CHANGE, testScroll);			
		}	
		
		public function testScroll():Boolean {
			if (t.maxScrollV > 1) {
				return true;
			} else {
				return false;
			}
		}
		
		private function doDown(e:MouseEvent):void {
			lastY = startY = mouseY;
			startS = t.scrollV;			
			t.stage.addEventListener(MouseEvent.MOUSE_MOVE, doScroll);
			t.stage.addEventListener(MouseEvent.MOUSE_UP, doUP);
		}
		private function doScroll(e:MouseEvent):void {			
			var newV:Number = startS - (mouseY-startY)*sensitivity;
			trace (sensitivity, newV);
			t.scrollV = Math.min(t.maxScrollV, Math.max(0, newV));			
		}
		private function doUP(e:MouseEvent):void {
			t.stage.removeEventListener(MouseEvent.MOUSE_MOVE, doScroll);
			t.stage.removeEventListener(MouseEvent.MOUSE_UP, doUP);
		}
	}
}