diff --git a/.flexLibProperties b/.flexLibProperties index 8938403..eb426a0 100644 --- a/.flexLibProperties +++ b/.flexLibProperties @@ -111,6 +111,7 @@ + diff --git a/bin/flex-extensions.swc b/bin/flex-extensions.swc index 01a2b9b..b3eabd4 100644 Binary files a/bin/flex-extensions.swc and b/bin/flex-extensions.swc differ diff --git a/src/com/codecatalyst/component/behavior/ui/Popup.as b/src/com/codecatalyst/component/behavior/ui/Popup.as index e91aa13..073d29b 100644 --- a/src/com/codecatalyst/component/behavior/ui/Popup.as +++ b/src/com/codecatalyst/component/behavior/ui/Popup.as @@ -2,11 +2,13 @@ package com.codecatalyst.component.behavior.ui { import com.codecatalyst.component.behavior.AbstractBehavior; import com.codecatalyst.component.behavior.IBehavior; + import com.codecatalyst.component.behavior.ui.events.ContentEvent; import com.codecatalyst.factory.ClassFactory; import com.codecatalyst.util.invalidation.InvalidationTracker; import flash.display.DisplayObject; import flash.events.Event; + import flash.events.KeyboardEvent; import flash.events.MouseEvent; import flash.geom.Point; @@ -21,10 +23,12 @@ package com.codecatalyst.component.behavior.ui import mx.managers.PopUpManager; import mx.styles.IStyleClient; - [Event(name="contentChange", type="flash.events.Event")] - [Event(name="contentInitialized", type="flash.events.Event")] - [Event(name="contentReady", type="flash.events.Event")] + [Event(name="contentChange", type="com.codecatalyst.component.behavior.ui.events.ContentEvent")] + [Event(name="contentInitialized", type="com.codecatalyst.component.behavior.ui.events.ContentEvent")] + [Event(name="contentReady", type="com.codecatalyst.component.behavior.ui.events.ContentEvent")] + [Event(name="contentReleased", type="com.codecatalyst.component.behavior.ui.events.ContentEvent")] [Event(name="close", type="flash.events.Event")] + [Event(name="keyDown", type="flash.events.KeyboardEvent")] [DefaultProperty("renderer")] @@ -109,14 +113,19 @@ package com.codecatalyst.component.behavior.ui * parent="{this}" * autoClose="true" * modal="false" - * showEffect="{ new ClassFactory( Fade,null,{duration:600} ) }" + * showEffect="{ new ClassFactory( Fade,null,{duration:600} ) }" * hideEffect="{ new ClassFactory( Fade,null,{duration:400} ) }" * renderer="{ new StyleableFactory( CorrelationWindow, null,{ bottom:100, right:100 } ) }" * xmlns:ui="com.codecatalyst.component.behavior.ui.*" /> * + * <!-- Enabled Swiz injection via SET_UP_BEAN --> + * * <ui:Popup id="performances" * parent="testsGrid" * autoClose="true" modal="true" + * showEffect="{ new ClassFactory( Fade,null,{duration:600} ) }" + * hideEffect="{ new ClassFactory( Fade,null,{duration:400} ) }" + * contentChange="dispatchEvent( new BeanEvent(BeanEvent.SET_UP_BEAN,popup.content) );" * xmlns:ui="com.codecatalyst.component.behavior.ui.*" > * * <mx:Component> @@ -209,10 +218,10 @@ package com.codecatalyst.component.behavior.ui // Listen to ready notification so positioning will work... instance.addEventListener(FlexEvent.CREATION_COMPLETE, onContentReady, false, 0, true); - instance.addEventListener(CloseEvent.CLOSE, onCloseContent, false, 0, true); + instance.addEventListener(CloseEvent.CLOSE, onCloseContent, false, 0, true); instance.addEventListener(FlexEvent.INITIALIZE, onContentInitialized, false, 0 , true); - dispatchEvent(new Event('contentChange')); + dispatchEvent(new ContentEvent(ContentEvent.CONTENT_CHANGE,instance)); } return instance; @@ -332,9 +341,11 @@ package com.codecatalyst.component.behavior.ui instance.removeEventListener(EffectEvent.EFFECT_END, onHideFinished); instance.removeEventListener(CloseEvent.CLOSE, onCloseContent); + instance.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + dispatchEvent( new ContentEvent(ContentEvent.CONTENT_RELEASED,instance) ); instance = null; - dispatchEvent(new Event('contentChange')); + dispatchEvent(new ContentEvent(ContentEvent.CONTENT_CHANGE,null)); } } @@ -401,7 +412,7 @@ package com.codecatalyst.component.behavior.ui { content.removeEventListener(FlexEvent.INITIALIZE, onContentInitialized); - dispatchEvent( new Event('contentInitialized') ); + dispatchEvent( new ContentEvent(ContentEvent.CONTENT_INITIALIZED) ); } @@ -412,10 +423,11 @@ package com.codecatalyst.component.behavior.ui */ protected function onContentReady(event:FlexEvent):void { - content.removeEventListener(FlexEvent.CREATION_COMPLETE, onContentReady); content.stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown,true,0,true); + content.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true); - dispatchEvent( new Event('contentReady') ); + content.removeEventListener(FlexEvent.CREATION_COMPLETE, onContentReady); + dispatchEvent( new ContentEvent(ContentEvent.CONTENT_READY,content) ); showInstance(); @@ -437,7 +449,11 @@ package com.codecatalyst.component.behavior.ui if ( !content ) return; if ( content.stage ) + { content.stage.removeEventListener(MouseEvent.MOUSE_DOWN,onMouseDown,true); + content.stage.removeEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); + } + // This will execute a hideEffect effect IF one has been configured @@ -452,6 +468,16 @@ package com.codecatalyst.component.behavior.ui event.stopPropagation(); } + /** + * The keydown event is dispatched from the popup if no one + * else kills it first. + */ + protected function onKeyDown(event:KeyboardEvent):void + { + dispatchEvent( event.clone() ); + event.stopImmediatePropagation(); + } + /** * * @param event @@ -583,7 +609,10 @@ package com.codecatalyst.component.behavior.ui UIComponent(content).isPopUp = true; if ( content.stage ) + { content.stage.addEventListener(MouseEvent.MOUSE_DOWN,onMouseDown,true,0,true); + content.stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown, false, 0, true); + } content.visible = isContentReady; @@ -990,4 +1019,4 @@ class LayoutConstraints public function get hasConstraints():Boolean { return top || left || bottom || right || horizontalCenter || verticalCenter; } -} \ No newline at end of file +} diff --git a/src/com/codecatalyst/component/behavior/ui/events/ContentEvent.as b/src/com/codecatalyst/component/behavior/ui/events/ContentEvent.as new file mode 100644 index 0000000..b2dfcbf --- /dev/null +++ b/src/com/codecatalyst/component/behavior/ui/events/ContentEvent.as @@ -0,0 +1,27 @@ +package com.codecatalyst.component.behavior.ui.events +{ + import flash.events.Event; + + public class ContentEvent extends Event + { + + public static const CONTENT_CHANGE : String = "contentChange"; + public static const CONTENT_INITIALIZED : String = "contentInitialized"; + public static const CONTENT_READY : String = "contentReady"; + public static const CONTENT_RELEASED : String = "contentReleased"; + + public var content : Object; + + + public function ContentEvent(type:String, content:Object=null) + { + super(type,false,false); + this.content = content; + } + + override public function clone():Event + { + return new ContentEvent(type, content); + } + } +} \ No newline at end of file diff --git a/src/com/codecatalyst/util/DelayedCall.as b/src/com/codecatalyst/util/DelayedCall.as index 14559bf..470ad78 100644 --- a/src/com/codecatalyst/util/DelayedCall.as +++ b/src/com/codecatalyst/util/DelayedCall.as @@ -47,6 +47,11 @@ package com.codecatalyst.util */ protected var args:Array = null; + /** + * Scope context for the function invocation + */ + protected var scope:Object = null; + // ======================================== // Constructor // ======================================== @@ -70,11 +75,11 @@ package com.codecatalyst.util * @param args The parameters to pass to the function / class method. * @param delay The time in milliseconds to delay before making the function / class method call. */ - public static function schedule( func:Function, args:Array, delay:Number ):void + public static function schedule( func:Function, args:Array, delay:Number, scope:Object=null ):void { var call:DelayedCall = new DelayedCall(); - call.initiate( func, args, delay ); + call.initiate( func, args, delay, scope ); // Grab a reference so the call doesn't get prematurely garbage-collected @@ -98,10 +103,11 @@ package com.codecatalyst.util /** * Initiate a delayed call. */ - protected function initiate( func:Function, args:Array, delay:Number ):void + protected function initiate( func:Function, args:Array, delay:Number, scope:Object=null ):void { this.func = func; - this.args = args; + this.args = args || [ ]; + this.scope= scope; // Create and start a timer @@ -122,7 +128,7 @@ package com.codecatalyst.util // Execute the delayed function call if ( func != null ) - func.apply( null, args ); + func.apply( scope, args ); release( this ); } diff --git a/src/com/codecatalyst/util/DictionaryUtil.as b/src/com/codecatalyst/util/DictionaryUtil.as index c36dc17..d1d27b9 100644 --- a/src/com/codecatalyst/util/DictionaryUtil.as +++ b/src/com/codecatalyst/util/DictionaryUtil.as @@ -36,14 +36,22 @@ package com.codecatalyst.util * @param dictionary Dictionary instance * @return Array of keys in the dictionary */ - public static function keys( dictionary:Dictionary ):Array + public static function keys( dictionary:Dictionary, flatten:Boolean=false ):Array { - var keys:Array = []; + var list:Array = []; for ( var key:* in dictionary ) - keys.push( key ); + { + if ( flatten ) + { + if ( dictionary[key] is Dictionary ) + list.concat( keys( dictionary[key] as Dictionary, flatten ) ); + } + else + list.push( key ); + } - return keys; + return list; } /** @@ -52,25 +60,45 @@ package com.codecatalyst.util * @param dictionary Dictionary instance * @return Array of values in the dictionary */ - public static function values( dictionary:Dictionary ):Array + public static function values( dictionary:Dictionary, flatten:Boolean=false ):Array { - var values:Array = []; + var list:Array = []; - for each ( var item:* in dictionary ) - values.push( item ); + for each ( var item:* in dictionary ) + { + if ( flatten ) + { + if (item is Dictionary) + list = list.concat( values( item as Dictionary, flatten ) ); + else if (item is Array) + list = list.concat( item as Array ); + } + else + list.push( item ); + } - return values; + return list; } /** * Returns the number of keys in the specified Dictionary */ - public static function keyCount( dictionary:Dictionary ):int + public static function keyCount( dictionary:Dictionary, flatten:Boolean=false ):int { var count:int = 0; for ( var key:* in dictionary ) - count++; + { + if ( flatten ) + { + if ( dictionary[key] is Dictionary ) + count += keyCount( dictionary[key] as Dictionary, flatten); + else if ( dictionary[key] is Array ) + count += (dictionary[key] as Array).length; + } + else + count += 1; + } return count; } @@ -83,9 +111,9 @@ package com.codecatalyst.util * * @see #values() */ - public static function toArray( dictionary:Dictionary ):Array + public static function toArray( dictionary:Dictionary,flatten:Boolean=false ):Array { - return values( dictionary ); + return values( dictionary, flatten ); } /** diff --git a/src/com/codecatalyst/util/NumberUtil.as b/src/com/codecatalyst/util/NumberUtil.as index f7eb892..417d7dd 100644 --- a/src/com/codecatalyst/util/NumberUtil.as +++ b/src/com/codecatalyst/util/NumberUtil.as @@ -22,49 +22,57 @@ package com.codecatalyst.util { - public class NumberUtil - { - // ======================================== - // Public methods - // ======================================== - - /** - * Comparator function for two Numbers. - */ - public static function compare( a:Number, b:Number ):int - { - if ( a < b ) - { - return -1; - } - else if ( b < a ) - { - return 1; - } - else - { - return 0; - } - } - - /** - * Returns a Boolean indicating whether the specified value is a whole number (ex. 1, 2, 3, etc.). - */ - public static function isWholeNumber( value:* ):Boolean - { - var number:Number = Number( value ); - - return ( Math.floor( Math.abs( number ) ) == value ); - } - - /** - * Returns the first parameter if it is a valid Number, otherwise returns the second parameter. - */ - public static function sanitizeNumber( value:*, otherwise:Number ):Number - { - var number:Number = Number( value ); - - return ( ( value == null ) || isNaN( number ) ) ? otherwise : number; - } - } -} \ No newline at end of file + + public class NumberUtil + { + // ======================================== + // Public methods + // ======================================== + + /** + * Comparator function for two Numbers. + */ + public static function compare(a:Number, b:Number):int + { + if (a < b) + { + return -1; + } + else if (b < a) + { + return 1; + } + else + { + return 0; + } + } + + /** + * Returns a Boolean indicating whether the specified value is a whole number (ex. 1, 2, 3, etc.). + */ + public static function isWholeNumber(value:*):Boolean + { + var number:Number = Number(value); + + return (Math.floor(Math.abs(number)) == value); + } + + /** + * Returns the first parameter if it is a valid Number, otherwise returns the second parameter. + */ + public static function sanitizeNumber(value:*, otherwise:Number):Number + { + var number:Number = Number(value); + + return ((value == null) || isNaN(number)) ? otherwise : number; + } + + public static function inRange(value:*, min:Number, max:Number):Boolean + { + var number:Number = Number(value); + return ((value == null) || isNaN(number)) ? false : ((value >= min) && (value < max)); + + } + } +}