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

scaffold.libs_as.feathers.controls.popups.BottomDrawerPopUpContentManager.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.controls.Button;
	import feathers.controls.Header;
	import feathers.controls.Panel;
	import feathers.core.PopUpManager;
	import feathers.layout.HorizontalAlign;
	import feathers.layout.VerticalLayout;
	import feathers.utils.display.getDisplayObjectDepthFromStage;

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

	import starling.animation.Transitions;
	import starling.animation.Tween;
	import starling.core.Starling;
	import starling.display.DisplayObject;
	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 pop-up content as a mobile-style drawer that opens from the * bottom of the stage. */ public class BottomDrawerPopUpContentManager extends EventDispatcher implements IPersistentPopUpContentManager, IPopUpContentManagerWithPrompt { /** * @private */ private static const HELPER_POINT:Point = new Point(); /** * Constructor. */ public function BottomDrawerPopUpContentManager() { super(); } /** * @private */ protected var panel:Panel; /** * @private */ protected var content:DisplayObject; /** * @private */ protected var isClosing:Boolean = false; /** * @inheritDoc */ public function get isOpen():Boolean { return this.content !== null; } /** * Adds a style name to the panel that wraps the content. * *

In the following example, a custom style name is provided:

* * * manager.customPanelStyleName = "my-custom-pop-up-panel"; * * @default null */ public var customPanelStyleName:String; /** * @private */ protected var _prompt:String; /** * A prompt to display in the panel's title. * *

Note: If using this manager with a component that has its own * prompt (like PickerList), this value may be overridden * by the component.

* *

In the following example, a custom title is provided:

* * * manager.prompt = "Pick a value"; * * @default null */ public function get prompt():String { return this._prompt; } /** * @private */ public function set prompt(value:String):void { this._prompt = value; } /** * @private */ protected var _closeButtonLabel:String = "Done"; /** * The text to display in the label of the close button. * *

In the following example, a custom close button label is provided:

* * * manager.closeButtonLabel = "Save"; * * @default "Done" */ public function get closeButtonLabel():String { return this._closeButtonLabel; } /** * @private */ public function set closeButtonLabel(value:String):void { this._closeButtonLabel = value; } /** * @private */ protected var _openOrCloseDuration:Number = 0.5; /** * The duration, in seconds, of the animation to open or close the * pop-up. * *

In the following example, the duration is changed to 2 seconds:

* * * manager.openOrCloseDuration = 2.0; * * @default 0.5 */ public function get openOrCloseDuration():Number { return this._openOrCloseDuration; } /** * @private */ public function set openOrCloseDuration(value:Number):void { this._openOrCloseDuration = value; } /** * @private */ protected var _openOrCloseEase:Object = Transitions.EASE_OUT; /** * The easing function used for opening or closing the pop-up. * *

In the following example, the animation ease is changed:

* * * manager.openOrCloseEase = Transitions.EASE_IN_OUT; * * @default starling.animation.Transitions.EASE_OUT * * @see http://doc.starling-framework.org/core/starling/animation/Transitions.html starling.animation.Transitions * @see #openOrCloseDuration */ public function get openOrCloseEase():Object { return this._openOrCloseEase; } /** * @private */ public function set openOrCloseEase(value:Object):void { this._openOrCloseEase = value; } /** * @private */ protected var touchPointID:int = -1; /** * @private */ protected var openTween:Tween; /** * @private */ protected var closeTween:Tween; /** * @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; var layout:VerticalLayout = new VerticalLayout(); layout.horizontalAlign = HorizontalAlign.JUSTIFY; this.panel = new Panel(); if(this.customPanelStyleName) { this.panel.styleNameList.add(this.customPanelStyleName); } this.panel.title = this._prompt; this.panel.layout = layout; this.panel.headerFactory = headerFactory; this.panel.touchable = false; this.panel.addChild(content); PopUpManager.addPopUp(this.panel, true, false); this.layout(); this.panel.addEventListener(Event.REMOVED_FROM_STAGE, panel_removedFromStageHandler); 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.panel); Starling.current.nativeStage.addEventListener(KeyboardEvent.KEY_DOWN, nativeStage_keyDownHandler, false, priority, true); this.panel.y = this.panel.stage.stageHeight; this.openTween = new Tween(this.panel, this.openOrCloseDuration, this.openOrCloseEase); this.openTween.moveTo(0, this.panel.stage.stageHeight - this.panel.height); this.openTween.onComplete = openTween_onComplete; Starling.juggler.add(this.openTween); } /** * @inheritDoc */ public function close():void { if(!this.isOpen || this.isClosing) { return; } if(this.openTween) { Starling.juggler.remove(this.openTween); this.openTween = null; } if(this.content.stage) { this.isClosing = true; this.panel.touchable = false; this.closeTween = new Tween(this.panel, this.openOrCloseDuration, this.openOrCloseEase); this.closeTween.moveTo(0, this.panel.stage.stageHeight); this.closeTween.onComplete = closeTween_onComplete; Starling.juggler.add(this.closeTween); } else { this.cleanup(); this.dispatchEventWith(Event.CLOSE); } } /** * @inheritDoc */ public function dispose():void { this.close(); } /** * @private */ protected function headerFactory():Header { var header:Header = new Header(); var closeButton:Button = new Button(); closeButton.label = this.closeButtonLabel; closeButton.addEventListener(Event.TRIGGERED, closeButton_triggeredHandler); header.rightItems = new [closeButton]; return header; } /** * @private */ protected function layout():void { this.panel.width = this.panel.stage.stageWidth; this.panel.x = 0; this.panel.maxHeight = this.panel.stage.stageHeight; this.panel.validate(); this.panel.y = this.panel.stage.stageHeight - this.panel.height; } /** * @private */ protected function cleanup():void { 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(this.panel) { this.panel.removeEventListener(Event.REMOVED_FROM_STAGE, panel_removedFromStageHandler); if(this.panel.contains(this.content)) { this.panel.removeChild(this.content, false); } this.panel.removeFromParent(true); this.panel = null; } this.content = null; } /** * @private */ protected function openTween_onComplete():void { this.openTween = null; this.panel.touchable = true; this.dispatchEventWith(Event.OPEN); } /** * @private */ protected function closeTween_onComplete():void { this.isClosing = false; this.closeTween = null; this.cleanup(); this.dispatchEventWith(Event.CLOSE); } /** * @private */ protected function closeButton_triggeredHandler(event:Event):void { this.close(); } /** * @private */ protected function panel_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 { if(this.closeTween) { this.closeTween.advanceTime(this.closeTween.totalTime); //the onComplete callback will remove the panel, so no layout is //required. return; } if(this.openTween) { //just stop the animation and go to the final layout Starling.juggler.remove(this.openTween); this.openTween = null; } this.layout(); } /** * @private */ protected function stage_touchHandler(event:TouchEvent):void { if(!PopUpManager.isTopLevelPopUp(this.panel)) { 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); if(!this.panel.contains(hitTestResult)) { 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); if(this.panel.contains(hitTestResult)) { return; } this.touchPointID = touch.id; } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy