Repository: flex-sdk Updated Branches: refs/heads/release4.14.0 8e29f1dad -> f6c82a967
Add non iOS7/Android skinclass and bring back old BusyIndicator behavior - to fix Mustella tests Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/f6c82a96 Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/f6c82a96 Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/f6c82a96 Branch: refs/heads/release4.14.0 Commit: f6c82a967bcf8c8f608b5209866c3404ed798d7d Parents: 8e29f1d Author: OmPrakash Muppirala <[email protected]> Authored: Mon Dec 29 17:53:16 2014 -0800 Committer: OmPrakash Muppirala <[email protected]> Committed: Mon Dec 29 17:57:09 2014 -0800 ---------------------------------------------------------------------- frameworks/projects/mobiletheme/defaults.css | 5 +- .../mobiletheme/src/MobileThemeClasses.as | 1 + .../src/spark/skins/mobile/BusyIndicatorSkin.as | 446 +++++++++++++++++++ .../spark/src/spark/components/BusyIndicator.as | 9 +- 4 files changed, 456 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f6c82a96/frameworks/projects/mobiletheme/defaults.css ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobiletheme/defaults.css b/frameworks/projects/mobiletheme/defaults.css index 7a6548c..6e0edee 100644 --- a/frameworks/projects/mobiletheme/defaults.css +++ b/frameworks/projects/mobiletheme/defaults.css @@ -101,8 +101,7 @@ ActionBar.beveled Group#actionGroup Button.emphasized BusyIndicator { - skinClass: ClassReference("spark.skins.ios7.BusyIndicatorSkin"); - rotationInterval: 30; /* Must be multiples of 30 */ + skinClass: ClassReference("spark.skins.mobile.BusyIndicatorSkin"); } Button @@ -269,7 +268,7 @@ SpinnerList { skinClass: ClassReference("spark.skins.mobile.SpinnerListSkin"); color: #000000; - accentColor: #000000; + accentColor: #0099FF; } SpinnerListContainer http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f6c82a96/frameworks/projects/mobiletheme/src/MobileThemeClasses.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobiletheme/src/MobileThemeClasses.as b/frameworks/projects/mobiletheme/src/MobileThemeClasses.as index 32c2239..70272df 100644 --- a/frameworks/projects/mobiletheme/src/MobileThemeClasses.as +++ b/frameworks/projects/mobiletheme/src/MobileThemeClasses.as @@ -32,6 +32,7 @@ package import spark.skins.mobile.ActionBarSkin; spark.skins.mobile.ActionBarSkin; import spark.skins.mobile.BeveledActionButtonSkin; spark.skins.mobile.BeveledActionButtonSkin; import spark.skins.mobile.BeveledBackButtonSkin; spark.skins.mobile.BeveledBackButtonSkin; + import spark.skins.mobile.BusyIndicatorSkin; spark.skins.mobile.BusyIndicatorSkin; import spark.skins.mobile.ButtonBarSkin; spark.skins.mobile.ButtonBarSkin; import spark.skins.mobile.ButtonSkin; spark.skins.mobile.ButtonSkin; import spark.skins.mobile.CalloutSkin; spark.skins.mobile.CalloutSkin; http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f6c82a96/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as new file mode 100644 index 0000000..194e222 --- /dev/null +++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as @@ -0,0 +1,446 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Licensed to the Apache Software Foundation (ASF) under one or more +// contributor license agreements. See the NOTICE file distributed with +// this work for additional information regarding copyright ownership. +// The ASF licenses this file to You under the Apache License, Version 2.0 +// (the "License"); you may not use this file except in compliance with +// the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +package spark.skins.mobile +{ + + import flash.display.CapsStyle; + import flash.display.Graphics; + import flash.display.LineScaleMode; + import flash.events.TimerEvent; + import flash.geom.Point; + import flash.utils.Timer; + + import mx.core.DPIClassification; + import mx.core.mx_internal; + + import spark.components.BusyIndicator; + import spark.skins.mobile.supportClasses.MobileSkin; + + public class BusyIndicatorSkin extends MobileSkin + { + //-------------------------------------------------------------------------- + // + // Class constants + // + //-------------------------------------------------------------------------- + + /** + * @private + */ + static private const DEFAULT_ROTATION_INTERVAL:Number = 50; + + /** + * @private + */ + static private const DEFAULT_MINIMUM_SIZE:Number = 20; + + /** + * @private + */ + static private const RADIANS_PER_DEGREE:Number = Math.PI / 180; + + public function BusyIndicatorSkin() + { + super(); + alpha = 0.60; // default alpha + + // Set the default measured size depending on the + // applicationDPI + if (applicationDPI == DPIClassification.DPI_640) + { + measuredWidth = 104; + measuredHeight = 104; + } + else if (applicationDPI == DPIClassification.DPI_480) + { + measuredWidth = 80; + measuredHeight = 80; + } + else if (applicationDPI == DPIClassification.DPI_320) + { + measuredWidth = 52; + measuredHeight = 52; + } + else if (applicationDPI == DPIClassification.DPI_240) + { + measuredWidth = 40; + measuredHeight = 40; + } + else if (applicationDPI == DPIClassification.DPI_160) + { + measuredWidth = 26; + measuredHeight = 26; + } + else if (applicationDPI == DPIClassification.DPI_120) + { + measuredWidth = 20; + measuredHeight = 20; + } + else + { + measuredWidth = DEFAULT_MINIMUM_SIZE; + measuredHeight = DEFAULT_MINIMUM_SIZE; + } + + measuredMinWidth = DEFAULT_MINIMUM_SIZE; + measuredMinHeight = DEFAULT_MINIMUM_SIZE; + } + + private var _hostComponent:spark.components.BusyIndicator; + + public function get hostComponent():spark.components.BusyIndicator + { + return _hostComponent; + } + + public function set hostComponent(value:spark.components.BusyIndicator):void + { + _hostComponent = value; + } + + /** + * @private + */ + private var oldUnscaledHeight:Number; + + /** + * @private + */ + private var oldUnscaledWidth:Number; + + /** + * @private + */ + private var rotationTimer:Timer; + + /** + * @private + * + * Current rotation of this component in degrees. + */ + private var currentRotation:Number = 0; + + /** + * @private + * + * Diameter of the spinner for this component. + */ + private var spinnerDiameter:int; + + /** + * @private + * + * Cached value of the spoke color. + */ + private var spokeColor:uint; + + override public function styleChanged(styleProp:String):void + { + super.styleChanged(styleProp); + + var allStyles:Boolean = !styleName || styleName == "styleName"; + + // Check for skin/icon changes here. + // We could only throw out any skins that change, + // but since dynamic re-skinning is uncommon, we'll take + // the simpler approach of throwing out all skins. + if (allStyles || styleName == "rotationInterval") + { + // Update the timer if the rotation interval has changed. + if (isRotating()) + { + stopRotation(); + startRotation(); + } + } + + if (allStyles || styleName == "symbolColor") + { + updateSpinner(spinnerDiameter); + } + } + + override protected function commitCurrentState():void + { + super.commitCurrentState(); + if(currentState == "rotatingState") + { + startRotation(); + } + else + { + stopRotation(); + } + } + + /** + * @private + */ + override protected function updateDisplayList(unscaledWidth:Number, + unscaledHeight:Number):void + { + super.updateDisplayList(unscaledWidth, unscaledHeight); + + // If the size changed, then create a new spinner. + if (oldUnscaledWidth != unscaledWidth || + oldUnscaledHeight != unscaledHeight) + { + var newDiameter:Number; + + newDiameter = calculateSpinnerDiameter(unscaledWidth, unscaledHeight); + updateSpinner(newDiameter); + + oldUnscaledWidth = unscaledWidth; + oldUnscaledHeight = unscaledHeight; + } + } + + //-------------------------------------------------------------------------- + // + // Methods + // + //-------------------------------------------------------------------------- + + /** + * @private + * + * Apply the rules to calculate the spinner diameter from the width + * and height. + * + * @param width new width of this component + * @param height new height of this component + * + * @return true if the spinner's diameter changes, false otherwise. + */ + private function calculateSpinnerDiameter(width:Number, height:Number):Number + { + var diameter:Number = Math.min(width, height); + diameter = Math.max(DEFAULT_MINIMUM_SIZE, diameter); + if (diameter % 2 != 0) + diameter--; + + return diameter; + } + + /** + * @private + * + * Update the spinner properties and redraw. + */ + private function updateSpinner(diameter:Number):void + { + var isRotating:Boolean = isRotating(); + + if (isRotating) + stopRotation(); + + spinnerDiameter = diameter; + spokeColor = getStyle("symbolColor"); + + mx_internal::drawSpinner(); + + if (isRotating) + startRotation(); + } + + /** + * @private + * + * Draw the spinner using the graphics property of this component. + */ + mx_internal function drawSpinner():void + { + var g:Graphics = graphics; + var spinnerRadius:int = spinnerDiameter / 2; + var spinnerWidth:int = spinnerDiameter; + var spokeHeight:Number = spinnerDiameter / 3.7; + var insideDiameter:Number = spinnerDiameter - (spokeHeight * 2); + var spokeWidth:Number = insideDiameter / 5; + var eHeight:Number = spokeWidth / 2; + var spinnerPadding:Number = 0; + + // Undocumented styles to modified the spokeWidth + // and spokeHeight. + // if (getStyle("spokeWidth") !== undefined) + // { + // spokeWidth = getStyle("spokeWidth"); + // eHeight = spokeWidth / 2; + // } + // + // if (getStyle("spokeHeight") !== undefined) + // spokeHeight = getStyle("spokeHeight"); + // + // // spinnerPadding is the padding between the outside + // // edge of the circle and the edge of a spoke. + // if (getStyle("spinnerPadding") !== undefined) + // spinnerPadding = getStyle("spinnerPadding"); + // + // trace("spoke height = " + spokeHeight); + // trace("spoke width = " + spokeWidth); + // trace("center = " + center); + + g.clear(); + + // 1 + drawSpoke(0.20, currentRotation + 300, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 2 + drawSpoke(0.25, currentRotation + 330, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 3 + drawSpoke(0.30, currentRotation, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 4 + drawSpoke(0.35, currentRotation + 30, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 5 + drawSpoke(0.40, currentRotation + 60, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 6 + drawSpoke(0.45, currentRotation + 90, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 7 + drawSpoke(0.50, currentRotation + 120, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 8 + drawSpoke(0.60, currentRotation + 150, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 9 + drawSpoke(0.70, currentRotation + 180, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 10 + drawSpoke(0.80, currentRotation + 210, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 11 + drawSpoke(0.90, currentRotation + 240, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + + // 12 + drawSpoke(1.0, currentRotation + 270, spokeWidth, spokeHeight, spokeColor, spinnerRadius, eHeight, spinnerPadding); + } + + + /** + * @private + * + * @param spokeAlpha: alpha value of the spoke. + * @param spokeWidth: width of the spoke in points. + * @param spokeHeight: the lenght of the spoke in pixels. + * @param spokeColor: the color of the spoke. + * @param spinnerRadius: radius of the spinner. + * @param eHeight: estimated height of the rounded end of the spinner. + * @param spinnerPadding: number of pixels between the outside + * radius of the spinner and the spokes. This is used to make + * spinners with skinny spokes look better by moving them + * closer to the center of the spinner. + */ + private function drawSpoke(spokeAlpha:Number, degrees:int, + spokeWidth:Number, + spokeHeight:Number, + spokeColor:uint, + spinnerRadius:Number, + eHeight:Number, + spinnerPadding:Number):void + { + var g:Graphics = graphics; + + g.lineStyle(spokeWidth, spokeColor, spokeAlpha, false, LineScaleMode.NORMAL, CapsStyle.ROUND); + var outsidePoint:Point = calculatePointOnCircle(spinnerRadius, spinnerRadius - eHeight - spinnerPadding, degrees); + var insidePoint:Point = calculatePointOnCircle(spinnerRadius, spinnerRadius - spokeHeight + eHeight - spinnerPadding, degrees); + g.moveTo(outsidePoint.x, outsidePoint.y); + g.lineTo(insidePoint.x, insidePoint.y); + + } + + /** + * @private + */ + private function calculatePointOnCircle(center:Number, radius:Number, degrees:Number):Point + { + var point:Point = new Point(); + var radians:Number = degrees * RADIANS_PER_DEGREE; + point.x = center + radius * Math.cos(radians); + point.y = center + radius * Math.sin(radians); + + return point; + } + + /** + * @private + */ + private function startRotation():void + { + if (!rotationTimer) + { + var rotationInterval:Number = getStyle("rotationInterval"); + if (isNaN(rotationInterval)) + rotationInterval = DEFAULT_ROTATION_INTERVAL; + + if (rotationInterval < 16.6) + rotationInterval = 16.6; + + rotationTimer = new Timer(rotationInterval); + } + + if (!rotationTimer.hasEventListener(TimerEvent.TIMER)) + { + rotationTimer.addEventListener(TimerEvent.TIMER, timerHandler); + rotationTimer.start(); + } + + } + + /** + * @private + */ + private function stopRotation():void + { + if (rotationTimer) + { + rotationTimer.removeEventListener(TimerEvent.TIMER, timerHandler); + rotationTimer.stop(); + rotationTimer = null; + } + } + + /** + * @private + */ + private function isRotating():Boolean + { + return rotationTimer != null; + } + + /** + * @private + * + * Rotate the spinner once for each timer event. + */ + private function timerHandler(event:TimerEvent):void + { + currentRotation += 30; + if (currentRotation >= 360) + currentRotation = 0; + + mx_internal::drawSpinner(); + event.updateAfterEvent(); + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/f6c82a96/frameworks/projects/spark/src/spark/components/BusyIndicator.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/spark/src/spark/components/BusyIndicator.as b/frameworks/projects/spark/src/spark/components/BusyIndicator.as index 259393d..a78ac8e 100644 --- a/frameworks/projects/spark/src/spark/components/BusyIndicator.as +++ b/frameworks/projects/spark/src/spark/components/BusyIndicator.as @@ -23,6 +23,7 @@ package spark.components import mx.core.IUIComponent; import mx.core.IVisualElement; + import mx.core.mx_internal; import mx.events.FlexEvent; import mx.events.PropertyChangeEvent; import mx.states.State; @@ -139,12 +140,13 @@ package spark.components // Listen to added to stage and removed from stage. // Start rotating when we are on the stage and stop // when we are removed from the stage. - addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); - addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler); + addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler,false,0,true); + addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler,false,0,true); states = [ new State({name:"notRotatingState"}), new State({name:"rotatingState"}) ]; + //mx_internal::skinDestructionPolicy = "auto"; } override protected function commitProperties():void @@ -207,7 +209,10 @@ package spark.components { currentState = "notRotatingState"; + removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); + removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler); removeVisibilityListeners(); + detachSkin(); invalidateSkinState(); }
