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

Reply via email to