| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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.ios7 |
| { |
| import flash.display.DisplayObject; |
| import flash.events.TimerEvent; |
| import flash.geom.Matrix; |
| import flash.utils.Timer; |
| |
| import mx.core.DPIClassification; |
| |
| import spark.components.BusyIndicator; |
| import spark.skins.ios7.assets.BusyIndicator; |
| import spark.skins.mobile.supportClasses.MobileSkin; |
| |
| public class BusyIndicatorSkin extends MobileSkin |
| { |
| static private const DEFAULT_ROTATION_INTERVAL:Number = 30; |
| private var busyIndicatorClass:Class; |
| private var busyIndicator:DisplayObject; |
| private var busyIndicatorBackground:DisplayObject; |
| private var busyIndicatorDiameter:Number; |
| private var rotationTimer:Timer; |
| private var rotationInterval:Number; |
| private var rotationSpeed:Number; |
| /** |
| * @private |
| * |
| * Current rotation of this component in degrees. |
| */ |
| private var currentRotation:Number = 0; |
| private var symbolColor:uint; |
| private var symbolColorChanged:Boolean = false; |
| |
| public function BusyIndicatorSkin() |
| { |
| super(); |
| |
| busyIndicatorClass = spark.skins.ios7.assets.BusyIndicator; |
| rotationInterval = getStyle("rotationInterval"); |
| if (isNaN(rotationInterval)) |
| rotationInterval = DEFAULT_ROTATION_INTERVAL; |
| if (rotationInterval < 30) //Spokes are at 30 degree angle to each other. |
| rotationInterval = 30; |
| rotationSpeed = 60; |
| |
| switch(applicationDPI) |
| { |
| case DPIClassification.DPI_640: |
| { |
| busyIndicatorDiameter = 104; |
| break; |
| } |
| case DPIClassification.DPI_480: |
| { |
| busyIndicatorDiameter = 80; |
| break; |
| } |
| case DPIClassification.DPI_320: |
| { |
| busyIndicatorDiameter = 52; |
| break; |
| } |
| case DPIClassification.DPI_240: |
| { |
| busyIndicatorDiameter = 40; |
| break; |
| } |
| case DPIClassification.DPI_120: |
| { |
| busyIndicatorDiameter = 20; |
| break; |
| } |
| default://160 DPI |
| { |
| busyIndicatorDiameter = 20; |
| break; |
| } |
| } |
| } |
| |
| 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; |
| } |
| |
| override protected function createChildren():void |
| { |
| //This layer stays still in the background |
| busyIndicatorBackground = new busyIndicatorClass(); |
| busyIndicatorBackground.width = busyIndicatorBackground.height = busyIndicatorDiameter; |
| addChild(busyIndicatorBackground); |
| //This layer rotates in the foreground to give the required effect |
| busyIndicator = new busyIndicatorClass(); |
| busyIndicator.alpha = 0.3; |
| 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(); |
| } |
| } |
| |
| override public function styleChanged(styleProp:String):void |
| { |
| var allStyles:Boolean = !styleProp || styleProp == "styleName"; |
| |
| if (allStyles || styleProp == "symbolColor") |
| { |
| symbolColor = getStyle("symbolColor"); |
| symbolColorChanged = true; |
| invalidateDisplayList(); |
| } |
| if (styleProp == "styleName") { |
| var value:String = getStyle("styleName"); |
| |
| // We're being removed from the stage |
| if (value == null) { |
| stopRotation(); |
| busyIndicatorBackground = null; |
| busyIndicator = null; |
| } |
| } |
| super.styleChanged(styleProp); |
| } |
| |
| override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void |
| { |
| super.updateDisplayList(unscaledWidth,unscaledHeight); |
| if(symbolColorChanged) |
| { |
| colorizeSymbol(); |
| symbolColorChanged = false; |
| } |
| } |
| |
| private function colorizeSymbol():void |
| { |
| super.applyColorTransform(this.busyIndicator, 0x000000, symbolColor); |
| } |
| |
| private function startRotation():void |
| { |
| rotationTimer = new Timer(rotationSpeed); |
| 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,width/2,height/2); |
| event.updateAfterEvent(); |
| } |
| |
| private function rotate(obj:DisplayObject, angle:Number, aroundX:Number, aroundY:Number):void |
| { |
| var center:Number = Math.min(aroundX, aroundY); // stop wobbling if not square |
| var rotationMatrix:Matrix = new Matrix(); |
| rotationMatrix.translate(-center,-center); |
| rotationMatrix.rotate(Math.PI*angle/180); |
| rotationMatrix.translate(center,center); |
| obj.transform.matrix = rotationMatrix; |
| } |
| |
| } |
| } |