All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scaffold.libs_as.feathers.controls.popups.VerticalCenteredPopUpContentManager.as Maven / Gradle / Ivy

/*
Feathers
Copyright 2012-2015 Bowler Hat LLC. All Rights Reserved.

This program is free software. You can redistribute and/or modify it in
accordance with the terms of the accompanying license agreement.
*/
package feathers.controls.popups
{
	import feathers.core.IFeathersControl;
	import feathers.core.IValidating;
	import feathers.core.PopUpManager;
	import feathers.events.FeathersEventType;
	import feathers.utils.display.getDisplayObjectDepthFromStage;

	import flash.errors.IllegalOperationError;
	import flash.events.KeyboardEvent;
	import flash.geom.Point;
	import flash.ui.Keyboard;

	import starling.core.Starling;
	import starling.display.DisplayObject;
	import starling.display.DisplayObjectContainer;
	import starling.display.Stage;
	import starling.events.Event;
	import starling.events.EventDispatcher;
	import starling.events.ResizeEvent;
	import starling.events.Touch;
	import starling.events.TouchEvent;
	import starling.events.TouchPhase;

	/**
	 * Dispatched when the pop-up content opens.
	 *
	 * 

The properties of the event object have the following values:

* * * * * * *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the * event listener that handles the event. For example, if you use * myButton.addEventListener() to register an event listener, * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; * it is not always the Object listening for the event. Use the * currentTarget property to always access the Object * listening for the event.
* * @eventType starling.events.Event.OPEN */ [Event(name="open",type="starling.events.Event")] /** * Dispatched when the pop-up content closes. * *

The properties of the event object have the following values:

* * * * * * *
PropertyValue
bubblesfalse
currentTargetThe Object that defines the * event listener that handles the event. For example, if you use * myButton.addEventListener() to register an event listener, * myButton is the value of the currentTarget.
datanull
targetThe Object that dispatched the event; * it is not always the Object listening for the event. Use the * currentTarget property to always access the Object * listening for the event.
* * @eventType starling.events.Event.CLOSE */ [Event(name="close",type="starling.events.Event")] /** * Displays a pop-up at the center of the stage, filling the vertical space. * The content will be sized horizontally so that it is no larger than the * the width or height of the stage (whichever is smaller). */ public class VerticalCenteredPopUpContentManager extends EventDispatcher implements IPopUpContentManager { /** * @private */ private static const HELPER_POINT:Point = new Point(); /** * Constructor. */ public function VerticalCenteredPopUpContentManager() { } /** * Quickly sets all margin properties to the same value. The * margin getter always returns the value of * marginTop, but the other padding values may be * different. * *

The following example gives the pop-up a minimum of 20 pixels of * margin on all sides:

* * * manager.margin = 20; * * @default 0 * * @see #marginTop * @see #marginRight * @see #marginBottom * @see #marginLeft */ public function get margin():Number { return this.marginTop; } /** * @private */ public function set margin(value:Number):void { this.marginTop = 0; this.marginRight = 0; this.marginBottom = 0; this.marginLeft = 0; } /** * The minimum space, in pixels, between the top edge of the content and * the top edge of the stage. * *

The following example gives the pop-up a minimum of 20 pixels of * margin on the top:

* * * manager.marginTop = 20; * * @default 0 * * @see #margin */ public var marginTop:Number = 0; /** * The minimum space, in pixels, between the right edge of the content * and the right edge of the stage. * *

The following example gives the pop-up a minimum of 20 pixels of * margin on the right:

* * * manager.marginRight = 20; * * @default 0 * * @see #margin */ public var marginRight:Number = 0; /** * The minimum space, in pixels, between the bottom edge of the content * and the bottom edge of the stage. * *

The following example gives the pop-up a minimum of 20 pixels of * margin on the bottom:

* * * manager.marginBottom = 20; * * @default 0 * * @see #margin */ public var marginBottom:Number = 0; /** * The minimum space, in pixels, between the left edge of the content * and the left edge of the stage. * *

The following example gives the pop-up a minimum of 20 pixels of * margin on the left:

* * * manager.marginLeft = 20; * * @default 0 * * @see #margin */ public var marginLeft:Number = 0; /** * @private */ protected var content:DisplayObject; /** * @private */ protected var touchPointID:int = -1; /** * @inheritDoc */ public function get isOpen():Boolean { return this.content !== null; } /** * @inheritDoc */ public function open(content:DisplayObject, source:DisplayObject):void { if(this.isOpen) { throw new IllegalOperationError("Pop-up content is already open. Close the previous content before opening new content."); } this.content = content; PopUpManager.addPopUp(this.content, true, false); if(this.content is IFeathersControl) { this.content.addEventListener(FeathersEventType.RESIZE, content_resizeHandler); } this.content.addEventListener(Event.REMOVED_FROM_STAGE, content_removedFromStageHandler); this.layout(); var stage:Stage = Starling.current.stage; stage.addEventListener(TouchEvent.TOUCH, stage_touchHandler); stage.addEventListener(ResizeEvent.RESIZE, stage_resizeHandler); //using priority here is a hack so that objects higher up in the //display list have a chance to cancel the event first. var priority:int = -getDisplayObjectDepthFromStage(this.content); Starling.current.nativeStage.addEventListener(KeyboardEvent.KEY_DOWN, nativeStage_keyDownHandler, false, priority, true); this.dispatchEventWith(Event.OPEN); } /** * @inheritDoc */ public function close():void { if(!this.isOpen) { return; } var content:DisplayObject = this.content; this.content = null; var stage:Stage = Starling.current.stage; stage.removeEventListener(TouchEvent.TOUCH, stage_touchHandler); stage.removeEventListener(ResizeEvent.RESIZE, stage_resizeHandler); Starling.current.nativeStage.removeEventListener(KeyboardEvent.KEY_DOWN, nativeStage_keyDownHandler); if(content is IFeathersControl) { content.removeEventListener(FeathersEventType.RESIZE, content_resizeHandler); } content.removeEventListener(Event.REMOVED_FROM_STAGE, content_removedFromStageHandler); if(content.parent) { content.removeFromParent(false); } this.dispatchEventWith(Event.CLOSE); } /** * @inheritDoc */ public function dispose():void { this.close(); } /** * @private */ protected function layout():void { var stage:Stage = Starling.current.stage; var maxWidth:Number = stage.stageWidth; if(maxWidth > stage.stageHeight) { maxWidth = stage.stageHeight; } maxWidth -= (this.marginLeft + this.marginRight); var maxHeight:Number = stage.stageHeight - this.marginTop - this.marginBottom; var hasSetBounds:Boolean = false; if(this.content is IFeathersControl) { //if it's a ui control that is able to auto-size, this section //will ensure that the control stays within the required bounds. var uiContent:IFeathersControl = IFeathersControl(this.content); uiContent.minWidth = maxWidth; uiContent.maxWidth = maxWidth; uiContent.maxHeight = maxHeight; hasSetBounds = true; } if(this.content is IValidating) { IValidating(this.content).validate(); } if(!hasSetBounds) { //if it's not a ui control, and the control's explicit width and //height values are greater than our maximum bounds, then we //will enforce the maximum bounds the hard way. if(this.content.width > maxWidth) { this.content.width = maxWidth; } if(this.content.height > maxHeight) { this.content.height = maxHeight; } } //round to the nearest pixel to avoid unnecessary smoothing this.content.x = Math.round((stage.stageWidth - this.content.width) / 2); this.content.y = Math.round((stage.stageHeight - this.content.height) / 2); } /** * @private */ protected function content_resizeHandler(event:Event):void { this.layout(); } /** * @private */ protected function content_removedFromStageHandler(event:Event):void { this.close(); } /** * @private */ protected function nativeStage_keyDownHandler(event:KeyboardEvent):void { if(event.isDefaultPrevented()) { //someone else already handled this one return; } if(event.keyCode != Keyboard.BACK && event.keyCode != Keyboard.ESCAPE) { return; } //don't let the OS handle the event event.preventDefault(); this.close(); } /** * @private */ protected function stage_resizeHandler(event:ResizeEvent):void { this.layout(); } /** * @private */ protected function stage_touchHandler(event:TouchEvent):void { if(!PopUpManager.isTopLevelPopUp(this.content)) { return; } var stage:Stage = Starling.current.stage; if(this.touchPointID >= 0) { var touch:Touch = event.getTouch(stage, TouchPhase.ENDED, this.touchPointID); if(!touch) { return; } touch.getLocation(stage, HELPER_POINT); var hitTestResult:DisplayObject = stage.hitTest(HELPER_POINT); var isInBounds:Boolean = false; if(this.content is DisplayObjectContainer) { isInBounds = DisplayObjectContainer(this.content).contains(hitTestResult); } else { isInBounds = this.content == hitTestResult; } if(!isInBounds) { this.touchPointID = -1; this.close(); } } else { touch = event.getTouch(stage, TouchPhase.BEGAN); if(!touch) { return; } touch.getLocation(stage, HELPER_POINT); hitTestResult = stage.hitTest(HELPER_POINT); isInBounds = false; if(this.content is DisplayObjectContainer) { isInBounds = DisplayObjectContainer(this.content).contains(hitTestResult); } else { isInBounds = this.content == hitTestResult; } if(isInBounds) { return; } this.touchPointID = touch.id; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy