package com.oxylusflash.book { import caurina.transitions.Tweener; import com.oxylusflash.utils.NumberUtil; import flash.display.DisplayObject; import flash.display.Sprite; import flash.events.Event; import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.ui.Keyboard; public class ZoomSourceHolder extends Sprite { public var wrapper:ZoomSourceWrapper; private var w:Number = 0; private var h:Number = 0; public static const NO_INTERACT:int = 0; public static const CLICK_DRAG:int = 1; public static const MOUSE_PAN:int = 2; private var _interaction:int = NO_INTERACT; private var dx:Number = 0; private var dy:Number = 0; private var wrapperX:Number = 0; private var wrapperY:Number = 0; // Parameters. private var minX:Number = 0; private var minY:Number = 0; private var centerX:Number = 0; private var centerY:Number = 0; private static const SCROLL_STEP:Number = 10; /** * Zoom source content holder. */ public function ZoomSourceHolder() { this.mouseEnabled = false; this.mouseChildren = false; this.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler, false, 0, true); if (stage) { addKeyDownEvent(); } else { this.addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler, false, 0, true); } } private function addedToStageHandler(e:Event):void { this.removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); addKeyDownEvent(); } private function addKeyDownEvent():void { stage.addEventListener(KeyboardEvent.KEY_DOWN, keyDownHandler, false, 0, true); } private function keyDownHandler(e:KeyboardEvent):void { if (_interaction != MOUSE_PAN && wrapper) { var stepX:Number = 0; var stepY:Number = 0; var instant:Boolean = true; switch(e.keyCode) { case Keyboard.UP: stepY = SCROLL_STEP; break; case Keyboard.DOWN: stepY = -SCROLL_STEP; break; case Keyboard.LEFT: stepX = SCROLL_STEP; break; case Keyboard.RIGHT: stepX = -SCROLL_STEP; break; case Keyboard.HOME: stepY = wrapper.height; instant = false; break; case Keyboard.END: stepY = -wrapper.height; instant = false; break; case Keyboard.PAGE_UP: stepY = Global.layout.height; instant = false; break; case Keyboard.PAGE_DOWN: stepY = -Global.layout.height; instant = false; break; } updateWrapperPos(wrapperX + stepX, wrapperY + stepY, false, instant); } } /** * Mouse wheel scroll. */ private function mouseWheelHandler(e:MouseEvent):void { if (_interaction != MOUSE_PAN && !e.buttonDown) { var step:Number = e.delta * SCROLL_STEP; if (e.shiftKey) { updateWrapperPos(wrapperX + step, wrapperY); } else { updateWrapperPos(wrapperX, wrapperY + step); } } } /** * Update parameters. */ public function updateParams():void { if (wrapper) { minX = w - wrapper.width; minY = h - wrapper.height; centerX = (w - wrapper.width) * 0.5; centerY = (h - wrapper.height) * 0.5; } } /** * Add content in a wrapper sprite. * @param content Content to add. */ public function addWrapperFor(content:DisplayObject):void { clearWrapper(); wrapper = this.addChild(new ZoomSourceWrapper) as ZoomSourceWrapper; wrapper.addContent(content); updateParams(); wrapper.x = (w < wrapper.width) ? 0 : centerX; wrapper.y = (h < wrapper.height) ? 0 : centerY; wrapperX = wrapper.x; wrapperY = wrapper.y; this.mouseEnabled = true; this.mouseChildren = true; } public function clearWrapper():void { if (wrapper) { wrapper.die(); wrapper = null; } } public function blurWrapper():void { this.mouseEnabled = false; this.mouseChildren = false; if (wrapper) { wrapper.blurContent(); } } /** * Mouse interaction type. */ public function get interaction():int { return _interaction; } public function set interaction(value:int):void { if (_interaction != value) { clearEventsFor(_interaction); _interaction = NO_INTERACT; this.buttonMode = false; switch(value) { case CLICK_DRAG: _interaction = CLICK_DRAG; this.mouseChildren = false; this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler, false, 0, true); break; case MOUSE_PAN: _interaction = MOUSE_PAN; this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler, false, 0, true); break; } } } /** * Clear events for interaction. * @param value interaction type. */ public function clearEventsFor(value:int):void { switch(value) { case CLICK_DRAG: this.mouseChildren = true; this.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler); break; case MOUSE_PAN: this.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler); break; } } /** * Mouse down handler for CLICK_DRAG. */ private function mouseDownHandler(e:MouseEvent):void { if (wrapper) { dx = this.mouseX - wrapper.x; dy = this.mouseY - wrapper.y; stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler, false, 0, true); stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler, false, 0, true); } } /** * Mouse move handler for CLICK_DRAG. */ private function stage_mouseMoveHandler(e:MouseEvent):void { updateWrapperPos(this.mouseX - dx, this.mouseY - dy); } /** * Mouse up handler for CLICK_DRAG. */ private function stage_mouseUpHandler(e:MouseEvent):void { stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler); stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler); } /** * Mouse up handler for MOUSE_PAN. */ private function mouseMoveHandler(e:MouseEvent):void { if (wrapper) { var xPer:Number = (this.mouseX - ZoomSourceWrapper.PADDING_X) / (w - 2 * ZoomSourceWrapper.PADDING_X); var yPer:Number = (this.mouseY - ZoomSourceWrapper.PADDING_Y) / (h - 2 * ZoomSourceWrapper.PADDING_Y); updateWrapperPos(minX * xPer, minY * yPer); } } /** * Update wrapper position. * @param xPos Position on x. * @param yPos Position on y. * @param forced Forces position update. */ private function updateWrapperPos(xPos:Number, yPos:Number, forced:Boolean = false, instant:Boolean = false):void { if (wrapper && !Global.fullViewToolBar.isDragged) { xPos = Math.round((w < wrapper.width) ? Math.min(0, Math.max(minX, xPos)) : centerX); yPos = Math.round((h < wrapper.height) ? Math.min(0, Math.max(minY, yPos)) : centerY); if (wrapperX != xPos || wrapperY != yPos || forced) { wrapperX = xPos; wrapperY = yPos; Tweener.addTween(wrapper, { x: wrapperX, y: wrapperY, base: Global.baseTween, time: instant ? 0 : 0.2 } ); } } } /** * Overrides. */ override public function get width():Number { return w; } override public function set width(value:Number):void { w = value; updateParams(); updateWrapperPos(wrapperX, wrapperY, true, true); } override public function get height():Number { return h; } override public function set height(value:Number):void { h = value; updateParams(); updateWrapperPos(wrapperX, wrapperY, true, true); } } }