Repository: flex-sdk Updated Branches: refs/heads/new_android_skins 75236aa86 -> b019135c8
Added new component MobileBusyIndicator. It has only an Android 4.x specific skin for now. The current BusyIndicator's visual will be moved into an iOS 7 specific skin later. Project: http://git-wip-us.apache.org/repos/asf/flex-sdk/repo Commit: http://git-wip-us.apache.org/repos/asf/flex-sdk/commit/b019135c Tree: http://git-wip-us.apache.org/repos/asf/flex-sdk/tree/b019135c Diff: http://git-wip-us.apache.org/repos/asf/flex-sdk/diff/b019135c Branch: refs/heads/new_android_skins Commit: b019135c8e4d8193f8c7d21ce4bc745bb7e82b3c Parents: 75236aa Author: Om <bigosma...@gmail.com> Authored: Mon Jul 7 18:07:23 2014 -0700 Committer: Om <bigosma...@gmail.com> Committed: Mon Jul 7 18:07:23 2014 -0700 ---------------------------------------------------------------------- .../projects/mobilecomponents/manifest.xml | 1 + .../src/spark/components/MobileBusyIndicator.as | 181 +++++++++++++++++++ .../projects/mobiletheme/src/android4x.css | 6 +- .../spark/skins/android4/BusyIndicatorSkin.as | 180 ++++++++++++++++++ .../src/spark/skins/android4/HSliderSkin.as | 1 - .../skins/android4/assets/BusyIndicator.fxg | 64 +++++++ 6 files changed, 431 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b019135c/frameworks/projects/mobilecomponents/manifest.xml ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobilecomponents/manifest.xml b/frameworks/projects/mobilecomponents/manifest.xml index 810bfea..4e85f42 100644 --- a/frameworks/projects/mobilecomponents/manifest.xml +++ b/frameworks/projects/mobilecomponents/manifest.xml @@ -25,6 +25,7 @@ --> <componentPackage> <component id="ActionBar" class="spark.components.ActionBar"/> + <component id="MobileBusyIndicator" class="spark.components.MobileBusyIndicator" /> <component id="CrossFadeViewTransition" class="spark.transitions.CrossFadeViewTransition"/> <component id="DateSpinner" class="spark.components.DateSpinner"/> <component id="DateSpinnerItemRenderer" class="spark.components.calendarClasses.DateSpinnerItemRenderer"/> http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b019135c/frameworks/projects/mobilecomponents/src/spark/components/MobileBusyIndicator.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobilecomponents/src/spark/components/MobileBusyIndicator.as b/frameworks/projects/mobilecomponents/src/spark/components/MobileBusyIndicator.as new file mode 100644 index 0000000..a257557 --- /dev/null +++ b/frameworks/projects/mobilecomponents/src/spark/components/MobileBusyIndicator.as @@ -0,0 +1,181 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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 components +{ + import flash.events.Event; + import mx.core.IUIComponent; + import mx.core.IVisualElement; + import mx.events.FlexEvent; + import mx.states.State; + import spark.components.supportClasses.SkinnableComponent; + + [SkinState("rotatingState")] + [SkinState("notRotatingState")] + + public class MobileBusyIndicator extends SkinnableComponent + { + private var effectiveVisibility:Boolean = false; + private var effectiveVisibilityChanged:Boolean = true; + + public function BusyIndicator() + { + super(); + // 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); + states = [ + new State({name:"notRotatingState"}), + new State({name:"rotatingState"}) + ]; + } + + override protected function getCurrentSkinState():String + { + return currentState; + } + + private function addedToStageHandler(event:Event):void + { + // Check our visibility here since we haven't added + // visibility listeners yet. + computeEffectiveVisibility(); + + if (canRotate()) + currentState = "rotatingState"; + + addVisibilityListeners(); + invalidateSkinState(); + } + + private function removedFromStageHandler(event:Event):void + { + currentState = "notRotatingState"; + + removeVisibilityListeners(); + invalidateSkinState(); + } + + private function computeEffectiveVisibility():void + { + + // Check our design layer first. + if (designLayer && !designLayer.effectiveVisibility) + { + effectiveVisibility = false; + return; + } + + // Start out with true visibility and enablement + // then loop up parent-chain to see if any of them are false. + effectiveVisibility = true; + var current:IVisualElement = this; + + while (current) + { + if (!current.visible) + { + if (!(current is IUIComponent) || !IUIComponent(current).isPopUp) + { + // Treat all pop ups as if they were visible. This is to + // fix a bug where the BusyIndicator does not spin when it + // is inside modal popup. The problem is in we do not get + // an event when the modal window is made visible in + // PopUpManagerImpl.fadeInEffectEndHandler(). When the modal + // window is made visible, setVisible() is passed "true" so + // as to not send an event. When do get events when the + // non-modal windows are popped up. Only modal windows are + // a problem. + // The downside of this fix is BusyIndicator components that are + // inside of hidden, non-modal, popup windows will paint themselves + // on a timer. + effectiveVisibility = false; + break; + } + } + + current = current.parent as IVisualElement; + } + } + + /** + * The BusyIndicator can be rotated if it is both on the display list and + * visible. + * + * @returns true if the BusyIndicator can be rotated, false otherwise. + */ + private function canRotate():Boolean + { + if (effectiveVisibility && stage != null) + return true; + + return false; + } + + + /** + * @private + * Add event listeners for SHOW and HIDE on all the ancestors up the parent chain. + * Adding weak event listeners just to be safe. + */ + private function addVisibilityListeners():void + { + var current:IVisualElement = this.parent as IVisualElement; + while (current) + { + // add visibility listeners to the parent + current.addEventListener(FlexEvent.HIDE, visibilityChangedHandler, false, 0, true); + current.addEventListener(FlexEvent.SHOW, visibilityChangedHandler, false, 0, true); + + current = current.parent as IVisualElement; + } + } + + /** + * @private + * Remove event listeners for SHOW and HIDE on all the ancestors up the parent chain. + */ + private function removeVisibilityListeners():void + { + var current:IVisualElement = this; + while (current) + { + current.removeEventListener(FlexEvent.HIDE, visibilityChangedHandler, false); + current.removeEventListener(FlexEvent.SHOW, visibilityChangedHandler, false); + + current = current.parent as IVisualElement; + } + } + + /** + * @private + * Event call back whenever the visibility of us or one of our ancestors + * changes + */ + private function visibilityChangedHandler(event:FlexEvent):void + { + effectiveVisibilityChanged = true; + invalidateProperties(); + } + + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b019135c/frameworks/projects/mobiletheme/src/android4x.css ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobiletheme/src/android4x.css b/frameworks/projects/mobiletheme/src/android4x.css index 02511c1..b04cb20 100644 --- a/frameworks/projects/mobiletheme/src/android4x.css +++ b/frameworks/projects/mobiletheme/src/android4x.css @@ -19,7 +19,6 @@ @namespace "library://ns.adobe.com/flex/spark"; - /* Android 4.x specific Mobile Flex skins and styles. Defaults sizes are based on application-dpi=240. @@ -82,6 +81,11 @@ ActionBar Group#actionGroup Button skinClass: ClassReference("spark.skins.android4.TransparentActionButtonSkin"); } +MobileBusyIndicator +{ + skinClass: ClassReference("spark.skins.android4.BusyIndicatorSkin"); +} + Button { fontFamily: RobotoBold; http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b019135c/frameworks/projects/mobiletheme/src/spark/skins/android4/BusyIndicatorSkin.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/BusyIndicatorSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/BusyIndicatorSkin.as new file mode 100644 index 0000000..dd3aa44 --- /dev/null +++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/BusyIndicatorSkin.as @@ -0,0 +1,180 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// 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.android4 +{ + import flash.display.DisplayObject; + import flash.events.TimerEvent; + import flash.geom.Matrix; + import flash.utils.Timer; + import mx.core.DPIClassification; + import spark.skins.android4.assets.BusyIndicator; + import spark.skins.mobile.supportClasses.MobileSkin; + + import spark.components.MobileBusyIndicator; + + public class BusyIndicatorSkin extends MobileSkin + { + static private const DEFAULT_ROTATION_INTERVAL:Number = 50; + private var busyIndicatorClass:Class; + private var busyIndicator:DisplayObject; + private var busyIndicatorDiameter:Number; + private var rotationTimer:Timer; + private var rotationInterval:Number; + /** + * @private + * + * Current rotation of this component in degrees. + */ + private var currentRotation:Number = 0; + + public function BusyIndicatorSkin() + { + super(); + + busyIndicatorClass = spark.skins.android4.assets.BusyIndicator; + rotationInterval = getStyle("rotationInterval"); + if (isNaN(rotationInterval)) + rotationInterval = DEFAULT_ROTATION_INTERVAL; + if (rotationInterval < 16.6) + rotationInterval = 16.6; + + switch(applicationDPI) + { + case DPIClassification.DPI_640: + { + busyIndicatorDiameter = 144; + break; + } + case DPIClassification.DPI_480: + { + busyIndicatorDiameter = 108; + break; + } + case DPIClassification.DPI_320: + { + busyIndicatorDiameter = 72; + break; + } + case DPIClassification.DPI_240: + { + busyIndicatorDiameter = 54; + break; + } + case DPIClassification.DPI_120: + { + busyIndicatorDiameter = 27; + break; + } + default://160 DPI + { + busyIndicatorDiameter = 36; + break; + } + } + } + + private var _hostComponent:spark.components.MobileBusyIndicator; + + public function get hostComponent():spark.components.MobileBusyIndicator + { + return _hostComponent; + } + + public function set hostComponent(value:spark.components.MobileBusyIndicator):void + { + _hostComponent = value; + } + + override protected function createChildren():void + { + busyIndicator = new busyIndicatorClass(); + busyIndicator.width = busyIndicator.height = busyIndicatorDiameter; + addChild(busyIndicator); + } + + override protected function measure():void + { + measuredWidth = busyIndicatorDiameter; + measuredHeight = busyIndicatorDiameter; + + measuredMinHeight = busyIndicatorDiameter; + measuredMinWidth = busyIndicatorDiameter + } + + override protected function commitCurrentState():void + { + super.commitCurrentState(); + if(currentState == "rotatingState") + { + startRotation(); + } + else + { + stopRotation(); + } + } + + private function startRotation():void + { + rotationTimer = new Timer(rotationInterval); + if (!rotationTimer.hasEventListener(TimerEvent.TIMER)) + { + rotationTimer.addEventListener(TimerEvent.TIMER, timerHandler); + rotationTimer.start(); + } + } + + private function stopRotation():void + { + if (rotationTimer) + { + rotationTimer.removeEventListener(TimerEvent.TIMER, timerHandler); + rotationTimer.stop(); + rotationTimer = null; + } + } + + /** + * @private + * + * Rotate the spinner once for each timer event. + */ + private function timerHandler(event:TimerEvent):void + { + currentRotation += rotationInterval; + if (currentRotation >= 360) + currentRotation = 0; + + rotate(busyIndicator,currentRotation,measuredWidth/2,measuredHeight/2); + event.updateAfterEvent(); + } + + private var rotationMatrix:Matrix; + private function rotate(obj:DisplayObject, angle:Number, aroundX:Number, aroundY:Number):void + { + rotationMatrix = new Matrix(); + rotationMatrix.translate(-aroundX,-aroundY); + rotationMatrix.rotate(Math.PI*angle/180); + rotationMatrix.translate(aroundX,aroundY); + obj.transform.matrix = rotationMatrix; + } + + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b019135c/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as index 66ee390..6f970f8 100644 --- a/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as +++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as @@ -28,7 +28,6 @@ package spark.skins.android4 import spark.components.Button; import spark.components.HSlider; - import spark.components.ToggleSwitch; import spark.skins.android4.assets.HSliderTrack_filled; import spark.skins.mobile.supportClasses.HSliderDataTip; import spark.skins.mobile.supportClasses.MobileSkin; http://git-wip-us.apache.org/repos/asf/flex-sdk/blob/b019135c/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/BusyIndicator.fxg ---------------------------------------------------------------------- diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/BusyIndicator.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/BusyIndicator.fxg new file mode 100644 index 0000000..e04248f --- /dev/null +++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/BusyIndicator.fxg @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> + +<Graphic version="2.0" xmlns="http://ns.adobe.com/fxg/2008" viewWidth="36" viewHeight="36"> + <Group> + <Group x="-12.8125" y="-6.73926"> + <mask> + <Group x="12.8496" y="6.6665"> + <Path winding="nonZero" data="M0 18.0117C0 27.9429 6.96289 35.9961 17.9629 36.0239L17.9629 33.0127C8.96289 32.9858 3.01074 26.2813 3.01074 18.0117 3.01074 9.74316 8.96289 3.03809 17.9629 3.00977L17.9629 0C6.96289 0.027832 0 8.08008 0 18.0117Z"> + <fill> + <SolidColor color="#FFFFFF"/> + </fill> + </Path> + </Group> + </mask> + <Path winding="nonZero" data="M0 36.7485 16.332 0 44.7012 12.6084 28.3691 49.3569 0 36.7485Z"> + <fill> + <LinearGradient x="13.4458" y="44.7148" scaleX="27.8603" rotation="293.962"> + <GradientEntry ratio="0" color="#FFFFFF"/> + <GradientEntry ratio="0.576638" color="#B4B4B3"/> + <GradientEntry ratio="0.820765" color="#9C9C9B"/> + <GradientEntry ratio="1" color="#919190"/> + </LinearGradient> + </fill> + </Path> + </Group> + <Group x="2.61719" y="-8"> + <mask> + <Group x="15.3828" y="7.92773"> + <Path winding="nonZero" data="M0 3.00977C8 3.03809 14.9512 9.74316 14.9512 18.0117 14.9512 26.2813 8 32.9858 0 33.0127L0 36.0239C10 35.9961 17.9629 27.9429 17.9629 18.0117 17.9629 8.08008 10 0.027832 0 0L0 3.00977Z"> + <fill> + <SolidColor color="#FFFFFF"/> + </fill> + </Path> + </Group> + </mask> + <Path winding="nonZero" data="M49.7617 34.4028 29.1016 0 0 17.4766 20.6621 51.8799 49.7617 34.4028Z"> + <fill> + <LinearGradient x="37.6406" y="47.1841" scaleX="27.7241" rotation="239.012"> + <GradientEntry ratio="0" color="#919190"/> + <GradientEntry ratio="1" color="#FFFFFF"/> + </LinearGradient> + </fill> + </Path> + </Group> + </Group> +</Graphic> \ No newline at end of file