+
+Permission to use, copy, modify, distribute and sell this software and its documentation for any purpose
+is hereby granted without fee, provided that the above copyright notice appear in all copies and
+that both that copyright notice and this permission notice appear in supporting documentation.
+CERN makes no representations about the suitability of this software for any purpose.
+It is provided "as is" without expressed or implied warranty.
+
+This product bundles software available under a
+BSD software license. For details, see lib/external/saxon9-NOTICES/THAI.txt
+
+This product bundles software available under a
+MIT software license. For details, see lib/external/saxon9-NOTICES/UNICODE.txt
+
+This product bundles software available under a
+MIT software license. For details, see lib/external/saxon9-NOTICES/JAMESCLARK.txt
+
------------------------------------------------------------------------------------------
-lib/xercesImpl.jar (Xerces-J-bin.2.9.1.zip)
+lib/external/xml-apis.jar
+
+This product bundles documents available under a
+W3C document license. For details, see lib/external/xml-apis-LICENSES/LICENSE.dom-documentation.txt
- Apache License Version 2.0, January 2004
-
- See notice file at lib/xerces-NOTICES/NOTICE
- See license file at lib/xerces-NOTICES/LICENSE
+This product bundles software available under a
+W3C software license. For details, see lib/external/xml-apis-LICENSES/LICENSE.dom-software.txt
+
+This product bundles SAX2 available under a Public Domain license.
+For more details see lib/external/xml-apis-LICENSES/LICENSE.sax.txt
------------------------------------------------------------------------------------------
-lib/xalan.jar (xalan-j_2_6_0-bin.tar.gz)
+lib/external/xml-apis-ext.jar
+
+This product bundles documents available under a
+W3C document license. For details, see lib/external/xml-apis-ext-LICENSES/LICENSE.dom-documentation.txt
- Apache License Version 2.0, January 2004
-
- See notice file at lib/xalan-NOTICE
- See license file at lib/xalan-LICENSE
+This product bundles software available under a
+W3C software license. For details, see lib/external/xml-apis-ext-LICENSES/LICENSE.dom-software.txt
------------------------------------------------------------------------------------------
-lib/xalan.jar (xalan-j_2_6_0-bin.tar.gz)
+lib/external/xalan.jar
+
+This product bundles Apache Commons BCEL available under a
+Apache Software License, Version 1.1. For details, see lib/external/xalan-LICENSES/BCEL.LICENSE.txt
- Apache License Version 2.0, January 2004
-
- See the Apache License, Version 2.0 at the top of this file.
+This product bundle CUP Parser Generator available under an (old style)
+MIT license. For details, see lib/external/xalan-LICENSES/java_cup.LICENSE.txt
+
+This product bundles Jakarta Regexp available under a
+Apache Software License, Version 1.1. For details,
+see lib/external/xalan-LICENSES/LICENSE.dom-software.txt
------------------------------------------------------------------------------------------
+
+
diff --git a/NOTICE b/NOTICE
index ca0b3ca931..a78d131dc3 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,27 +1,40 @@
Apache Flex
-Copyright 2014 The Apache Software Foundation
+Copyright 2012-2015 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
-The Initial Developer of the Original Code, known as Adobe Flex,
-is Adobe Systems Incorporated (http://www.adobe.com/).
+The Initial Developer of the Original Code, known as Adobe Flex, is Adobe
+Systems Incorporated (http://www.adobe.com/).
Copyright 2003 - 2012 Adobe Systems Incorporated. All Rights Reserved.
The asc compiler contains code written by Jeff Dyer at:
Copyright Mountain View Compiler Company (1998-2003).
-The easing equations in the mx tween class are based on code written by Robert Penner.
- Copyright 2001 Robert Penner
- All rights reserved.
+The easing equations in the mx tween class are based on code written by Robert
+Penner.
+ Copyright 2001 Robert Penner. All rights reserved.
-The Batik SVG toolkit source contains code from the World Wide Web Consortium (W3C) for
- the Document Object Model API (DOM API) and SVG Document Type Definition (DTD).
+The Batik SVG toolkit source contains code from the World Wide Web Consortium
+(W3C) for the Document Object Model API (DOM API) and SVG Document Type
+Definition (DTD).
-The Batik SVG toolkit source contains code from the International Organisation for
- Standardization for the definition of character entities used in the software's
- documentation.
+The Batik SVG toolkit source contains code from the International Organisation
+for Standardization for the definition of character entities used in the
+software's documentation.
+
+The Batik SVG toolkit source includes images from the Tango Desktop Project
+(http://tango.freedesktop.org/).
+
+The Batik SVG toolkit source includes images from the Pasodoble Icon Theme
+(http://www.jesusda.com/projects/pasodoble).
+
+Portions of Xerces were originally based on the following:
+ - software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
+ - software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
+ - voluntary contributions made by Paul Eng on behalf of the
+ Apache Software Foundation that were originally developed at iClick, Inc.
+ software copyright (c) 1999.
+
+Changes to Xerces sources in this product were developed by Adobe Systems Inc.
-The Open Source Media Framework used by the video components is licensed under the
- Mozilla Public License Version 1.1. The source code can be found here:
- http://sourceforge.net/projects/osmf.adobe/files/OSMF%201.0%20%28final%20source%2C%20ASDocs%2C%20PDF%20guides%2C%20and%20release%20notes%29/OSMF_1.0.zip
diff --git a/NOTICE.asc b/NOTICE.asc
new file mode 100644
index 0000000000..de97becf23
--- /dev/null
+++ b/NOTICE.asc
@@ -0,0 +1,13 @@
+Apache Flex
+Copyright 2012-2015 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+The Initial Developer of the Original Code, known as Adobe Flex, is Adobe
+Systems Incorporated (http://www.adobe.com/).
+ Copyright 2003 - 2012 Adobe Systems Incorporated. All Rights Reserved.
+
+The asc compiler contains code written by Jeff Dyer at:
+ Copyright Mountain View Compiler Company (1998-2003).
+
diff --git a/NOTICE.base b/NOTICE.base
new file mode 100644
index 0000000000..8b91f51217
--- /dev/null
+++ b/NOTICE.base
@@ -0,0 +1,9 @@
+Apache Flex
+Copyright 2012-2015 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+The Initial Developer of the Original Code, known as Adobe Flex, is Adobe
+Systems Incorporated (http://www.adobe.com/).
+ Copyright 2003 - 2012 Adobe Systems Incorporated. All Rights Reserved.
diff --git a/NOTICE.bin b/NOTICE.bin
new file mode 100644
index 0000000000..6243f66402
--- /dev/null
+++ b/NOTICE.bin
@@ -0,0 +1,49 @@
+
+Portions of Apache Xerces were originally based on the following:
+ - software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
+ - software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
+ - voluntary contributions made by Paul Eng on behalf of the
+ Apache Software Foundation that were originally developed at iClick, Inc.,
+ software copyright (c) 1999.
+
+Portions of Apache Xerces was originally based on the following:
+ - software copyright (c) 1999-2002, Lotus Development Corporation.,
+ http://www.lotus.com.
+ - software copyright (c) 2001-2002, Sun Microsystems.,
+ http://www.sun.com.
+ - software copyright (c) 2003, IBM Corporation.,
+ http://www.ibm.com.
+
+Portions of Apache Xerces are derived from classes placed in the public domain
+by Arbortext on 10 Apr 2000. See:
+ http://www.arbortext.com/customer_support/updates_and_technical_notes/catalogs/docs/README.htm
+
+Portions of Apache Xalan were originally based on the following:
+ - software copyright (c) 1999-2002, Lotus Development Corporation.,
+ http://www.lotus.com.
+ - software copyright (c) 2001-2002, Sun Microsystems.,
+ http://www.sun.com.
+ - software copyright (c) 2003, IBM Corporation., http://www.ibm.com.
+ - voluntary contributions made by Ovidiu Predescu on
+ behalf of the Apache Software Foundation that was originally developed
+ at Hewlett Packard Company.
+
+Apache Xalan includes software developed by the following:
+ - The Apache Software Foundation (see BCEL.README.txt, ant.README.txt,
+ regexp.README.txt, stylebook-1.0-b3_xalan-2.README.txt,
+ xercesImpl.README.txt, xml-apis.README.txt)
+ - International Business Machines Corporation (see bsf.README.txt)
+ - World Wide Web Consortium (see jtidy.README.txt)
+ - Elliot Joel Berk and C. Scott Ananian (see JLex.README.txt)
+ - Scott Hudson, Frank Flannery, C. Scott Ananian
+ (see java_cup.READNE.txt, runtime.README.txt)
+
+Portions of Apache XML Commons were originally based on the following:
+ - software copyright (c) 1999, IBM Corporation., http://www.ibm.com.
+ - software copyright (c) 1999, Sun Microsystems., http://www.sun.com.
+ - software copyright (c) 2000 World Wide Web Consortium, http://www.w3.org
+
+Portions of Saxon9 are derived from classes placed in the
+public domain by Arbortext on 10 Apr 2000. See:
+ http://www.arbortext.com/customer_support/updates_and_technical_notes/catalogs/docs/README.htm
+
diff --git a/NOTICE.pb b/NOTICE.pb
index bbf5c9a212..5aa29006ab 100644
--- a/NOTICE.pb
+++ b/NOTICE.pb
@@ -1,5 +1,5 @@
Apache Flex
-Copyright 2014 The Apache Software Foundation
+Copyright 2012-2015 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
diff --git a/README b/README
index 8d0ffda786..93e839e4b7 100644
--- a/README
+++ b/README
@@ -1,599 +1,505 @@
-Apache Flex (Flex)
-==================
+The Apache Flex SDK
+===================
- Apache Flex SDK is an application development framework for easily building
- Flash-based applications for mobile devices, web browsers, and desktops.
+The Apache Flex SDK is the evolution of the popular Adobe Flex SDK. The Apache
+Flex SDK is an application development framework for easily building Flash
+based applications for mobile devices, web browsers, and desktop platforms.
+Currently supported platforms include:
- Apache Flex 4.13.0 is a follow up release to Apache Flex 4.12.1. This version
- adds new features and implements bug fixes that were unavailable in previous
- versions. It is compatible with most code written to target Adobe Flex 4.6.
+ Microsoft Windows
+ Mac OS X
+ Apple iOS
+ Google Android
+ RIM BlackBerry
+ (Linux)
+
+Linux support is currently experimental and you may run into issues. The Apache
+Flex project would like to see a fully supported Linux release, but we need
+help from the community in order to do that. Please help out if you can.
+
+For more information about the Apache Flex project, please visit:
- For detailed information about Apache Flex please visit
http://flex.apache.org/
- Apache Flex is a large project with many pieces. The framework is
- implemented in ActionScript and the compiler is implemented in Java.
+The Apache Flex SDK 4.14.0 is a follow up release to version 4.13.0. It is
+compatible with most code written for the original Adobe Flex 4.6 SDK.
- Currently supported platforms include:
- Microsoft Windows
- Mac OS X
- Apple iOS
- Google Android
- RIM BlackBerry
- Linux
- Apache Flex is the software evolution of the popular Adobe Flex SDK project.
+Installing the Apache Flex SDK
+==============================
- The community surrounding Flex is vast, diverse, distributed globally, and
- with all levels of proficiency in software development.
+The Apache Flex SDK Installer is an AIR application that simplifies the
+download and installation of the Apache Flex SDK and its (required) components.
+It is aimed at anyone who wants to use the latest release of the Apache Flex
+SDK, but who might not necessarily be familiar with the tools and procedures
+required to compile the Apache Flex SDK from source code. The application will
+grab the binary distribution of the SDK from apache.org or one of its mirrors,
+install it onto your computer and prepare it for use with your favourite IDE
+such as Adobe Flash Builder or JetBrains IntelliJ IDEA.
- There has been more that 30,000 installs of Apache Flex. The Apache Flex web
- site gets 3 quarters of a million page views a year and more than 250,000
- unique visitors a year.
+You can get the Apache Flex SDK Installer from the Apache Flex website at:
+ http://flex.apache.org/installer.html
-Getting the convenience packages for Apache Flex
-================================================
+Starting with the Apache Flex SDK 4.12, Linux users can install the binary
+distribution using ANT. More information about installing the binary package
+with ANT can be found on our wiki at:
- The Apache Flex SDK Installer is an application that simplifies the download
- and installation of the Apache Flex SDK and its (required) components. It is
- aimed at anyone who wants to use the latest release of the Apache Flex SDK,
- but who might not necessarily be familiar with the tools and procedures
- required to compile the Apache Flex SDK from source code. The application
- will grab the binary distribution of the SDK from apache.org or one of its
- mirrors, install it onto your computer and prepare it for use with your
- favorite IDE such as Adobe Flash Builder or JetBrains IntelliJ IDEA.
+ https://cwiki.apache.org/confluence/display/FLEX/Installation+help#Installationhelp-Antinstaller
- You can get the SDK Installer from the Apache Flex website at
- http://flex.apache.org/installer.html
- The SDK installer requires the Adobe AIR runtime to be installed.
+Building the Apache Flex SDK from source
+========================================
- Starting with Apache Flex 4.12 the binary distribution can be installed
- using only ANT in addition to the AIR installer mentioned above. This is
- the recommended method for Linux users. More information about installing
- the binary package with ANT can be found on our wiki at :
+The Apache Flex SDK is a large project. It requires build tools which must be
+installed on your system and it depends on some external software. The external
+software is downloaded as part of the build process.
- https://cwiki.apache.org/confluence/display/FLEX/Installation+help#Installationhelp-Antinstaller
+There are two ways to get the SDK source.
+1) from a git repository
+2) from a source package distribution
-Getting the latest sources via git
-==================================
+The following steps are all you need for a fully functional SDK:
+- Prepare your system
+ - install external software
+ - set environment variables
+- Get the source code
+- Build the SDK
+- Prepare the SDK for use with an IDE
+- Optional steps:
+ - Flash Player configuration
+ - Other locale support
- Getting the source code is the recommended way to get Apache Flex. We also
- offer an automated installer along with binary distributions on our website
- at http://flex.apache.org/.
- You can always checkout the latest source via git using the following
- command:
+Prepare your system
+-------------------
- git clone https://git-wip-us.apache.org/repos/asf/flex-sdk.git sdk
- cd sdk
- git checkout develop
+Before building the Apache Flex SDK you must install the following software and
+set the corresponding environment variables. Make sure to use absolute paths,
+relative paths will result in build errors.
- An Apache Flex SDK also requires source code from other Apache Flex git
- repositories. To get the latest source via git for the Text Layout
- Framework use the following command:
+The environment variables PLAYERGLOBAL_HOME, AIR_HOME, FLASHPLAYER_DEBUGGER,
+TLF_HOME, BLAZEDS_HOME and ADOBE_EXTENSION_MANAGER can also be set in a
+property file called env.properties. See the env-template.properties file
+for instructions.
- git clone https://git-wip-us.apache.org/repos/asf/flex-tlf.git tlf
- cd tlf
- git checkout develop
+The Adobe Flash Player and Adobe AIR have non Apache compatible licenses so
+they can not be bundled with the Apache Flex SDK and need to be installed
+separately.
- In an Apache Flex source code package hosted on the distribution server or
- one of its mirrors, the Text Layout Framework code is already included in
- the package. This is also true for the convenience package.
+The Adobe Flash Player ‘playerglobal.swc’ is needed to compile all the
+components with the exception of the ‘airframework’ and ‘airspark’
+components, which require ‘airglobal.swc’ from the AIR Integration Kit. The
+AIR Integration kit is also needed to build and debug mobile and desktop
+applications. The Adobe Flash Player content debugger is used by the ant
+‘checkintests’ target and other pieces of the test subsystem to run compiled
+applications.
- Linux support is currently experimental and you may run into issues. Apache
- Flex would like to see a fully supported Linux release, but we need support
- from the community in order to do that. Please help out if you can.
- For further information visit http://flex.apache.org/download-source.html
+---------------------------------------------------------------------
+SOFTWARE ENVIRONMENT VARIABLE
+---------------------------------------------------------------------
-Building Apache Flex 4.13.0
-=========================
+Java SDK 1.6 or greater (* 1) JAVA_HOME
+ (for Java 1.7 see note at (* 2))
- Apache Flex is a large project. It requires some build tools which must be
- installed prior to building Flex and it depends on some external software
- which are downloaded as part of the build process. Some of these have
- different licenses. See the Software Dependencies section for more
- information on the external software dependencies.
+Ant 1.7.1 or greater (* 1) ANT_HOME
+ (for Java 1.7 see note at (* 2))
- From Apache's perspective, the Adobe Flash Player and Adobe AIR have
- excluded licenses so they can not be bundled with the Apache Flex binaries.
- They must be installed prior to building Apache Flex.
+Adobe AIR Integration Kit (* 3) AIR_HOME
- Linux support is currently experimental and while it is possible to compile
- the SDK it has not been fully tested so you may run into issues.
+Adobe Flash Player Content Debugger (* 4) FLASHPLAYER_DEBUGGER
-Install Prerequisites
----------------------
+Adobe Flash Player playerglobal swcs (* 5) PLAYERGLOBAL_HOME
- Before building Flex you must install the following software and set the
- corresponding environment variables using absolute file paths. Relative
- file paths will result in build errors.
+Optional: Text Layout Framework (* 6) TLF_HOME
- The environment variables PLAYERGLOBAL_HOME, AIR_HOME, FLASHPLAYER_DEBUGGER,
- TLF_HOME, and ADOBE_EXTENSION_MANAGER can also be set in the property file
- called env.properties. See the env-template.properties file for
- instructions.
+Optional: Adobe Extension Manager CS5 (* 7) ADOBE_EXTENSION_MANAGER
- The Adobe Flash Player playerglobal.swc is needed to compile all the
- components
- with the exception of the airframework and airspark components which require
- airglobal.swc from the AIR Integration Kit. The AIR Integration kit is also
- needed to build and debug mobile applications. The Adobe Flash Player
- content debugger is used by checkintests and other pieces of the test
- subsystem to run compiled applications.
+Optional: Flex Messaging Common (* 8) BLAZEDS_HOME
- The build scripts assume that the source code folder containing the Text
- Layout Framework (tlf) folder is at the same level as the sdk folder or
- located inside the frameworks/projects folder. If this is not true, then
- you must set the TLF_HOME environment variable to point to the tlf folder.
+---------------------------------------------------------------------
- ==================================================================================
- SOFTWARE ENVIRONMENT VARIABLE (absolute paths)
- ==================================================================================
+* 1)
+The bin directories for ANT_HOME and JAVA_HOME should be added to your PATH.
- Java SDK 1.6 or greater (*1) JAVA_HOME
- (for Java 1.7 see note at (*2))
+On Windows, set PATH to
- Ant 1.7.1 or greater (*1) ANT_HOME
- (for Java 1.7 see note at (*2))
+ PATH=%PATH%;%ANT_HOME%\bin;%JAVA_HOME%\bin
- Adobe AIR Integration Kit (*3) AIR_HOME
+On the Mac (bash), set PATH to
- Adobe Flash Player Content Debugger (*4) FLASHPLAYER_DEBUGGER
+ export PATH='$PATH:$ANT_HOME/bin:$JAVA_HOME/bin'
- Adobe Flash Player playerglobal swcs (*5) PLAYERGLOBAL_HOME
+On Linux make sure your path includes ANT_HOME and JAVA_HOME.
- Adobe Extension Manager CS5 (*6) ADOBE_EXTENSION_MANAGER
+* 2)
+If you are using Java SDK 1.7 or greater on a Mac you must use Ant 1.8 or
+greater. If you use Java 1.7 with Ant 1.7, ant reports the java version as
+1.6 so the JVM args for the data model (-d32/-d64) will not be set correctly
+and you will get compile errors.
- Text Layout Framework TLF_HOME
+* 3)
+The Adobe AIR integration kit for Windows can be downloaded from:
- ==================================================================================
+ http://airdownload.adobe.com/air/win/download/16.0/AdobeAIRSDK.zip
- *1) The bin directories for ANT_HOME and JAVA_HOME should be added to your
- PATH.
+The Adobe AIR integration kit for Mac can be downloaded from:
- On Windows, set PATH to
+ http://airdownload.adobe.com/air/mac/download/16.0/AdobeAIRSDK.tbz2
- PATH=%PATH%;%ANT_HOME%\bin;%JAVA_HOME%\bin
+The Adobe AIR integration kit for Linux can be downloaded from:
- On the Mac (bash), set PATH to
+ http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRSDK.tbz2
- export PATH="$PATH:$ANT_HOME/bin:$JAVA_HOME/bin"
+Download the AIR SDK for your platform and unzip it. Set AIR_HOME to the
+absolute path of the AIR SDK directory.
- On Linux make sure you path include ANT_HOME and JAVA_HOME.
+This version of the Apache Flex SDK was certified for use with Adobe AIR 16
+and is compatible with version 3.1 and up. It has been fully tested on AIR 3.7,
+4 and 16.
- *2) If you are using Java SDK 1.7 or greater on a Mac you must use Ant 1.8
- or greater. If you use Java 1.7 with Ant 1.7, ant reports the java
- version as 1.6 so the JVM args for the data model (-d32/-d64) will not
- be set correctly and you will get compile errors.
+* 4)
+The Adobe Flash Player content debuggers can be found here:
- *3) The Adobe AIR integration kit for Windows can be downloaded from:
- http://airdownload.adobe.com/air/win/download/14.0/AdobeAIRSDK.zip
+ http://www.adobe.com/support/flashplayer/downloads.html
- The Adobe AIR integration kit for Mac can be downloaded from:
- http://airdownload.adobe.com/air/mac/download/14.0/AdobeAIRSDK.tbz2
+This version of the Apache Flex SDK was certified for use with Adobe Flash
+Player 11.1, and is compatible with version 10.2 and up. It has been tested
+with versions 11.1, 11.7, 13.0 and 16.0 on Windows and Mac. It has been
+compiled, but not fully tested, against other Adobe Flash Player versions.
+It has not been fully tested on Linux.
- The Adobe AIR integration kit for Linux can be downloaded from:
- http://airdownload.adobe.com/air/lin/download/2.6/AdobeAIRSDK.tbz2
+On Windows, set FLASHPLAYER_DEBUGGER to the absolute path including the
+filename of the FlashPlayerDebugger.exe. Note the filename of flash player
+debugger may be different, e.g. C:\MyPath\FlashPlayerDebugger.exe.
- This version of Apache Flex was certified for use with AIR 14.0, and
- should be compatible with other versions of AIR newer than 3.1. However
- it hasn't been fully tested on AIR 3.2, 3.3, 3.5, 3.6 or 3.7.
+On the Mac, set FLASHPLAYER_DEBUGGER to the absolute path of
+'Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger'
- Download the AIR SDK for your platform and unzip it. Set AIR_HOME to the
- absolute path of the AIR SDK directory.
+On Linux, set FLASHPLAYER_DEBUGGER to the absolute path of flashplayerdebugger.
- *4) The Adobe Flash Player content debuggers can be found here:
- http://www.adobe.com/support/flashplayer/downloads.html
+* 5)
+The Adobe Flash Player playerglobal.swc for 11.1 can be downloaded from:
- This version of Apache Flex was certified for use with Adobe Flash
- Player 11.1, and is compatible with versions 10.2 through 14.0. It has
- been tested with versions 11.1, 11.7, 11.8, 11.9, 12.0, 13.0 and 14.0
- on Windows and Mac. It has been compiled against other Adobe Flash
- Player versions but has not been fully tested. It has not been fully
- tested on Linux.
+ http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_1.swc
- On Windows, set FLASHPLAYER_DEBUGGER to the absolute path including the
- filename of the FlashPlayerDebugger.exe. Note the filename of flash
- player debugger maybe different.
- e.g. C:\MyPath\FlashPlayerDebugger.exe
+Set PLAYERGLOBAL_HOME to the absolute path of the player directory (not
+including the version subdirectory). The target-player option controls which
+PLAYERGLOBAL_HOME subdirectory is used.
- On the Mac, set FLASHPLAYER_DEBUGGER to the absolute path of
- Flash Player Debugger.app/Contents/MacOS/Flash Player Debugger
+Additional information about downloading and setting up this and/or other
+versions of the Adobe Flash Player can be found in the section
+'Adobe Flash Player Version Support' below.
- On Linux, set FLASHPLAYER_DEBUGGER to the absolute path of
- flashplayerdebugger
+* 6)
+The build scripts assume that the source code folder containing the Apache Flex
+Text Layout Framework root folder ('flex-tlf') is at the same level as the SDK
+root folder ('flex-sdk'). See 'Getting the source code', below. If this is not
+the case on your system, then you must set the TLF_HOME environment variable to
+point to your TLF root folder. If you are using a released artifact, the
+source should be included in the artifact, so setting TLF_HOME is not
+required.
- *5) The Adobe Flash Player playerglobal.swc for 11.1 can be downloaded from:
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_1.swc
+* 7)
+The Adobe Extension Manager is only required for those creating releases or
+testing changes to the flash-integration SWC. Note that if you change APIs on
+classes that flash-integration depends on, you may need to update
+flash-integration.
- Use URL above to download playerglobal11_1.swc. Create the directory,
- player/11.1 and copy playerglobal11_1.swc to
- player/11.1/playerglobal.swc.
+On Windows, download the Adobe Extension Manager from:
- Set PLAYERGLOBAL_HOME to the absolute path of the player directory (not
- including the version subdirectory). The target-player option controls
- which PLAYERGLOBAL_HOME subdirectory is used.
+ http://download.macromedia.com/pub/dw_exchange/extension_manager/win/AdobeExtensionManager5All.zip
- Other more recent versions of Adobe Flash Player playerglobal.swc can be
- downloaded from:
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_2.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_3.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_4.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_5.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_6.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_7.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_8.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_9.swc
- http://download.macromedia.com/get/flashplayer/updaters/12/playerglobal12_0.swc
- http://download.macromedia.com/get/flashplayer/updaters/13/playerglobal13_0.swc
- http://download.macromedia.com/get/flashplayer/updaters/14/playerglobal14_0.swc
+and set ADOBE_EXTENSION_MANAGER to the absolute path of
+'Adobe Extension Manager CS5.exe'
- These can be used with Apache Flex but not all have not been fully
- tested.
+On Mac, download the Adobe Extension Manager from:
- *6) The Adobe Extension Manager is only required for those creating releases
- or testing changes to the flash-integration swc. Note that if you
- change APIs on classes that flash-integration depends on, you may need
- to update flash-integration.
+ http://download.macromedia.com/pub/dw_exchange/extension_manager/mac/AdobeExtensionManager5All.dmg
- The Adobe Extension Manager for Windows can be downloaded from:
- http://download.macromedia.com/pub/dw_exchange/extension_manager/win/AdobeExtensionManager5All.zip
+and set ADOBE_EXTENSION_MANAGER to the absolute path of
+'Adobe Extension Manager CS5.app/Contents/MacOS/Adobe Extension Manager CS5'
- The Adobe Extension Manager for Mac can be downloaded from:
- http://download.macromedia.com/pub/dw_exchange/extension_manager/mac/AdobeExtensionManager5All.dmg
+On Linux, no Adobe Extension Manager exists.
- On Windows, set ADOBE_EXTENSION_MANAGER to the absolute path of "Adobe
- Extension Manager CS5.exe"
+* 8)
+The build scripts assume that the source code folder containing the Apache Flex
+BlazeDS root folder ('flex-blazeds') is at the same level as the SDK
+root folder ('flex-sdk'). See 'Getting the source code', below. If this is not
+the case on your system, then you must set the BLAZEDS_HOME environment variable
+to point to your BLAZEDS root folder. If you are using a released artifact, the
+source should be included in the artifact, so setting BLAZEDS_HOME is not
+required.
- On Mac, set ADOBE_EXTENSION_MANAGER to the absolute path of "Adobe
- Extension Manager CS5.app"
- On Linux, no Adobe Extension Manager exists and there's nothing that
- needs to be done here.
+Get the source code
+-------------------
-FlashPlayer Configuration
--------------------------
+You can get the source directly from the source code repository (Apache Flex
+uses git for SCM).
- For testing, the Adobe Flash Player's mm.cfg file must have the following
- entries
+Clone the latest source ('develop' branch) using the following commands:
- ErrorReportingEnable=1
- TraceOutputFileEnable=1
+ git clone https://git-wip-us.apache.org/repos/asf/flex-sdk.git flex-sdk
+ cd flex-sdk
+ git checkout develop
- and a FlashPlayerTrust file must allow local SWFs to access local files.
+The Apache Flex SDK also requires source code from the Apache Flex Text Layout
+Framework (TLF). To get the latest source for TLF ('develop' branch), use the
+following commands:
-Other Locale Support
---------------------
+ git clone https://git-wip-us.apache.org/repos/asf/flex-tlf.git flex-tlf
+ cd flex-tlf
+ git checkout develop
- The Apache Flex SDK defaults to using the en_US locale and SDK error
- messages are by default displayed in American English.
+The Apache Flex SDK also requires source code from Apache Flex BlazeDS. To get
+the latest source for Apache Flex BlazeDS (‘master’ branch), use the
+following commands:
- To compile the SDK for another locale either:
+ git clone https://git-wip-us.apache.org/repos/asf/flex-blazeds.git flex-blazeds
+ cd flex-blazeds
- Change the locale in the build.properties file to have a value other than
- "en_US". For this new locale to take effect the SDK needs to be recompiled.
- For example, to use the Australian English locale change locale to have a
- value of "en_AU"
- like so:
+Another option to get the source is to download a released source package.
- locale = en_AU
+For further information visit:
- OR
+ http://flex.apache.org/download-source.html
- Compile the SDK with a -Dlocale= option, where is the new
- locale to compile the SDK against.
- To compile all supported locales, which may take some time, use
+Build the SDK
+-------------
- ant other.locales
+When you have all the prerequisites in place and the environment variables set,
+use these commands:
- The list of supported locales currently include:
- da_DK el_GR en_GB fi_FI it_IT nb_NO pt_PT zh_CN
- de_CH en_AU en_US fr_CH ja_JP nl_NL ru_RU zh_TW
- de_DE en_CA es_ES fr_FR ko_KR pt_BR sv_SE
+ cd
+ ant main
- The Apache Flex SDK has only been tested for the en_US locale, however there
- is unlikely to be any issues with a SDK compiled for another locales.
+to download the third party dependencies and build the source. You will be
+prompted to acknowledge and/or confirm some of the downloads. Since the
+third-party dependencies take a little while to download and they don't change
+very often, they are not cleaned with the regular 'clean' target.
-Adobe Flash Player Version Support
-----------------------------------
+If you would like to build the RSLs, use:
- The Apache Flex SDK defaults to using the Adobe Flash Player 11.1. The SDK
- can be used with Flash Player versions 10.2, 10.3, 11.0, 11.1, 11.2, 11.3,
- 11.4, 11.5, 11.6, 11.7, 11.8, 11.9, 12.0, 13.0 and 14.0.
+ ant frameworks-rsls
- It is recommended that you update to the latest version of Adobe Flash
- Player. Newer versions of the Adobe Flash player address security
- vulnerabilities, fix bugs/issues, increase stability, and implement new
- features.
+To clean the build of everything other than the downloaded third-party
+dependencies, use:
- To use the SDK for another version of the Adobe Flash Player either:
+ ant clean
- Change the flex-config.xml configuration file to specify another version of
- the Adobe Flash Player.
+To clean the build of everything, including the downloaded third-party
+dependencies, use:
- OR
+ ant super-clean
- Change the playerglobal.version in the build.properties file to have a value
- other than "11.1". For this change to take effect the SDK needs to be
- recompiled. For example to compile against the latest version of the Adobe
- Flash Player set the value of playerglobal.version to be "14.0" like so:
+To generate a source distribution package and a binary distribution package,
+use:
- playerglobal.version = 14.0
+ ant -Dbuild.number= -Dbuild.noprompt= release
- OR
+The packages can then be found in the \out directory.
- Compile the SDK with a -Dplayerglobal.version= option, where
- is the Adobe Flash Player version to compile the SDK against.
+To build the ASDoc package, use:
+ ant asdoc-package
- Different versions of the Adobe Flash Player require different versions of
- playerglobal.swc.
+To get a brief listing of all the targets, use:
- These can be found at:
+ ant -projecthelp
- http://download.macromedia.com/get/flashplayer/installers/archive/playerglobal/playerglobal10_2.swc
- http://download.macromedia.com/get/flashplayer/installers/archive/playerglobal/playerglobal10_3.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_0.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_1.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_2.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_3.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_4.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_5.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_6.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_7.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_8.swc
- http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_9.swc
- http://download.macromedia.com/get/flashplayer/updaters/12/playerglobal12_0.swc
- http://download.macromedia.com/get/flashplayer/updaters/13/playerglobal13_0.swc
- http://download.macromedia.com/get/flashplayer/updaters/14/playerglobal14_0.swc
-
- Copy the target playerglobal.swc to the directory:
-
- frameworks/libs/player//playerglobal.swc
-
- Where is the major and minor version numbers of the Adobe Flash
- Player separated by a period or full stop.
-
- If all of the playerglobal swcs where installed the frameworks/libs/player
- directory structure would look like this.
-
- /frameworks
- /libs
- /player
- /10.2
- /playerglobal.swc
- /10.3
- /playerglobal.swc
- /11.0
- /playerglobal.swc
- /11.2
- /playerglobal.swc
- /11.2
- /playerglobal.swc
- /11.3
- /playerglobal.swc
- /11.4
- /playerglobal.swc
- /11.5
- /playerglobal.swc
- /11.6
- /playerglobal.swc
- /11.7
- /playerglobal.swc
- /11.8
- /playerglobal.swc
- /11.9
- /playerglobal.swc
- /12.0
- /playerglobal.swc
- /13.0
- /playerglobal.swc
- /14.0
- /playerglobal.swc
-
- Apache Flex has been tested with Adobe Flash Player 11.1, 11.5, 11.7, 11.8,
- 11.9, 12.0, 13.0 and 14.0 on Windows and Mac.
-
- Apache Flex has not been tested on Linux so some issues may exist in this
- release.
-
- It compiles against other Adobe Flash Player versions and is expected to
- work but their may be some issues, particularly with the earlier 10.2 and
- 10.3 versions of the Adobe Flash Player.
-Software Dependencies
----------------------
- Apache Flex uses third-party code that will be downloaded as part of the
- Apache Flex build. In addition, there is some optional third-party code
- that you can choose to download if you would like to take advantage of the
- features offered and you agree to the license terms.
+Prepare the SDK for use with an IDE
+-----------------------------------
- The Apache Version 2.0 license is in the LICENSE file.
+To create an SDK for Flash Builder or any other IDE, run:
- The following dependencies have licenses which are, or are compatible with,
- the Apache Version 2.0 license. You will not be prompted to acknowledge the
- download. Most of the jars are installed in lib/external.
+ cd
+ ant frameworks-rsls
+ ant -f installer.xml
+
+If you want to set the Flash Player and AIR versions to something other
+than their defaults, pass the verisons to the ant script like so:
- batik - http://archive.apache.org/dist/xmlgraphics/batik/batik-1.6.zip
- commons-collections - http://archive.apache.org/dist/commons/collections/binaries/commons-collections-3.0.tar.gz
- commons-discovery - http://archive.apache.org/dist/commons/discovery/binaries/commons-discovery-0.2.tar.gz
- commons-logging - http://archive.apache.org/dist/commons/logging/binaries/commons-logging-1.0.4.tar.gz
- javacc - http://java.net/projects/javacc/downloads/download/javacc-5.0.tar.gz
- saxon9 - http://sourceforge.net/projects/saxon/files/Saxon-B/9.1.0.8/saxonb9-1-0-8j.zip/download
- velocity - http://archive.apache.org/dist/velocity/engine/1.4/velocity-1.4.tar.gz
- xalan - http://archive.apache.org/dist/xml/xalan-j/binaries/xalan-j_2_6_0-bin.tar.gz
- xerces - http://archive.apache.org/dist/xerces/j/Xerces-J-bin.2.9.1.zip
+ ant -f installer.xml -Dflash.sdk.version=16.0 -Dair.sdk.version=16.0
- The following dependencies have licenses which Apache considers to be
- reciprocal licenses so you will be prompted to acknowledge the license
- before the software is downloaded to your system. These files are installed
- in frameworks/libs.
+On Mac/Linux the AIR and Flash Player version can be changed, after the SDK
+has been compiled, by running:
- osmf.swc
+ ./ide/setFlashPlayerVersion.sh ./ 16.0
+ ./ide/addAIRtoSDK.sh 16.0 ./
- Open Source Media Framework v1.0 used for video components
- This file is extracted from:
- http://sourceforge.net/projects/osmf.adobe/files/OSMF%201.0%20%28final%20source%2C%20ASDocs%2C%20PDF%20guides%2C%20and%20release%20notes%29/OSMF_1.0.zip/download
- This software is released under the Mozilla Public License Version 1.1:
-
+Using the Binary Distribution
+=============================
- The following dependencies have licenses which Apache considers to be not
- compatible with the Apache License Version 2.0. You will be prompted to read
- and agree to the license terms of the dependency before the software can be
- downloaded to your system.
- These are optional components which enable additional features. They are
- installed in libs/external/optional.
+In order to use the binary distribution of the SDK, follow the instructions in
+the 'Prepare the SDK for use with an IDE' section above.
- flex-messaging-common.jar
- Provides integration with Adobe BlazeDS.
- This files are extracted from:
- http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.6/flex_sdk_4.6.0.23201B.zip
- This software is released under an Adobe license:
-
+Flash Player Configuration
+=========================
- flex-fontkit.jar
- afe.jar, adt.jar
- aglj40.jar
- rideau.jar
- Adobe proprietary software which provides embedded font support.
+For testing, the Adobe Flash Player's mm.cfg file must have the following
+entries
- These jars are extracted from:
- http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.6/flex_sdk_4.6.0.23201B.zip
+ ErrorReportingEnable=1
+ TraceOutputFileEnable=1
- This software is released under an Adobe license:
-
+and a FlashPlayerTrust file must allow local SWFs to access local files.
-Using the Binary Distribution
------------------------------
+More information about these settings can be found here:
- You must download the third-party dependencies.
+ http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7c95.html
- When you have all the prerequisites in place and the environment variables
- set, (see Install Prerequisites above -- you cannot use the env.properties
- file to set the environment variables for these steps.), use
- cd /frameworks
- ant thirdparty-downloads
- Additionally, you will need to build the RSLS for the SDK before you run the
- batch files.
+Other Locale Support
+====================
+
+The Apache Flex SDK defaults to using the en_US locale and SDK error messages
+are by default displayed in American English.
+
+To compile the SDK for another locale either:
+
+Change the locale in the build.properties file to have a value other than
+'en_US'. For this new locale to take effect, the SDK needs to be recompiled. For
+example, to use the Australian English locale change locale to have a value of
+'en_AU' like so:
+
+ locale = en_AU
+
+OR
+
+Compile the SDK with a -Dlocale= option, where is the new
+locale to compile the SDK against.
+
+To compile all supported locales, which may take some time, use:
- cd
- ant frameworks-rsls
+ ant other.locales
- To use this SDK in a IDE like Flash Builder 4.6 or 4.7 the SDK needs
- several other files to be packaged and integrated with the Apache Flex SDK.
+The list of supported locales currently include:
+ da_DK el_GR en_GB fi_FI it_IT nb_NO pt_PT zh_CN
+ de_CH en_AU en_US fr_CH ja_JP nl_NL ru_RU zh_TW
+ de_DE en_CA es_ES fr_FR ko_KR pt_BR sv_SE
- If you have an existing installation of Flash Builder run:
+The Apache Flex SDK has only been tested for the en_US locale. However, you are
+unlikely to run into any issues with a SDK compiled for another locale.
- /ide/constructFlexForIDE.sh (on Mac and Linux)
- /ide/constructFlexForIDE.bat (on Windows)
- This will create an Apache Flex 4.13.0 SDK that can be used with Flash
- Builder by copying the required files from the Adobe Flex 4.6 SDK.
+Adobe Flash Player Version Support
+==================================
+
+The Apache Flex SDK defaults to using the Adobe Flash Player 11.1. The SDK can
+be used with Flash Player versions 10.2 and up.
+
+It is recommended that you update to the latest version of Adobe Flash Player.
+Newer versions of the Adobe Flash player address security vulnerabilities, fix
+bugs/issues, increase stability, and support new features.
- To create an SDK for other IDE or if you want to use Adobe AIR 14.0
- (rather than AIR 3.1 contained in Adobe Flex 4.6) run:
+To use the SDK for another version of the Adobe Flash Player either:
- /ide/flashbuilder/makeApacheFlexForIDE.sh (on Mac and Linux)
- /ide/flashbuilder/makeApacheFlexForIDE.bat (on Windows)
+Change the flex-config.xml configuration file to specify another version of the
+Adobe Flash Player.
- This will create an Apache Flex 4.13.0 SDK that can be used by an IDE by
- downloading Adobe Flex 4.6 SDK and Adobe AIR 14.0.
+OR
-Building the Framework in a Binary Distribution
------------------------------------------------
+Change the playerglobal.version in the build.properties file to have a value
+other than '11.1'. For this change to take effect, the SDK needs to be
+recompiled. For example, to compile against the latest version of the Adobe
+Flash Player, set the value of playerglobal.version to be '16.0' like so:
- The source for most of the framework is included in the binary distribution.
- It can be useful if you wish to debug and/or extend components.
+ playerglobal.version = 16.0
- When you have all the prerequisites in place and the environment variables
- set, (see Install Prerequisites above), use
+OR
- cd /frameworks
- ant main (or just ant since the default target is main)
+Compile the SDK with a -Dplayerglobal.version= option, where
+is the Adobe Flash Player version to compile the SDK against.
- to download the third-party dependencies and build the Flex framework. You
- may be prompted to acknowledge some of the downloads. Since the third-party
- dependencies take a little while to download and they don't change very
- often, they are not cleaned with the regular clean target.
+Different versions of the Adobe Flash Player require different versions of
+playerglobal.swc.
- To clean the build, of everything other than the downloaded third-party
- dependencies use
+These can be found at:
- ant clean
+ http://download.macromedia.com/get/flashplayer/installers/archive/playerglobal/playerglobal10_2.swc
+ http://download.macromedia.com/get/flashplayer/installers/archive/playerglobal/playerglobal10_3.swc
- To clean the build, of everything, including the downloaded third-party
- dependencies use
+and
- ant super-clean (which is just thirdparty-clean followed by clean)
+ http://download.macromedia.com/get/flashplayer/updaters//playerglobal_.swc
-Building the Source in the Source Distribution
-----------------------------------------------
+(e.g. http://download.macromedia.com/get/flashplayer/updaters/11/playerglobal11_1.swc)
- The source for both the Flex compiler and the Flex framework is included in
- the source distribution. The compiler is in the modules directory and the
- framework is in the frameworks directory.
+Copy the target playerglobal.swc to the directory:
- Because the sdk uses the Text Layout Framework, you will have to clone
- it too and link it to the textLayout project of the sdk:
+ frameworks/libs/player/./playerglobal.swc
+
+On OSX, running the script:
- cd /..
- git clone https://git-wip-us.apache.org/repos/asf/flex-tlf.git tlf
+ ./ide/checkAllPlayerGlobals.sh
+
+will download any new or missing player global swcs.
- When you have all the prerequisites in place and the environment variables
- set (see Install Prerequisites above), use
- cd
- ant main (or just ant since the default target is main)
+Software Dependencies
+=====================
- to download the thirdparty dependencies and build the source. You may be
- prompted to acknowledge and/or confirm some of the downloads. Since the
- third-party dependencies take a little while to download and they don't
- change very often, they are not cleaned with the regular clean target.
+The Apache Flex SDK uses third-party code that will be downloaded as part of
+the build. In addition, you can choose to download optional third-party code
+if you would like to take advantage of the features offered, and you agree to
+the license terms.
- If you would like to build the RSLs, use
+The following dependencies have licenses which are, or are compatible with, the
+Apache Version 2.0 license. You will not be prompted to acknowledge the
+download. Most of the jars are installed in lib/external.
- ant frameworks-rsls
+ batik - http://archive.apache.org/dist/xmlgraphics/batik/batik-1.6.zip
+ commons-collections - http://archive.apache.org/dist/commons/collections/binaries/commons-collections-3.0.tar.gz
+ commons-discovery - http://archive.apache.org/dist/commons/discovery/binaries/commons-discovery-0.2.tar.gz
+ commons-logging - http://archive.apache.org/dist/commons/logging/binaries/commons-logging-1.0.4.tar.gz
+ javacc - http://java.net/projects/javacc/downloads/download/javacc-5.0.tar.gz
+ velocity - http://archive.apache.org/dist/velocity/engine/1.4/velocity-1.4.tar.gz
+ xalan - http://archive.apache.org/dist/xml/xalan-j/binaries/xalan-j_2_6_0-bin.tar.gz
+ xerces - http://archive.apache.org/dist/xerces/j/Xerces-J-bin.2.9.1.zip
- To clean the build, of everything other than the downloaded third-party
- dependencies use
+The following dependencies have licenses which Apache considers to be
+reciprocal licenses. These files are installed in lib/external
+frameworks/libs respectively.
- ant clean
+ saxon9 - http://sourceforge.net/projects/saxon/files/Saxon-B/9.1.0.8/saxonb9-1-0-8j.zip/download
+ osmf.swc (Open Source Media Framework v2.0; used for video components) - http://sourceforge.net/projects/osmf.adobe/files/OSMF%201.0%20%28final%20source%2C%20ASDocs%2C%20PDF%20guides%2C%20and%20release%20notes%29/OSMF_1.0.zip/download
- To clean the build, of everything, including the downloaded third-party
- dependencies use
+ saxon9 is released under the Mozilla Public License Version 1.0:
+ osmf.swc is released under the Mozilla Public License Version 1.1:
- ant super-clean (which is just thirdparty-clean followed by clean)
+ http://www.mozilla.org/MPL/
- To generate a source distribution package and a binary distribution package
- use
+The following dependencies have licenses which Apache considers to be
+incompatible with the Apache License Version 2.0. You will be prompted to read
+and agree to the license terms of the dependency before the software can be
+downloaded to your system. These are optional components which enable
+additional features. They are installed in libs/external/optional.
- ant -Dbuild.number= -Dbuild.noprompt= release
+ adt.jar, afe.jar, aglj40.jar, flex-fontkit.jar and rideau.jar (provide embedded font support)
- The packages can be found in the "out" subdirectory.
+ These jars are extracted from:
- To build the ASDoc package
+ http://fpdownload.adobe.com/pub/flex/sdk/builds/flex4.6/flex_sdk_4.6.0.23201B.zip
- ant asdoc-package
+ and are released under an Adobe license:
- To get a brief listing of all the targets type
+ http://www.adobe.com/products/eulas/pdfs/adobe_flex_software_development_kit-combined-20110916_0930.pdf
- ant -projecthelp
-Thanks for using Apache Flex. Enjoy!
+Thanks for using the Apache Flex SDK. Enjoy!
- The Apache Flex Project
-
+ The Apache Flex Project
+
diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index c79379f164..89a111be04 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,3 +1,135 @@
+Apache Flex 4.14.0
+==================
+
+New Features
+------------
+- iOS 7+ and Android 4.x+ mobile theme support
+ More info: https://cwiki.apache.org/confluence/x/7AAIAw
+- New Spark components skin: FlatSpark
+ More info: https://cwiki.apache.org/confluence/x/wQEIAw
+- Spark RichTextEditor
+- Native support for tables in TLF
+- Promises/A+
+ More info: https://cwiki.apache.org/confluence/x/cIH_Ag
+
+AIR and Flash Player Support
+----------------------------
+- Support Flash Player 16.0
+- Support for AIR 16.0
+
+Bug Fixes
+---------
+FLEX-34710 spark datagrid doubleClickMode throws Error #1009 when the
+ application is run
+FLEX-34707 Flatspark: Update to current version "Font Awesome 4.2"
+FLEX-34701 BusyIndicator does not spin when itscontainer becomes visible
+FLEX-34694 Flatspark: Setting Applications "chromeColor" style throws error
+FLEX-34693 Flatspark ButtonIcon: Introduce property 'iconFontSize' to set icon
+ size directly
+FLEX-34692 Flatspark ButtonSkin: Icon defined by using the 'icon' style
+ property doesn't appear
+FLEX-34690 Skin for BusyIndicator cannot be found (legacy mobile skin)
+FLEX-34685 Allow legacy mobile theme to be used if needed
+FLEX-34657 SelectedIndices order is messed up
+FLEX-34649 (partial) Fatal errors in TextBlock after pasting text of specific
+ length in TextArea
+FLEX-34644 Datagrid - Rectangle bounds problem
+FLEX-34636 Release build does not work as described in README on OS X
+FLEX-34634 DataGroup fires RendererExistenceEvent with a null renderer when an
+ offscreen item is removed/replaced in the dataProvider
+FLEX-34633 HSlider track (Android4 skin) not being filled if thumb position set
+ in one case, text selection using the arrow keys doesn't work in
+ RichEditableText
+FLEX-34631 Cannot add source paths to a mustella test using a config file
+FLEX-34611 Application crash when textFlow property set to null with
+ preserveSelection
+FLEX-34609 ContainerController has superfluous null checks for _container
+FLEX-34608 IOS 7 Hslider (Scrubber) skin
+FLEX-34606 Redundant variable
+FLEX-34592 Can't use optionnal importer for TLF plainTextFormat and
+ TextLayoutFormat
+FLEX-34564 Minor changes to spelling, punctuation, grammar and logic.
+FLEX-34557 Platform.isBrowser does not work correctly
+FLEX-34556 Starting an app in portrait on an iPad results in wrong DPI
+FLEX-34543 Invalid event data when saving or cancelling grid item editor
+ session after data provider changes
+FLEX-34539 Callout skin assumes top level application is s:Application
+FLEX-34538 Spark Alert component does not add proper padding
+FLEX-34531 mx.charts.series.HLOCSeries excluding a style being used in example
+FLEX-34507 expected build.xml file missing from Linux binary tarball
+ apache-flex-sdk-4.13.0-bin.tar.gz
+FLEX-34476 Added RichTextEditor
+FLEX-34467 Spark DataGrid performance extremely decreased since "gridView" is
+ introduced
+FLEX-34460 adt is missing in windows install
+FLEX-34458 HierarchicalCollectionViewCursor.current returns wrong item after
+ previous sibling is removed when current was "${L}"
+ (CursorBookmark.LAST)
+FLEX-34456 HierarchicalCollectionViewCursors interfere with each other's
+ operation
+FLEX-34454 Setting modalTransparencyBlur to 0 gives blur when Alert ist shown
+ on top of modal Dialog
+FLEX-34450 mx.validators.EmailValidator does not accept ".email" domain
+FLEX-34440 'Bookmark no longer valid' CursorError caused by
+ HierarchicalCollectionView's conversion of
+ CollectionEventKind.REPLACE into CollectionEventKind.REMOVE
+FLEX-34424 HierarchicalCollectionViewCursor.current returns null when previous
+ sibling is removed
+FLEX-34390 SkinnableTextBase bug (found in Flex 4.13.0 RC2)
+FLEX-34385 Document try..catch limitation
+FLEX-34378 mx:DateValidator allows multiple separator chars
+FLEX-34373 spark.components.Alert should set a focus to defaultButton
+FLEX-34336 Strange Trace Statements When Debugging
+FLEX-34323 Allow the mustella tests directory to be located anywhere
+FLEX-34318 [Mavenizer] Refactor the Mavenizer in preparation of future
+ mavenized releases of flex
+FLEX-34260 s:datagrid cacheAsBitmap caches an itemRenderer for every item in
+ the dataProvider
+FLEX-34213 Flex mobile list performance
+FLEX-34212 invalidIndex RTE in LinearLayoutVector when mouse scrolling List
+FLEX-34119 mx.collections.HierarchicalCollectionViewCursor causes CursorError
+ RTE from ListCollectionView when the underlying collections change
+FLEX-34034 You can paste a newline code to a single-line TextInput.
+FLEX-33732 Mobile theme support Android 4.x look and feel
+FLEX-33054 Cursor Seek in HierarchicalCollectionViewCursor operates on wrong
+ child level
+FLEX-32541 sortable ou sortableColumns = false still shows box of sorting and
+ sortItemRenderer = null throws error
+FLEX-28291 Linear Vector Layout on the ComboBox
+FLEX-26478 Runtime error occured when a TextInput's text mouse selection isn't
+ finished yet but the TextInput instance is removed or its text
+ changes
+
+Other fixes (no JIRA issue created):
+- correct case for osmf.swc so compiles on Linux work
+- Adding a mixin to set android os version during AIR simulation
+
+Known Issues
+------------
+
+Adobe Flash Builder Integration
+
+Adobe Flash Builder 4.7 and Adobe Flash Builder 4.6 both contain a bug where,
+when generating the .mxml file for a new project that uses Apache Flex SDK
+4.10.0 or later Spark Application, Flash Builder will incorrectly insert the
+attribute:
+
+ layout="absolute"
+
+This results in a compile error in the new project. The remedy is to simply
+remove the errant attribute.
+
+The following wiki page has been set up to contain the latest news on Adobe's
+attempt to correct this problem:
+
+ https://cwiki.apache.org/confluence/display/FLEX/Adobe+Flash+Builder+'New+Project'+Bug
+
+Adobe has provided a patch for Flash Builder 4.7 that resolves this issue:
+
+ http://helpx.adobe.com/flash-builder/kb/flex-new-project-issue--.html
+
+
+
Apache Flex 4.13.0
=================
diff --git a/apache-flex-sdk-installer-config.xml b/apache-flex-sdk-installer-config.xml
index edd5286c1f..71f344e55e 100755
--- a/apache-flex-sdk-installer-config.xml
+++ b/apache-flex-sdk-installer-config.xml
@@ -40,7 +40,7 @@
Adobe AIR SDK (Requerido)Adobe AIR SDK (Requis)Adobe AIR SDK (Verplicht)
- Adobe AIR SDK (Required)
+ Adobe AIR SDK (Obrigatório)Adobe AIR SDK (필수)Adobe AIR SDK (必须的)Adobe AIR SDK (必須的)
@@ -52,24 +52,24 @@
Adobe Flash Player playerglobal.swc (Requerido)Adobe Flash Player playerglobal.swc (Requis)Adobe Flash Player playerglobal.swc (Verplicht)
- Adobe Flash Player playerglobal.swc (Required)
+ Adobe Flash Player playerglobal.swc (Obrigatório)Adobe Flash Player playerglobal.swc (필수)Adobe Flash Player playerglobal.swc (必须的)Adobe Flash Player playerglobal.swc (必須的)
-
+ SWFObject (Benötigt)SWFObject (Απαιτούμενο)SWFObject (Required)SWFObject (Requerido)SWFObject (Requis)SWFObject (Verplicht)
- SWFObject (Required)
+ SWFObject (Obrigatório)SWFObject (필수)SWFObject (必须的)SWFObject (必須的)
-
+ OSMF (Benötigt)OSMF (Απαιτούμενο)OSMF (Required)
@@ -81,30 +81,18 @@
OSMF (必须的)OSMF (必須的)
-
+ Adobe Bibliothek zur Einbettung von Schriften (Optional)Adobe Embedded Font Libraries and Utilities (Προαιρετικό)Adobe Embedded Font Libraries and Utilities (Optional)Librería y utilidades de fuentes embebidas de Adobe (Opcional)Bibliothèques Adobe Font embarquées et utilitaires (Facultatif)Adobe Embedded Font Libraries en Utilities (Optioneel)
- Adobe Embedded Font Libraries and Utilities (Opcional)
+ Bibliotecas e Utilidades de Fontes Embutidas da Adobe (Opcional)Adobe Embedded Font 라이브러리 와 유틸리티 (선택)Adobe 镶入字体库和实用程序 (可选的)Adobe 鑲入字體庫和實用程式 (可選的)
-
- Remoting Support (Optional)
- Remoting Support (Προαιρετικό)
- Remoting Support (Optional)
- Soporte para Remoting (Opcional)
- Support du Remoting (Facultatif)
- Remoting Support (Optioneel)
- Suporte para Remoting (Opcional)
- 리모팅 지원 (선택)
- 远程支持 (可选的)
- 遠端支援 (可選的)
- Installiere Framework KonfigurationsdateienΕγκατάσταση των αρχείων ρυθμίσεων του Framework
@@ -146,6 +134,10 @@
De Apache License V2 geldt voor de Apache Flex SDK. Wilt u de Apache Flex SDK installeren?
+
+ A licença Apache V2 aplica-se ao Apache Flex SDK. Você quer instalar o Apache Flex SDK?
+ Apache V2 License
+ http://www.apache.org/licenses/LICENSE-2.0.html
@@ -191,6 +183,10 @@
De Adobe SDK licentie overeenkomst geldt voor de Adobe AIR SDK. Wilt u de Adobe AIR SDK installeren?
+
+ Os termos de licença Adobe SDK se aplicam ao Adobe AIR SDK. Você quer instalar o Adobe AIR SDK?
+ Adobe AIR SDK License
+ http://www.adobe.com/products/air/sdk-eula.html
@@ -236,6 +232,10 @@
De Adobe SDK licentie overeenkomst geldt voor de Adobe Flash Player playerglobal.swc. Wilt u de Adobe Flash Player playerglobal.swc installeren?
+
+ Os termos de licença Adobe SDK se aplicam ao Adobe Flash Player playerglobal.swc. Você quer instalar o Adobe Flash Player playerglobal.swc?
+ Adobe Flex SDK License
+ http://www.adobe.com/products/eulas/pdfs/adobe_flex_software_development_kit-combined-20110916_0930.pdf
@@ -252,189 +252,52 @@
Adobe Flex SDK 授權合約
-
-
-
- Das SWFObject utility verwendet die MIT License (MIT). Möchten SIe jetzt das SWFObject utility installieren?
-
-
-
- Για το SWFObject ισχύει η συμφωνία χρήσης του MIT License (MIT). Θέλετε να εγκαταστήσετε το SWFObject;
-
-
-
- The MIT License (MIT) applies to the SWFObject utility. Do you want to install the SWFObject utility?
- MIT License
- http://opensource.org/licenses/mit-license.php
-
-
-
- SWFObject se ofrece bajo licencia MIT (MIT). ¿Quiere instalar SWFObject?
-
-
-
- La licence MIT (MIT) s'applique à l'utilitaire SWFObject. Voulez-vous installer l'utilitaire SWFObject?
-
-
-
- De MIT License (MIT) geldt voor de SWFObject utility. Wilt u de SWFObject utility installeren?
-
-
-
- Das Apache Flex SDK verwendet die Apache License V2. Möchten Sie jetzt das Apache Flex SDK installieren?
-
-
-
- SWFObject 유틸리티에는 MIT License (MIT)가 적용됩니다. SWFObject 유틸리티를 설치하시겠습니까?
-
-
-
- MIT 许可协议适用于 SWFObject 实用程序. 您想要安装 SWFObject 实用程序吗?
- MIT 许可协议
-
-
-
- MIT 授權合約適用於 SWFObject 實用程式. 您想要安裝 SWFObject 實用程式嗎?
- MIT 授權合約
-
-
-
-
-
- Das Open Source Media Framework (OSMF) welches von den Videokomponenten verwendet wird ist unter der Mozilla Public License Version 1.1 lizensiert. Möchten Sie das Open Source Media Framework (OSMF) jetzt installieren?
-
-
-
- Για το Open Source Media Framework (OSMF) που χρησιμοποιείται απο τα αντικείμενα video ισχύει η συμφωνία χρήσης του Mozilla Public License Version 1.1. Θέλετε να εγκαταστήσετε το Για το Open Source Media Framework (OSMF);
-
-
-
- The Open Source Media Framework (OSMF) used by the video components is licensed under the Mozilla Public License Version 1.1. Do you want to install the Open Source Media Framework (OSMF)?
- Mozilla Public License Version 1.1
- http://www.mozilla.org/MPL/
-
-
-
- Open Source Media Framework (OSMF), utilizado en los componentes de video, se ofrece bajo los términos de la Mozilla Public License Version 1.1. ¿Quiere instalar Open Source Media Framework (OSMF)?
-
-
-
- L'Open Source Media Framework (OSMF) utilisé par les composants vidéo est sous licence Mozilla Public License Version 1.1. Voulez-vous installer le Open Source Media Framework (OSMF)?
-
-
-
- Het Open Source Media Framework (OSMF) dat gebruikt wordt door de video componenten is gelicenseerd onder de Mozilla Public License Versie 1.1. Wilt u het Open Source Media Framework (OSMF) installeren?
-
-
-
- O Open Source Media Framework (OSMF) utilizado pelos componentes de video está sob a licença Mozilla Public License Version 1.1.
-
-
-
- Video 컴포넌트에서 사용된 Open Source Media Framework (OSMF)는 Mozilla Public License Version 1.1로 라이센스 되어있습니다. Open Source Media Framework (OSMF)를 설치하시겠습니까?
-
-
-
- Flex 的一些视频组件需要用到开源媒体框架 Open Source Media Framework (OSMF), OSMF 由 Mozilla 公共许可协议 1.1 版提供授权. 您想要安装 OSMF 吗?
- Mozilla 公共许可协议 1.1 版
-
-
-
- Flex 的一些視頻元件需要用到開源媒體框架 Open Source Media Framework (OSMF), OSMF 由 Mozilla 公共授權合約 1.1 版提供授權. 您想要安裝 OSMF 嗎?
- Mozilla 公共授權合約 1.1 版
-
-
-
-
-
- Apache Flex kann optional Adobe BlazeDS einbinden. Dieses Feature benötigt flex-messaging-common.jar aus dem Adobe Flex SDK. Die Adobe SDK Lizenzvereinbarung für Adobe Flex 4.6 gilt für diese Jar-Datei. Diese Lizenz ist nicht mit der Apache V2 Lizenz vereinbar. Möchten Sie diese Jar-Datei aus dem Adobe Flex SDK installieren?
-
-
-
- Το Apache Flex μπορεί προαιρετικά να χρησιμοποιήσει το Adobe BlazeDS. Η λειτουργία αυτή απαιτεί το αρχείο flex-messaging-common.jar που βρίσκεται στο Adobe Flex SDK. Για το αρχείο αυτό ισχύει η συμφωνία χρήσης της άδειας Adobe SDK για το Adobe Flex 4.6. Η άδεια αυτή δεν είναι συμβατή με την άδεια χρήσης Apache V2. Θέλετε να εγκαταστήσετε το αρχείο αυτά απο το Adobe Flex SDK;
- 'Αδεια χρήσης Adobe Flex SDK
-
-
-
- Apache Flex can optionally integrate with remoting providers like BlazeDS, GraniteDS, WebORB, Red5, AMFPHP, RubyAMF, PyAMF and others. This feature requires flex-messaging-common.jar from the Adobe Flex SDK. The Adobe SDK license agreement for Adobe Flex 4.6 applies to this jar. This license is not compatible with the Apache V2 license. Do you want to install this jar from the Adobe Flex SDK?
- Adobe Flex SDK License
- http://www.adobe.com/products/eulas/pdfs/adobe_flex_software_development_kit-combined-20110916_0930.pdf
-
-
-
- Apache Flex puede integrarse de manera opcional con Adobe BlazeDS. Esta característica necesita flex-messaging-common.jar del SDK de Adobe Flex. Este archivo se ofrecen bajo los términos de la licencia de Adobe SDK para Adobe Flex 4.6. Esta licencia no es compatible con la licencia Apache V2. ¿Quiere instalar este archivo desde el SDK de Adobe Flex?
-
-
-
- Apache Flex peut éventuellement s'intégrer à Adobe BlazeDS. Cette fonctionnalité nécessite flex-messaging-common.jar du SDK Adobe Flex. L'accord de licence Adobe SDK pour Adobe Flex 4.6 s'applique à ce jar. Cette licence n'est pas compatible avec la licence Apache V2. Voulez-vous installer ce jar à partir du SDK Adobe Flex?
-
-
-
- Apache Flex kan optioneel integreren met remoting providers zoals BlazeDS, GraniteDS, WebORB, Red5, AMFPHP, RubyAMF, PyAMF en andere. Deze feature vereist flex-messaging-common.jar uit de Adobe Flex SDK. De Adobe SDK licentie overeenkomst voor Adobe Flex 4.6 geldt voor deze jar. Deze licentie is niet compatibel met de Apache V2 licentie. Wilt u deze jar uit de Adobe Flex SDK installeren?
-
-
-
- Apache Flex pode, opcionalmente, integrar-se com serviços de remoting como BlazeDS, GraniteDS, WebORB, Red5, AMFPHP, RubyAMF, PyAMF e outros. Esta funcionalidade requer a biblioteca flex-messaging-common.jar do SDK Adobe Flex. A licença do SDK Adobe Flex 4.6 aplica-se a esta biblioteca. Esta licença não é compatível com a licença Apache V2. Deseja instalar a biblioteca a partir do SDK Adobe Flex
-
-
-
- Apache Flex에서는 선택적으로 BlazeDS, GraniteDS, WebORB, Red5, AMFPHP, RubyAMF, PyAMF 등등과 같은 리모팅 공급자(Remoting Provider) 기능을 통합할 수 있습니다. 이 기능은 Adobe Flex SDK에서 flex-messaging-common.jar 파일이 필요합니다. Adobe Flex 4.6에 대한 Adobe SDK 라이센스 계약이 jar 파일에 적용됩니다. 이 라이센스는 Apache V2 라이센스와 호환되지 않습니다. Adobe Flex SDK에서 이 jar 파일을 가져와 설치 하시겠습니까?
-
-
-
- Apache Flex 可以选择性地与 BlazeDS, GraniteDS, WebORB, Red5, AMFPHP, RubyAMF, PyAMF 和其它一些远程服务提供者进行整合. 此功能须要 Adobe Flex SDK 里的 flex-messaging-common.jar 文件, Adobe Flex 4.6 的 Adobe SDK 许可协议适用于这个 jar 文件, 此许可与 Apache V2 许可并不兼容. 您想要安装来自 Adobe Flex SDK 里的这个 jar 文件吗?
- Adobe Flex SDK 许可协议
-
-
-
- Apache Flex 可以選擇性地與 BlazeDS, GraniteDS, WebORB, Red5, AMFPHP, RubyAMF, PyAMF 和其它一些遠端服務提供者進行整合. 此功能須要 Adobe Flex SDK 裡的 flex-messaging-common.jar 檔案, Adobe Flex 4.6 的 Adobe SDK 授權合約適用於這個 jar 檔案, 此許可與 Apache V2 許可並不相容. 您想要安裝來自 Adobe Flex SDK 裡的這個 jar 檔案嗎?
- Adobe Flex SDK 授權合約
-
-
- Apache Flex kann optional das Feature \"Einbetten von Schriftarten\" einbinden. Dieses Feature benötigt verschieden Schriftarten Jar-Dateien aus dem Adobe Flex SDK. Die Adobe SDK Lizenzvereinbarung für Adobe Flex 4.6 gilt für diese Jar-Dateien. Diese Lizenz ist nicht mit der Apache V2 Lizenz vereinbar. Möchten Sie diese Jar-Dateien aus dem Adobe Flex SDK installieren?
+ Apache Flex kann optional das Feature \"Einbetten von Schriftarten\" einbinden. Dieses Feature benötigt verschieden Schriftarten Jar-Dateien aus dem Adobe Flex SDK. Die Adobe SDK Lizenzvereinbarung für Adobe Flex 4.6 gilt für diese Jar-Dateien. Diese Lizenz ist nicht mit der Apache V2 Lizenz vereinbar. Möchten Sie diese Jar-Dateien aus dem Adobe Flex SDK installieren?\n\nNote: the use of the FlatSpark skin and components requires embedded font support.
- Το Apache Flex μπορεί προαιρετικά να χρησιμοποιήσει την υποστήριξη που παρέχει η Adobe για ενσωματωμένες γραματοσειρές. Η λειτουργία αυτή απαιτεί κάποια jar αρχεία που υπάρχουν στο Adobe Flex SDK. Για τα αρχεία αυτά ισχύει η συμφωνία χρήσης της άδειας Adobe SDK για το Adobe Flex 4.6. Η άδεια αυτή δεν είναι συμβατή με την άδεια χρήσης Apache V2. Θέλετε να εγκαταστήσετε τα αρχεία αυτά απο το Adobe Flex SDK;
+ Το Apache Flex μπορεί προαιρετικά να χρησιμοποιήσει την υποστήριξη που παρέχει η Adobe για ενσωματωμένες γραματοσειρές. Η λειτουργία αυτή απαιτεί κάποια jar αρχεία που υπάρχουν στο Adobe Flex SDK. Για τα αρχεία αυτά ισχύει η συμφωνία χρήσης της άδειας Adobe SDK για το Adobe Flex 4.6. Η άδεια αυτή δεν είναι συμβατή με την άδεια χρήσης Apache V2. Θέλετε να εγκαταστήσετε τα αρχεία αυτά απο το Adobe Flex SDK;\n\nNote: the use of the FlatSpark skin and components requires embedded font support.'Αδεια χρήσης Adobe Flex SDK
- Apache Flex can optionally integrate with Adobe's embedded font support. This feature requires a few font jars from the Adobe Flex SDK. The Adobe SDK license agreement for Adobe Flex 4.6 applies to these jars. This license is not compatible with the Apache V2 license. Do you want to install these jars from the Adobe Flex SDK?
+ Apache Flex can optionally integrate with Adobe's embedded font support. This feature requires a few font jars from the Adobe Flex SDK. The Adobe SDK license agreement for Adobe Flex 4.6 applies to these jars. This license is not compatible with the Apache V2 license. Do you want to install these jars from the Adobe Flex SDK?\n\nNote: the use of the FlatSpark skin and components requires embedded font support.Adobe Flex SDK Licensehttp://www.adobe.com/products/eulas/pdfs/adobe_flex_software_development_kit-combined-20110916_0930.pdf
- Apache Flex puede integrarse de manera opcional con el soporte para fuentes embebidas de Adobe. Esta característica necesita algunos ficheros de fuentes del SDK de Adobe Flex. Estos archivos se ofrecen bajo los términos de la licencia de Adobe SDK para Adobe Flex 4.6. Esta licencia no es compatible con la licencia Apache V2. ¿Quiere instalar estos archivos desde el SDK de Adobe Flex?
+ Apache Flex puede integrarse de manera opcional con el soporte para fuentes embebidas de Adobe. Esta característica necesita algunos ficheros de fuentes del SDK de Adobe Flex. Estos archivos se ofrecen bajo los términos de la licencia de Adobe SDK para Adobe Flex 4.6. Esta licencia no es compatible con la licencia Apache V2. ¿Quiere instalar estos archivos desde el SDK de Adobe Flex?\n\nNote: the use of the FlatSpark skin and components requires embedded font support.
- Apache Flex peut éventuellement s'intégrer avec le support de polices embarquées Adobe (Adobe's embedded font support). Cette fonctionnalité nécessite quelques jars de polices du SDK Adobe Flex. L'accord de licence Adobe SDK pour Adobe Flex 4.6 s'applique à ces jars. Cette licence n'est pas compatible avec la licence Apache V2. Voulez-vous installer ces jars à partir du SDK Adobe Flex?
+ Apache Flex peut éventuellement s'intégrer avec le support de polices embarquées Adobe (Adobe's embedded font support). Cette fonctionnalité nécessite quelques jars de polices du SDK Adobe Flex. L'accord de licence Adobe SDK pour Adobe Flex 4.6 s'applique à ces jars. Cette licence n'est pas compatible avec la licence Apache V2. Voulez-vous installer ces jars à partir du SDK Adobe Flex?\n\nL'utilisation des habillages et composants FlatSpark requiert les bibliothèques Adobe Font embarquées (Adobe's embedded font support).
- Apache Flex kan optioneel integreren met Adobe's embedded font support. Deze feature vereist een aantal font jars uit de Adobe Flex SDK. De Adobe SDK licentie overeenkomst voor Adobe Flex 4.6 geldt voor deze jars. Deze licentie is niet compatibel met de Apache V2 licentie. Wilt u deze jars uit de Adobe Flex SDK installeren?
+ Apache Flex kan optioneel integreren met Adobe's embedded font support. Deze feature vereist een aantal font jars uit de Adobe Flex SDK. De Adobe SDK licentie overeenkomst voor Adobe Flex 4.6 geldt voor deze jars. Deze licentie is niet compatibel met de Apache V2 licentie. Wilt u deze jars uit de Adobe Flex SDK installeren?\n\nAttentie: het gebruik van de FlatSpark skin en componenten vereist embedded font support.
- Apache Flex pode, opcionalmente, integrar-se com o suporte de fontes embutidas da Adobe. Este recurso requer alguns jars do Adobe Flex SDK, que estão sob o contrato de licença do Adobe Flex 4.6. Esta licença não é compatível com a licença Apache V2. Você quer instalar estes jars a partir do Adobe Flex SDK?
+ Apache Flex pode, opcionalmente, integrar-se com o suporte de fontes embutidas da Adobe. Este recurso requer alguns jars do Adobe Flex SDK, que estão sob o contrato de licença do Adobe Flex 4.6. Esta licença não é compatível com a licença Apache V2. Você quer instalar estes jars a partir do Adobe Flex SDK?\n\nNota: o uso dos skins e componentes FlatSpark requer suporte a fontes embutidas.
+ Adobe Flex SDK License
+ http://www.adobe.com/products/eulas/pdfs/adobe_flex_software_development_kit-combined-20110916_0930.pdf
- Apache Flex는 선택적으로 Adobe의 임베드 폰트지원 기능을 통합할 수 있습니다. 이 기능에는 Adobe Flex SDK에 있는 폰트 jar 파일들이 필요합니다. 이 jar 파일들에는 Adobe Flex 4.6에 대한 Adobe SDK 라이센스 계약이 적용됩니다. 이 라이센스는 Apache V2 라이센스와 호환되지 않습니다. Adobe Flex SDK에서 이 jar 파일들을 가져와 설치하시겠습니까?
+ Apache Flex는 선택적으로 Adobe의 임베드 폰트지원 기능을 통합할 수 있습니다. 이 기능에는 Adobe Flex SDK에 있는 폰트 jar 파일들이 필요합니다. 이 jar 파일들에는 Adobe Flex 4.6에 대한 Adobe SDK 라이센스 계약이 적용됩니다. 이 라이센스는 Apache V2 라이센스와 호환되지 않습니다. Adobe Flex SDK에서 이 jar 파일들을 가져와 설치하시겠습니까?\n\nNote: the use of the FlatSpark skin and components requires embedded font support.
- Apache Flex 可以选择性地与 Adobe 镶入字体支持 进行整合. 此功能须要 Adobe Flex SDK 里的一些与字体相关的 jar 文件, Adobe Flex 4.6 的 Adobe SDK 许可协议适用于这些 jar 文件, 此许可与 Apache V2 许可并不兼容. 您想要安装来自 Adobe Flex SDK 里的这些 jar 文件吗?
+ Apache Flex 可以选择性地与 Adobe 镶入字体支持 进行整合. 此功能须要 Adobe Flex SDK 里的一些与字体相关的 jar 文件, Adobe Flex 4.6 的 Adobe SDK 许可协议适用于这些 jar 文件, 此许可与 Apache V2 许可并不兼容. 您想要安装来自 Adobe Flex SDK 里的这些 jar 文件吗?\n\n提示: FlatSpark 主题的皮肤和组件须要 镶入字体库 的支持.Adobe Flex SDK 许可协议
- Apache Flex 可以選擇性地與 Adobe 鑲入字體支援 進行整合. 此功能須要 Adobe Flex SDK 裡的一些與字體相關的 jar 檔案, Adobe Flex 4.6 的 Adobe SDK 授權合約適用於這些 jar 檔案, 此許可與 Apache V2 許可並不相容. 您想要安裝來自 Adobe Flex SDK 裡的這些 jar 檔案嗎?
+ Apache Flex 可以選擇性地與 Adobe 鑲入字體支援 進行整合. 此功能須要 Adobe Flex SDK 裡的一些與字體相關的 jar 檔案, Adobe Flex 4.6 的 Adobe SDK 授權合約適用於這些 jar 檔案, 此許可與 Apache V2 許可並不相容. 您想要安裝來自 Adobe Flex SDK 裡的這些 jar 檔案嗎?\n\n提示: FlatSpark 主題的皮膚和元件須要 鑲入字體庫 的支援.Adobe Flex SDK 授權合約
diff --git a/build.properties b/build.properties
index 4303f2ab7b..a659241c7c 100644
--- a/build.properties
+++ b/build.properties
@@ -18,8 +18,8 @@
################################################################################
# flex-sdk-description values
-release = Apache Flex 4.13.0
-release.version = 4.13.0
+release = Apache Flex 4.14.0
+release.version = 4.14.0
# override on command line with -Dbuild.number=999 or in local.properties
build.number = 0
@@ -28,7 +28,7 @@ build.number = 0
playerglobal.version = 11.1
# AIR version number
-air.version = 14.0
+air.version = 16.0
# Default locale for the SDK
locale = en_US
diff --git a/build.xml b/build.xml
index 27395f6f20..96ea1d5e79 100644
--- a/build.xml
+++ b/build.xml
@@ -70,6 +70,26 @@
property="TLF_HOME"
value="${FLEX_HOME}/frameworks/projects" />
+
+
+
+
+
+
+
+
@@ -163,7 +183,7 @@
- OS: ${os.name} / ${os.version} / ${os.arch}VM: ${java.vm.name} / ${java.vm.version}
@@ -229,6 +249,21 @@
+
+
+
+
+
+
+
+
+
+
@@ -566,10 +601,16 @@
+
+
+
+
+
+
@@ -585,6 +626,9 @@
+
+
+
@@ -678,16 +722,10 @@
-
-
-
-
-
-
+
-
@@ -716,6 +754,23 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -850,13 +905,7 @@ There are no known issues.
-
-
-
-
-
-
-
@@ -893,9 +942,13 @@ There are no known issues.
-
+
+
+
+
+
+
@@ -1031,6 +1085,7 @@ There are no known issues.
+
@@ -1038,6 +1093,7 @@ There are no known issues.
+
@@ -1797,8 +1853,14 @@ There are no known issues.
+
+
+
+
+
+
@@ -1875,6 +1937,55 @@ There are no known issues.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1946,4 +2057,12 @@ There are no known issues.
${mymd5}
+
+
+
+
+
+
diff --git a/build/set-version.xml b/build/set-version.xml
index 1841e0ab4d..bbd83e3b5a 100644
--- a/build/set-version.xml
+++ b/build/set-version.xml
@@ -102,7 +102,7 @@ with latest version info ${major} ${minor} ${nano}
group="3"
property="MAJOR"/>
-
+
@@ -130,11 +130,11 @@ update ${FLEX_HOME}/build.properties release.version to ${major}.${minor}.${nano
-
+
-
+
@@ -148,7 +148,7 @@ update ${FLEX_HOME}/modules/compiler/src/java/flex2/tools/VersionInfo.java with
-
+
diff --git a/env-template.properties b/env-template.properties
index d1465ca123..ab7cb89d94 100644
--- a/env-template.properties
+++ b/env-template.properties
@@ -17,7 +17,7 @@
##
################################################################################
-# If you chose to use this file rename it to env.properties and uncomment the
+# If you choose to use this file, rename it to env.properties and uncomment the
# properties you wish to set.
# For each of
diff --git a/flex-sdk-description.xml b/flex-sdk-description.xml
index e752185f70..231303c0c0 100644
--- a/flex-sdk-description.xml
+++ b/flex-sdk-description.xml
@@ -18,8 +18,8 @@
-->
-Apache Flex 4.13.0 FP11.1 AIR3.9 en_US
-4.13.0
+Apache Flex 4.14.0 FP11.1 AIR15.0 en_US
+4.14.00
\ No newline at end of file
diff --git a/flexunit-tests.xml b/flexunit-tests.xml
new file mode 100644
index 0000000000..8681b862be
--- /dev/null
+++ b/flexunit-tests.xml
@@ -0,0 +1,110 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/build.xml b/frameworks/build.xml
index fcfa9f95c7..f44f73af8b 100644
--- a/frameworks/build.xml
+++ b/frameworks/build.xml
@@ -132,8 +132,15 @@
+
+
+
+
+
+
+
@@ -204,6 +211,12 @@
+
+
+
+
+
+
@@ -497,6 +512,9 @@
+
+
+
@@ -505,4 +523,8 @@
+
+
+
+
diff --git a/frameworks/downloads.xml b/frameworks/downloads.xml
index 1baff1bf80..0652183038 100644
--- a/frameworks/downloads.xml
+++ b/frameworks/downloads.xml
@@ -26,8 +26,9 @@
-
-
+
+
+
@@ -62,7 +63,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -215,63 +184,12 @@
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- libs/OSMF.swc
+ libs/osmf.swcosmf_${build.number}.swf
diff --git a/frameworks/flex-config.xml b/frameworks/flex-config.xml
index 2797eebd19..7092b1345b 100644
--- a/frameworks/flex-config.xml
+++ b/frameworks/flex-config.xml
@@ -406,7 +406,7 @@
Flex Library project, FlashBuilder will allow "Link Type" to be external.
-->
- libs/OSMF.swc
+ libs/osmf.swcosmf_${build.number}.swf
diff --git a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as
index f5dee09a74..6d4901c147 100644
--- a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as
+++ b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionView.as
@@ -139,7 +139,7 @@ public class HierarchicalCollectionView extends EventDispatcher
* Mapping of UID to parents. Must be maintained as things get removed/added
* This map is created as objects are visited
*/
- mx_internal var parentMap:Object;
+ private var parentMap:Object;
//--------------------------------------------------------------------------
//
@@ -536,6 +536,17 @@ public class HierarchicalCollectionView extends EventDispatcher
return undefined;
}
+
+ public function deleteParentMapping(uid:String):void
+ {
+ delete parentMap[uid];
+ }
+
+ public function addParentMapping(uid:String, parent:Object, replaceExisting:Boolean = true):void
+ {
+ if(replaceExisting || !parentMap.hasOwnProperty(uid))
+ parentMap[uid] = parent;
+ }
/**
* @inheritDoc
@@ -677,7 +688,7 @@ public class HierarchicalCollectionView extends EventDispatcher
while (!cursor.afterLast)
{
var uid:String = UIDUtil.getUID(cursor.current);
- delete parentMap[uid];
+ deleteParentMapping(uid);
try
{
@@ -722,7 +733,6 @@ public class HierarchicalCollectionView extends EventDispatcher
public function removeChild(parent:Object, child:Object):Boolean
{
var cursor:IViewCursor;
- var index:int = 0;
if (parent == null)
{
cursor = treeData.createCursor();
@@ -1007,7 +1017,7 @@ public class HierarchicalCollectionView extends EventDispatcher
{
var item:Object = cursor.current;
var uid:String = UIDUtil.getUID(item);
- parentMap[uid] = node;
+ addParentMapping(uid, node);
// check that the node is opened or not.
// If it is open, then update the length with the node's children.
@@ -1091,7 +1101,7 @@ public class HierarchicalCollectionView extends EventDispatcher
else
{
var uid:String = UIDUtil.getUID(node);
- parentMap[uid] = parent;
+ addParentMapping(uid, parent);
if (node != null &&
openNodes[uid] &&
hierarchicalData.canHaveChildren(node) &&
@@ -1303,7 +1313,7 @@ public class HierarchicalCollectionView extends EventDispatcher
nodeArray.push(node);
var uid:String = UIDUtil.getUID(node);
- parentMap[uid] = parent;
+ addParentMapping(uid, parent);
if (openNodes[uid] != null &&
hierarchicalData.canHaveChildren(node) &&
hierarchicalData.hasChildren(node))
@@ -1422,11 +1432,7 @@ public class HierarchicalCollectionView extends EventDispatcher
{
var i:int;
var n:int;
- var location:int;
- var uid:String;
- var parent:Object;
var node:Object;
- var items:Array;
var convertedEvent:CollectionEvent;
@@ -1482,9 +1488,16 @@ public class HierarchicalCollectionView extends EventDispatcher
stopTrackUpdates(node);
getVisibleNodes(node, null, convertedEvent.items);
}
+
currentLength -= convertedEvent.items.length;
+
dispatchEvent(convertedEvent);
-
+
+ n = convertedEvent.items.length;
+ for (i = 0; i < n; i++)
+ {
+ deleteParentMapping(UIDUtil.getUID(convertedEvent.items[i]));
+ }
}
else if (ce.kind == CollectionEventKind.UPDATE)
{
@@ -1540,11 +1553,8 @@ public class HierarchicalCollectionView extends EventDispatcher
{
var i:int;
var n:int;
- var location:int;
- var uid:String;
- var parent:Object;
- var node:Object;
- var items:Array;
+ var parentOfChangingNode:Object;
+ var changingNode:Object;
var convertedEvent:CollectionEvent;
if (event is CollectionEvent)
@@ -1570,14 +1580,14 @@ public class HierarchicalCollectionView extends EventDispatcher
ce.kind);
for (i = 0; i < n; i++)
{
- node = ce.items[i];
- if (node is XML)
- startTrackUpdates(node);
- parent = getParentItem(node);
- if (parent != null)
- getVisibleNodes(node, parent, convertedEvent.items);
+ changingNode = ce.items[i];
+ if (changingNode is XML)
+ startTrackUpdates(changingNode);
+ parentOfChangingNode = getParentItem(changingNode);
+ if (parentOfChangingNode != null)
+ getVisibleNodes(changingNode, parentOfChangingNode, convertedEvent.items);
}
- convertedEvent.location = getVisibleLocationInSubCollection(parent, ce.location);
+ convertedEvent.location = getVisibleLocationInSubCollection(parentOfChangingNode, ce.location);
dispatchEvent(convertedEvent);
}
else if (ce.kind == CollectionEventKind.REMOVE)
@@ -1590,14 +1600,14 @@ public class HierarchicalCollectionView extends EventDispatcher
ce.kind);
for (i = 0; i < n; i++)
{
- node = ce.items[i];
- if (node is XML)
- stopTrackUpdates(node);
- parent = getParentItem(node);
- if (parent != null)
- getVisibleNodes(node, parent, convertedEvent.items);
+ changingNode = ce.items[i];
+ if (changingNode is XML)
+ stopTrackUpdates(changingNode);
+ parentOfChangingNode = getParentItem(changingNode);
+ if (parentOfChangingNode != null)
+ getVisibleNodes(changingNode, parentOfChangingNode, convertedEvent.items);
}
- convertedEvent.location = getVisibleLocationInSubCollection(parent, ce.location);
+ convertedEvent.location = getVisibleLocationInSubCollection(parentOfChangingNode, ce.location);
currentLength -= convertedEvent.items.length;
dispatchEvent(convertedEvent);
}
@@ -1622,22 +1632,17 @@ public class HierarchicalCollectionView extends EventDispatcher
for (i = 0; i < n; i++)
{
- node = ce.items[i].oldValue;
- parent = getParentItem(node);
+ changingNode = ce.items[i].oldValue;
+ parentOfChangingNode = getParentItem(changingNode);
- if (parent != null)
+ if (parentOfChangingNode != null)
{
- getVisibleNodes(node, parent, convertedEvent.items);
+ getVisibleNodes(changingNode, parentOfChangingNode, convertedEvent.items);
// update the parent of the new item only
// if the parent node is opened
- if (_openNodes[UIDUtil.getUID(parent)] != null)
+ if (_openNodes[UIDUtil.getUID(parentOfChangingNode)] != null)
{
- var newNode:Object = ce.items[i].newValue;
- uid = UIDUtil.getUID(newNode);
- parentMap[uid] = parent;
-
- // delete the parent map for the old node
- delete parentMap[UIDUtil.getUID(node)];
+ addParentMapping(UIDUtil.getUID(ce.items[i].newValue), parentOfChangingNode);
}
}
}
@@ -1646,10 +1651,10 @@ public class HierarchicalCollectionView extends EventDispatcher
var j:int = 0;
for (i = 0; i < n; i++)
{
- node = ce.items[i].oldValue;
- if (node is XML)
- stopTrackUpdates(node);
- while (convertedEvent.items[j] != node)
+ changingNode = ce.items[i].oldValue;
+ if (changingNode is XML)
+ stopTrackUpdates(changingNode);
+ while (convertedEvent.items[j] != changingNode)
j++;
convertedEvent.items.splice(j, 1);
}
@@ -1660,6 +1665,15 @@ public class HierarchicalCollectionView extends EventDispatcher
dispatchEvent(convertedEvent);
}
dispatchEvent(event);
+
+ for (i = 0; i < n; i++)
+ {
+ changingNode = ce.items[i].oldValue;
+ parentOfChangingNode = getParentItem(changingNode);
+
+ if (parentOfChangingNode != null && _openNodes[UIDUtil.getUID(parentOfChangingNode)] != null)
+ deleteParentMapping(UIDUtil.getUID(changingNode));
+ }
}
else if (ce.kind == CollectionEventKind.RESET)
{
diff --git a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as
index c5765af590..1f3244dab6 100644
--- a/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as
+++ b/frameworks/projects/advancedgrids/src/mx/collections/HierarchicalCollectionViewCursor.as
@@ -91,11 +91,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
modelCursor = model.createCursor();
//check to see if the model has more than one top level items
- if (model.length > 1)
- more = true;
- else
- more = false;
-
+ more = model.length > 1;
}
//--------------------------------------------------------------------------
@@ -111,6 +107,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
/**
* @private
+ * The bookmark representing the position of the current node in its siblings collection
*/
private var currentChildBookmark:CursorBookmark = CursorBookmark.FIRST;
@@ -142,7 +139,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
* @private
* A stack of the currentChildBookmark in all parents of the currentNode.
*/
- private var childIndexStack:Array = [];
+ private var parentBookmarkStack:Array = [];
/**
* @private
@@ -215,7 +212,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
*/
public function get current():Object
{
- if (childIndexStack.length == 0)
+ if (parentBookmarkStack.length == 0)
{
return modelCursor.current;
}
@@ -268,7 +265,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
*/
public function get beforeFirst():Boolean
{
- return (currentIndex <= collection.length && current == null);
+ return currentIndex < 0 && current == null;
}
//----------------------------------
@@ -284,7 +281,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
*/
public function get afterLast():Boolean
{
- return (currentIndex >= collection.length && current == null);
+ return currentIndex >= collection.length && current == null;
}
//----------------------------------
@@ -431,7 +428,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
childNodes = collection.getChildren(currentNode);
if (childNodes.length > 0)
{
- childIndexStack.push(currentChildBookmark);
+ parentBookmarkStack.push(currentChildBookmark);
parentNodes.push(currentNode);
currentChildBookmark = CursorBookmark.FIRST;
childCursor = childNodes.createCursor();
@@ -481,7 +478,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
(childCursor.bookmark == CursorBookmark.LAST || childCursor.afterLast))
{
//check for the end of the tree here.
- if (childIndexStack.length < 1 && !more)
+ if (parentBookmarkStack.length < 1 && !more)
{
currentNode = null;
currentIndex++;
@@ -507,7 +504,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
childNodes = null;
}
//get new current nodes index
- currentChildBookmark = childIndexStack.pop();
+ currentChildBookmark = parentBookmarkStack.pop();
//pop the level up one
_currentDepth--;
}
@@ -515,7 +512,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
else
{
//if no childnodes then we're probably at the top level
- if (childIndexStack.length == 0)
+ if (parentBookmarkStack.length == 0)
{
//check for more top level siblings
//and if we're here the depth should be 1
@@ -568,11 +565,11 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
childNodes = null;
}
//get new current nodes index
- currentChildBookmark = childIndexStack.pop();
+ currentChildBookmark = parentBookmarkStack.pop();
//pop the level up one
_currentDepth--;
- if (childIndexStack.length == 0)
+ if (parentBookmarkStack.length == 0)
{
//check for more top level siblings
//and if we're here the depth should be 1
@@ -628,7 +625,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
{
//at the first node in this branch so move to parent
currentNode = parentNodes.pop();
- currentChildBookmark = childIndexStack.pop();
+ currentChildBookmark = parentBookmarkStack.pop();
var grandParent:Object = parentNodes[parentNodes.length-1];
//we could probably assume that a non-null grandparent has descendants
//but the analogy only goes so far...
@@ -709,7 +706,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
childNodes = collection.getChildren(currentNode);
if (childNodes.length > 0)
{
- childIndexStack.push(currentChildBookmark);
+ parentBookmarkStack.push(currentChildBookmark);
parentNodes.push(currentNode);
// if the child collection has only one item then set the
// bookmark to first
@@ -758,7 +755,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
updateParentMap(currentNode);
- currentIndex--;
+ currentIndex--;
return true;
}
@@ -881,7 +878,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
public function insert(item:Object):void
{
var parent:Object = collection.getParentItem(current);
- collection.addChildAt(parent, item, currentIndex);
+ collection.addChildAt(parent, item, currentIndex);
}
/**
@@ -926,8 +923,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
if (currentNode != null)
{
var uid:String = UIDUtil.getUID(currentNode);
- if (!collection.parentMap.hasOwnProperty(uid))
- collection.parentMap[uid] = parentNodes[parentNodes.length - 1];
+ collection.addParentMapping(uid, parentNodes[parentNodes.length - 1], false);
}
}
@@ -1060,13 +1056,10 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
// let it throw an IPE, the classes using this cursor will handle it
modelCursor.seek(CursorBookmark.FIRST, 0);
- if (model.length > 1)
- more = true;
- else
- more = false;
+ more = model.length > 1;
currentChildBookmark = CursorBookmark.FIRST;
parentNodes = [];
- childIndexStack = [];
+ parentBookmarkStack = [];
currentIndex = 0;
_currentDepth = 1;
}
@@ -1077,11 +1070,10 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
public function moveToLast():void
{
childNodes = null;
- childIndexStack = [];
+ parentBookmarkStack = [];
_currentDepth = 1;
parentNodes = [];
- var emptyBranch:Boolean = false;
-
+
//first move to the end of the top level collection
// let it throw an IPE, the classes using this cursor will handle it
modelCursor.seek(CursorBookmark.LAST, 0);
@@ -1109,7 +1101,7 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
break;
}
parentNodes.push(currentNode);
- childIndexStack.push(currentChildBookmark);
+ parentBookmarkStack.push(currentChildBookmark);
currentNode = childCursor.current;
currentChildBookmark = CursorBookmark.LAST;
try
@@ -1149,29 +1141,17 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
{
var i:int;
var n:int;
- var node:Object;
- var nodeParent:Object
- var parent:Object;
+ var changingNode:Object;
+ var parentOfChangingNode:Object;
+ var parentOfCurrentNode:Object;
var parentStack:Array;
- var parentTable:Dictionary;
var isBefore:Boolean = false;
-
- // get the parent of the current item
- parentStack = getParentStack(current);
- // hash it by parent to map to depth
- parentTable = new Dictionary();
- n = parentStack.length;
- // don't insert the immediate parent
- for (i = 0; i < n - 1; i++)
- {
- // 0 is null parent (the model)
- parentTable[parentStack[i]] = i + 1;
- }
- // remember the current parent
- parent = parentStack[parentStack.length - 1];
-
- var tmpChildnodes:ICollectionView;
- var childCursor:IViewCursor;
+ var parentOfChangingNodeIndex:int;
+ var isChangingNodeParentAncestorOfSelectedNode:Boolean;
+ var bookmarkInChangingCollection:CursorBookmark;
+ var changingNodeCollectionBookmarkIndex:int;
+ var changingNodeAndSiblings:ICollectionView;
+ var changingCollectionCursor:IViewCursor;
if (event.kind == CollectionEventKind.ADD)
{
@@ -1182,49 +1162,57 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
isBefore = true;
}
+ parentStack = getParentStack(current);
+ parentOfCurrentNode = parentStack[parentStack.length - 1];
+
for (i = 0; i < n; i++)
{
- node = event.items[i];
+ changingNode = event.items[i];
if (isBefore)
{
// if the added node is before the current
- // and they share parent's then we have to
+ // and they share parents then we have to
// adjust the currentChildIndex or
// the stack of child indexes.
- nodeParent = collection.getParentItem(node);
- tmpChildnodes = collection.getChildren(nodeParent);
- if (nodeParent == parent)
+ parentOfChangingNode = collection.getParentItem(changingNode);
+ changingNodeAndSiblings = collection.getChildren(parentOfChangingNode);
+
+ if (parentOfChangingNode == parentOfCurrentNode)
{
- if (tmpChildnodes != null)
+ if (changingNodeAndSiblings != null)
{
- childCursor = tmpChildnodes.createCursor();
+ changingCollectionCursor = changingNodeAndSiblings.createCursor();
try
{
- childCursor.seek(currentChildBookmark);
- childCursor.moveNext();
- currentChildBookmark = childCursor.bookmark;
+ changingCollectionCursor.seek(currentChildBookmark);
+ changingCollectionCursor.moveNext();
+ currentChildBookmark = changingCollectionCursor.bookmark;
}
catch (e:ItemPendingError)
{
-
}
}
}
- else if (parentTable[nodeParent] != null)
- {
- if (tmpChildnodes != null)
+ else {
+ parentOfChangingNodeIndex = parentStack.indexOf(parentOfChangingNode);
+ isChangingNodeParentAncestorOfSelectedNode = parentOfChangingNodeIndex != -1;
+ if (isChangingNodeParentAncestorOfSelectedNode)
{
- childCursor = tmpChildnodes.createCursor();
- try
+ if (changingNodeAndSiblings != null)
{
- childCursor.seek(currentChildBookmark);
- childCursor.moveNext();
- currentChildBookmark = childCursor.bookmark;
+ changingNodeCollectionBookmarkIndex = parentOfChangingNodeIndex + 1;
+ changingCollectionCursor = changingNodeAndSiblings.createCursor();
+ bookmarkInChangingCollection = parentBookmarkStack[changingNodeCollectionBookmarkIndex];
+ try
+ {
+ changingCollectionCursor.seek(bookmarkInChangingCollection);
+ changingCollectionCursor.moveNext();
+ }
+ catch (e:ItemPendingError)
+ {
+ }
+ parentBookmarkStack[changingNodeCollectionBookmarkIndex] = changingCollectionCursor.bookmark;
}
- catch (e:ItemPendingError)
- {
- }
- childIndexStack[parentTable[nodeParent]] = currentChildBookmark;
}
}
}
@@ -1236,20 +1224,19 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
n = event.items.length;
if (event.location <= currentIndex)
{
- if (event.location + n >= currentIndex)
+ var lastIndexAffectedByDeletion:int = event.location + n;
+ var isCurrentIndexAmongRemovedNodes:Boolean = lastIndexAffectedByDeletion >= currentIndex;
+ var currentItemNotFoundAmongItsSiblings:Boolean = isCurrentIndexAmongRemovedNodes ? false : (!afterLast && !beforeFirst && current == null);
+
+ if (isCurrentIndexAmongRemovedNodes || currentItemNotFoundAmongItsSiblings)
{
- // the current node was removed
// the list classes expect that we
// leave the cursor on whatever falls
// into that slot
- var newIndex:int = event.location;
+ var indexToReturnTo:int = isCurrentIndexAmongRemovedNodes ? event.location : currentIndex - n;
moveToFirst();
- seek(CursorBookmark.FIRST, newIndex);
- for (i = 0; i < n; i++)
- {
- node = event.items[i];
- delete collection.parentMap[UIDUtil.getUID(node)];
- }
+ seek(CursorBookmark.FIRST, indexToReturnTo);
+
return;
}
@@ -1257,55 +1244,68 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
isBefore = true;
}
+ parentStack = getParentStack(current);
+ parentOfCurrentNode = parentStack[parentStack.length - 1];
+
for (i = 0; i < n; i++)
{
- node = event.items[i];
+ changingNode = event.items[i];
if (isBefore)
{
// if the removed node is before the current
- // and they share parent's then we have to
+ // and they share parents then we have to
// adjust the currentChildIndex or
// the stack of child indexes.
- nodeParent = collection.getParentItem(node);
- tmpChildnodes = collection.getChildren(nodeParent);
- if (nodeParent == parent)
+ parentOfChangingNode = collection.getParentItem(changingNode);
+ changingNodeAndSiblings = collection.getChildren(parentOfChangingNode);
+
+ if (parentOfChangingNode == parentOfCurrentNode)
{
- if (tmpChildnodes != null)
+ if(currentChildBookmark == CursorBookmark.LAST)
+ break;
+
+ if (changingNodeAndSiblings != null)
{
- childCursor = tmpChildnodes.createCursor();
+ changingCollectionCursor = changingNodeAndSiblings.createCursor();
try
{
- childCursor.seek(currentChildBookmark);
- childCursor.movePrevious();
- currentChildBookmark = childCursor.bookmark;
+ changingCollectionCursor.seek(currentChildBookmark);
+ changingCollectionCursor.movePrevious();
+ currentChildBookmark = changingCollectionCursor.bookmark;
}
catch (e:ItemPendingError)
{
-
}
}
}
- else if (parentTable[nodeParent] != null)
- {
- if (tmpChildnodes != null)
+ else {
+ parentOfChangingNodeIndex = parentStack.indexOf(parentOfChangingNode);
+ isChangingNodeParentAncestorOfSelectedNode = parentOfChangingNodeIndex != -1;
+ if (isChangingNodeParentAncestorOfSelectedNode)
{
- childCursor = tmpChildnodes.createCursor();
- try
- {
- childCursor.seek(currentChildBookmark);
- childCursor.movePrevious();
- currentChildBookmark = childCursor.bookmark;
- }
- catch (e:ItemPendingError)
+ if (changingNodeAndSiblings != null)
{
+ changingNodeCollectionBookmarkIndex = parentOfChangingNodeIndex + 1;
+ changingCollectionCursor = changingNodeAndSiblings.createCursor();
+ bookmarkInChangingCollection = parentBookmarkStack[changingNodeCollectionBookmarkIndex];
+
+ if(bookmarkInChangingCollection == CursorBookmark.LAST)
+ break;
+
+ try
+ {
+ changingCollectionCursor.seek(bookmarkInChangingCollection);
+ changingCollectionCursor.movePrevious();
+ }
+ catch (e:ItemPendingError)
+ {
+ }
+ parentBookmarkStack[changingNodeCollectionBookmarkIndex] = changingCollectionCursor.bookmark;
}
- childIndexStack[parentTable[nodeParent]] = currentChildBookmark;
}
}
}
- delete collection.parentMap[UIDUtil.getUID(node)];
}
-
}
else if (event.kind == CollectionEventKind.RESET)
{
@@ -1325,5 +1325,4 @@ public class HierarchicalCollectionViewCursor extends EventDispatcher
}
}
}
-
}
diff --git a/frameworks/projects/advancedgrids/src/mx/collections/LeafNodeCursor.as b/frameworks/projects/advancedgrids/src/mx/collections/LeafNodeCursor.as
index 143e44f9d5..0703b78fef 100644
--- a/frameworks/projects/advancedgrids/src/mx/collections/LeafNodeCursor.as
+++ b/frameworks/projects/advancedgrids/src/mx/collections/LeafNodeCursor.as
@@ -236,7 +236,7 @@ public class LeafNodeCursor extends EventDispatcher
*/
public function get beforeFirst():Boolean
{
- return (currentIndex <= collection.length && current == null);
+ return currentIndex < 0 && current == null;
}
//----------------------------------
@@ -247,7 +247,7 @@ public class LeafNodeCursor extends EventDispatcher
*/
public function get afterLast():Boolean
{
- return (currentIndex >= collection.length && current == null);
+ return currentIndex >= collection.length && current == null;
}
//----------------------------------
@@ -304,8 +304,7 @@ public class LeafNodeCursor extends EventDispatcher
return false;
var uid:String = UIDUtil.getUID(currentNode);
- if (!collection.parentMap.hasOwnProperty(uid))
- collection.parentMap[uid] = parentNodes[parentNodes.length - 1];
+ collection.addParentMapping(uid, parentNodes[parentNodes.length - 1], false);
var flag:Boolean = true;
// If current node is a branch and is open, the first child is our next item so return it
diff --git a/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridHeaderRenderer.as b/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridHeaderRenderer.as
index a96acefd39..bd69089c1e 100644
--- a/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridHeaderRenderer.as
+++ b/frameworks/projects/advancedgrids/src/mx/controls/advancedDataGridClasses/AdvancedDataGridHeaderRenderer.as
@@ -622,9 +622,6 @@ public class AdvancedDataGridHeaderRenderer
if (sortItemRendererWidth == 0)
horizontalGap = 0;
- // Size of label
- const MINIMUM_SIZE:TextLineMetrics = measureText("w");
-
// Adjust to given width
var lineMetrics:TextLineMetrics = measureText(label.text);
var labelWidth:Number = lineMetrics.width + UITextField.TEXT_WIDTH_PADDING;
@@ -791,6 +788,9 @@ public class AdvancedDataGridHeaderRenderer
*/
public function mouseEventToHeaderPart(event:MouseEvent):String
{
+ if(sortItemRendererInstance == null)
+ return AdvancedDataGrid.HEADER_TEXT_PART;
+
var point:Point = new Point(event.stageX, event.stageY);
point = globalToLocal(point);
diff --git a/frameworks/projects/advancedgrids/src/mx/core/Version.as b/frameworks/projects/advancedgrids/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/advancedgrids/src/mx/core/Version.as
+++ b/frameworks/projects/advancedgrids/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/airframework/src/mx/core/Version.as b/frameworks/projects/airframework/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/airframework/src/mx/core/Version.as
+++ b/frameworks/projects/airframework/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/airspark/src/spark/core/Version.as b/frameworks/projects/airspark/src/spark/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/airspark/src/spark/core/Version.as
+++ b/frameworks/projects/airspark/src/spark/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/apache/build.xml b/frameworks/projects/apache/build.xml
index 363e8960ef..5e818746ca 100644
--- a/frameworks/projects/apache/build.xml
+++ b/frameworks/projects/apache/build.xml
@@ -188,6 +188,12 @@
+
+
+
+
+
+
diff --git a/frameworks/projects/apache/manifest.xml b/frameworks/projects/apache/manifest.xml
index a337a60322..15b77f4609 100644
--- a/frameworks/projects/apache/manifest.xml
+++ b/frameworks/projects/apache/manifest.xml
@@ -32,4 +32,6 @@
+
+
diff --git a/frameworks/projects/apache/src/core/Version.as b/frameworks/projects/apache/src/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/apache/src/core/Version.as
+++ b/frameworks/projects/apache/src/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/apache/src/org/apache/flex/promises/Promise.as b/frameworks/projects/apache/src/org/apache/flex/promises/Promise.as
new file mode 100644
index 0000000000..aacd101e40
--- /dev/null
+++ b/frameworks/projects/apache/src/org/apache/flex/promises/Promise.as
@@ -0,0 +1,247 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.promises
+{
+
+import org.apache.flex.promises.enums.PromiseState;
+import org.apache.flex.promises.interfaces.IThenable;
+import org.apache.flex.promises.vo.Handler;
+
+public class Promise implements IThenable
+{
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ public function Promise(resolver:Function)
+ {
+ handlers_ = new Vector.();
+
+ state_ = PromiseState.PENDING;
+
+ doResolve_(resolver, resolve_, reject_);
+ }
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ private var handlers_:Vector.;
+
+ private var state_:PromiseState;
+
+ private var value_:*;
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // doResolve_
+ //----------------------------------
+
+ private function doResolve_(fn:Function, onFulfilled:Function,
+ onRejected:Function):void
+ {
+ var done:Boolean = false;
+
+ try
+ {
+ fn(function (value:*):void {
+ if (done)
+ {
+ return;
+ }
+
+ done = true;
+
+ onFulfilled(value);
+ }, function (reason:*):void {
+ if (done)
+ {
+ return;
+ }
+
+ done = true;
+
+ onRejected(reason);
+ });
+ }
+ catch (e:Error)
+ {
+ if (done)
+ {
+ return;
+ }
+
+ done = true;
+
+ onRejected(e);
+ }
+ }
+
+ //----------------------------------
+ // fulfill_
+ //----------------------------------
+
+ private function fulfill_(result:*):void
+ {
+ state_ = PromiseState.FULFILLED;
+
+ value_ = result;
+
+ processHandlers_();
+ }
+
+ //----------------------------------
+ // handle_
+ //----------------------------------
+
+ private function handle_(handler:Handler):void
+ {
+ if (state_ === PromiseState.PENDING)
+ {
+ handlers_.push(handler);
+ }
+ else
+ {
+ if (state_ === PromiseState.FULFILLED &&
+ handler.onFulfilled != null)
+ {
+ handler.onFulfilled(value_);
+ }
+
+ if (state_ === PromiseState.REJECTED &&
+ handler.onRejected != null)
+ {
+ handler.onRejected(value_);
+ }
+ }
+ }
+
+ //----------------------------------
+ // processHandlers_
+ //----------------------------------
+
+ private function processHandlers_():void
+ {
+ for (var i:int = 0, n:int = handlers_.length; i < n; i++)
+ {
+ handle_(handlers_.shift());
+ }
+ }
+
+ //----------------------------------
+ // reject_
+ //----------------------------------
+
+ private function reject_(error:*):void
+ {
+ state_ = PromiseState.REJECTED;
+
+ value_ = error;
+
+ processHandlers_();
+ }
+
+ //----------------------------------
+ // resolve_
+ //----------------------------------
+
+ private function resolve_(result:*):void
+ {
+ try
+ {
+ if (result &&
+ (typeof(result) === 'object' ||
+ typeof(result) === 'function') &&
+ result.then is Function)
+ {
+ doResolve_(result.then, resolve_, reject_);
+ }
+ else
+ {
+ fulfill_(result);
+ }
+ }
+ catch (e:Error)
+ {
+ reject_(e);
+ }
+ }
+
+ //----------------------------------
+ // then
+ //----------------------------------
+
+ public function then(onFulfilled:Function = null,
+ onRejected:Function = null):IThenable
+ {
+ return new Promise(function (resolve:Function, reject:Function):* {
+ handle_(new Handler(function (result:*):* {
+ if (typeof(onFulfilled) === 'function')
+ {
+ try
+ {
+ return resolve(onFulfilled(result));
+ }
+ catch (e:Error)
+ {
+ return reject(e);
+ }
+ }
+ else
+ {
+ return resolve(result);
+ }
+ }, function (error:*):* {
+ if (typeof(onRejected) === 'function')
+ {
+ try
+ {
+ return resolve(onRejected(error));
+ }
+ catch (e:Error)
+ {
+ return reject(e);
+ }
+ }
+ else
+ {
+ return reject(error);
+ }
+ }))
+ });
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/apache/src/org/apache/flex/promises/enums/PromiseState.as b/frameworks/projects/apache/src/org/apache/flex/promises/enums/PromiseState.as
new file mode 100644
index 0000000000..169180f467
--- /dev/null
+++ b/frameworks/projects/apache/src/org/apache/flex/promises/enums/PromiseState.as
@@ -0,0 +1,71 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.promises.enums
+{
+
+public class PromiseState
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ public static const BLOCKED:PromiseState = new PromiseState("blocked");
+ public static const FULFILLED:PromiseState = new PromiseState("fulfilled");
+ public static const PENDING:PromiseState = new PromiseState("pending");
+ public static const REJECTED:PromiseState = new PromiseState("rejected");
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ public function PromiseState(stringValue:String) {
+ this.stringValue = stringValue;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ private var stringValue:String;
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // toString
+ //----------------------------------
+
+ public function toString():String
+ {
+ return stringValue;
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/apache/src/org/apache/flex/promises/interfaces/IThenable.as b/frameworks/projects/apache/src/org/apache/flex/promises/interfaces/IThenable.as
new file mode 100644
index 0000000000..71061791ee
--- /dev/null
+++ b/frameworks/projects/apache/src/org/apache/flex/promises/interfaces/IThenable.as
@@ -0,0 +1,31 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.promises.interfaces
+{
+
+public interface IThenable
+{
+
+ function then(onFulfilled:Function = null,
+ onRejected:Function = null):IThenable;
+
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/apache/src/org/apache/flex/promises/vo/Handler.as b/frameworks/projects/apache/src/org/apache/flex/promises/vo/Handler.as
new file mode 100644
index 0000000000..d57385cf4c
--- /dev/null
+++ b/frameworks/projects/apache/src/org/apache/flex/promises/vo/Handler.as
@@ -0,0 +1,68 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 org.apache.flex.promises.vo
+{
+
+public final class Handler
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ public function Handler(onFulfilled:Function = null,
+ onRejected:Function = null)
+ {
+ if (onFulfilled != null)
+ {
+ this.onFulfilled = onFulfilled;
+ }
+
+ if (onRejected != null)
+ {
+ this.onRejected = onRejected;
+ }
+ }
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // onFulfilled
+ //----------------------------------
+
+ public var onFulfilled:Function;
+
+ //----------------------------------
+ // onRejected
+ //----------------------------------
+
+ public var onRejected:Function;
+
+}
+
+}
\ No newline at end of file
diff --git a/frameworks/projects/apache/src/tests/promises/PromisesTestSuite.as b/frameworks/projects/apache/src/tests/promises/PromisesTestSuite.as
new file mode 100644
index 0000000000..57d6766950
--- /dev/null
+++ b/frameworks/projects/apache/src/tests/promises/PromisesTestSuite.as
@@ -0,0 +1,33 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 tests.promises
+{
+
+import tests.promises.cases.PromisesBasicTests;
+
+[Suite]
+[RunWith("org.flexunit.runners.Suite")]
+public class PromisesTestSuite
+{
+
+ public var promisesBasic:PromisesBasicTests;
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/apache/src/tests/promises/cases/PromisesBasicTests.as b/frameworks/projects/apache/src/tests/promises/cases/PromisesBasicTests.as
new file mode 100644
index 0000000000..978795e3dc
--- /dev/null
+++ b/frameworks/projects/apache/src/tests/promises/cases/PromisesBasicTests.as
@@ -0,0 +1,321 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 tests.promises.cases
+{
+
+import flash.events.TimerEvent;
+import flash.utils.Timer;
+import flash.utils.setTimeout;
+
+import flexunit.framework.Assert;
+
+import org.apache.flex.promises.Promise;
+import org.apache.flex.promises.interfaces.IThenable;
+import org.flexunit.asserts.assertEquals;
+import org.flexunit.asserts.assertNotNull;
+import org.flexunit.asserts.assertTrue;
+import org.flexunit.async.Async;
+
+public class PromisesBasicTests
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ private var expected_:*;
+
+ private var promise_:IThenable;
+
+ private var got_:*;
+
+ private var timer_:Timer;
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // parseErrorGot_
+ //----------------------------------
+
+ private function parseErrorGot_(value:*):void {
+ this.got_ = Error(value).message;
+ }
+
+ //----------------------------------
+ // parseGot_
+ //----------------------------------
+
+ private function parseGot_(value:*):void {
+ this.got_ = value;
+ }
+
+ //----------------------------------
+ // setUp
+ //----------------------------------
+
+ [Before(async)]
+ public function setUp():void
+ {
+ this.timer_ = new Timer(100, 1);
+ }
+
+ //----------------------------------
+ // tearDown
+ //----------------------------------
+
+ [After(async)]
+ public function tearDown():void
+ {
+ this.promise_ = null;
+
+ if (this.timer_)
+ {
+ this.timer_.stop();
+ this.timer_ = null;
+ }
+ }
+
+ //----------------------------------
+ // verifyGot_
+ //----------------------------------
+
+ private function verifyGot_(event:TimerEvent, result:*):void {
+ assertEquals(this.expected_, this.got_);
+ }
+
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Tests
+ //
+ //--------------------------------------------------------------------------
+
+ //----------------------------------
+ // test_Create
+ //----------------------------------
+
+ [Test]
+ public function test_Create():void
+ {
+ promise_ = new Promise(null);
+
+ Assert.assertNotUndefined(promise_);
+
+ assertNotNull(promise_);
+
+ assertTrue(promise_ is IThenable);
+ assertTrue(promise_ is Promise);
+ }
+
+ //----------------------------------
+ // test_SimpleSyncThen_FulFill
+ //----------------------------------
+
+ [Test(async)]
+ public function test_SimpleSyncThen_FulFill():void
+ {
+ Async.handleEvent(this, timer_, TimerEvent.TIMER_COMPLETE, verifyGot_);
+
+ timer_.start();
+
+ promise_ = new Promise(function (fulfill:Function = null, reject:Function = null):*
+ {
+ fulfill('Hello world');
+ });
+
+ expected_ = 'Hello world';
+ promise_.then(parseGot_);
+ }
+
+ //----------------------------------
+ // test_SimpleSyncThen_Reject
+ //----------------------------------
+
+ [Test(async)]
+ public function test_SimpleSyncThen_Reject():void
+ {
+ Async.handleEvent(this, timer_, TimerEvent.TIMER_COMPLETE, verifyGot_);
+
+ timer_.start();
+
+ promise_ = new Promise(function (fulfill:Function = null, reject:Function = null):*
+ {
+ reject(new Error('reject'));
+ });
+
+ expected_ = 'Error: reject';
+ promise_.then(null, parseErrorGot_);
+ }
+
+ //----------------------------------
+ // test_SimpleASyncThen_FulFill
+ //----------------------------------
+
+ [Test(async)]
+ public function test_SimpleASyncThen_FulFill():void
+ {
+ Async.handleEvent(this, timer_, TimerEvent.TIMER_COMPLETE, verifyGot_);
+
+ timer_.start();
+
+ this.promise_ = new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void { fulfill('Hello world'); }, 10);
+ });
+
+ expected_ = 'Hello world';
+ promise_.then(parseGot_);
+ }
+
+ //----------------------------------
+ // test_SimpleASyncThen_Reject
+ //----------------------------------
+
+ [Test(async)]
+ public function test_SimpleASyncThen_Reject():void
+ {
+ Async.handleEvent(this, timer_, TimerEvent.TIMER_COMPLETE, verifyGot_);
+
+ timer_.start();
+
+ this.promise_ = new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void { reject(new Error('reject')); }, 10);
+ });
+
+ expected_ = 'Error: reject';
+ promise_.then(null, parseErrorGot_);
+ }
+
+
+ //----------------------------------
+ // test_MultipleASyncThen_FulFill
+ //----------------------------------
+
+ [Test(async)]
+ public function test_MultipleASyncThen_FulFill():void
+ {
+ Async.handleEvent(this, timer_, TimerEvent.TIMER_COMPLETE, verifyGot_);
+
+ timer_.start();
+
+ var anotherStep:Function = function (value:*):IThenable
+ {
+ return new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void {
+ fulfill(value + ' ... again');
+ }, 10);
+ });
+ }
+
+ promise_ = new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void {
+ fulfill('Hello world');
+ }, 10);
+ });
+
+ expected_ = 'Hello world ... again';
+ promise_.then(anotherStep).then(parseGot_);
+ }
+
+ //----------------------------------
+ // test_MultipleASyncThen_RejectLast
+ //----------------------------------
+
+ [Test(async)]
+ public function test_MultipleASyncThen_RejectLast():void
+ {
+ Async.handleEvent(this, timer_, TimerEvent.TIMER_COMPLETE, verifyGot_);
+
+ timer_.start();
+
+ var anotherStep:Function = function (value:*):IThenable
+ {
+ return new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void {
+ reject(new Error('reject'));
+ }, 10);
+ });
+ }
+
+ promise_ = new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void {
+ fulfill('Hello world');
+ }, 10);
+ });
+
+ expected_ = 'Error: reject';
+ promise_.then(anotherStep).then(null, parseErrorGot_);
+ }
+
+ //----------------------------------
+ // test_MultipleASyncThen_RejectFirst
+ //----------------------------------
+
+ [Test(async)]
+ public function test_MultipleASyncThen_Reject():void
+ {
+ Async.handleEvent(this, timer_, TimerEvent.TIMER_COMPLETE, verifyGot_);
+
+ timer_.start();
+
+ var anotherStep:Function = function (value:*):IThenable
+ {
+ return new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void {
+ fulfill(value + ' ... again');
+ }, 10);
+ });
+ }
+
+ promise_ = new Promise(function (fulfill:Function = null,
+ reject:Function = null):*
+ {
+ setTimeout(function ():void {
+ reject(new Error('reject'));
+ }, 10);
+ });
+
+ expected_ = 'Error: reject';
+ promise_.then(anotherStep).then(null, parseErrorGot_);
+ }
+
+}}
\ No newline at end of file
diff --git a/frameworks/projects/automation/src/mx/core/Version.as b/frameworks/projects/automation/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/automation/src/mx/core/Version.as
+++ b/frameworks/projects/automation/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/automation_agent/src/mx/core/Version.as b/frameworks/projects/automation_agent/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/automation_agent/src/mx/core/Version.as
+++ b/frameworks/projects/automation_agent/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/automation_air/src/mx/core/Version.as b/frameworks/projects/automation_air/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/automation_air/src/mx/core/Version.as
+++ b/frameworks/projects/automation_air/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/automation_dmv/src/mx/core/Version.as b/frameworks/projects/automation_dmv/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/automation_dmv/src/mx/core/Version.as
+++ b/frameworks/projects/automation_dmv/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as b/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as
index f261fc5e7a..8d74c4e6cd 100644
--- a/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as
+++ b/frameworks/projects/automation_flashflexkit/src/mx/core/Version.as
@@ -24,4 +24,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/automation_spark/src/mx/core/Version.as b/frameworks/projects/automation_spark/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/automation_spark/src/mx/core/Version.as
+++ b/frameworks/projects/automation_spark/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/automation_spark/src/spark/core/Version.as b/frameworks/projects/automation_spark/src/spark/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/automation_spark/src/spark/core/Version.as
+++ b/frameworks/projects/automation_spark/src/spark/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/charts/src/mx/charts/series/HLOCSeries.as b/frameworks/projects/charts/src/mx/charts/series/HLOCSeries.as
index 93a5739ff3..dfcc8afe46 100644
--- a/frameworks/projects/charts/src/mx/charts/series/HLOCSeries.as
+++ b/frameworks/projects/charts/src/mx/charts/series/HLOCSeries.as
@@ -103,7 +103,6 @@ use namespace mx_internal;
*/
[Style(name="stroke", type="mx.graphics.IStroke", inherit="no")]
-[Exclude(name="hlocColor", kind="style")] //this is private style and excluded from tag inspector
/**
* Represents financial data as a series of elements
diff --git a/frameworks/projects/charts/src/mx/core/Version.as b/frameworks/projects/charts/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/charts/src/mx/core/Version.as
+++ b/frameworks/projects/charts/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/experimental/assets/tools/bold.png b/frameworks/projects/experimental/assets/tools/bold.png
new file mode 100755
index 0000000000..04abf6d675
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/bold.png differ
diff --git a/frameworks/projects/experimental/assets/tools/bullet.png b/frameworks/projects/experimental/assets/tools/bullet.png
new file mode 100755
index 0000000000..aa107ba917
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/bullet.png differ
diff --git a/frameworks/projects/experimental/assets/tools/center.png b/frameworks/projects/experimental/assets/tools/center.png
new file mode 100755
index 0000000000..68428a2ed8
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/center.png differ
diff --git a/frameworks/projects/experimental/assets/tools/italic.png b/frameworks/projects/experimental/assets/tools/italic.png
new file mode 100755
index 0000000000..e89f768fac
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/italic.png differ
diff --git a/frameworks/projects/experimental/assets/tools/justify.png b/frameworks/projects/experimental/assets/tools/justify.png
new file mode 100755
index 0000000000..5ea6b2a821
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/justify.png differ
diff --git a/frameworks/projects/experimental/assets/tools/left.png b/frameworks/projects/experimental/assets/tools/left.png
new file mode 100755
index 0000000000..91bfa6984a
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/left.png differ
diff --git a/frameworks/projects/experimental/assets/tools/link.png b/frameworks/projects/experimental/assets/tools/link.png
new file mode 100755
index 0000000000..f771236a2e
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/link.png differ
diff --git a/frameworks/projects/experimental/assets/tools/right.png b/frameworks/projects/experimental/assets/tools/right.png
new file mode 100755
index 0000000000..455cc6515c
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/right.png differ
diff --git a/frameworks/projects/experimental/assets/tools/underline.png b/frameworks/projects/experimental/assets/tools/underline.png
new file mode 100755
index 0000000000..7d892b1cbd
Binary files /dev/null and b/frameworks/projects/experimental/assets/tools/underline.png differ
diff --git a/frameworks/projects/experimental/defaults.css b/frameworks/projects/experimental/defaults.css
index 033d0b0374..7d2a3ba134 100644
--- a/frameworks/projects/experimental/defaults.css
+++ b/frameworks/projects/experimental/defaults.css
@@ -100,4 +100,8 @@ MaskedTextInput #promptDisplay {
MaskedTextInput:disabledWithPrompt {
color: #cccccc;
+}
+
+RichTextEditor {
+ skinClass: ClassReference("spark.skins.RichTextEditorSkin");
}
\ No newline at end of file
diff --git a/frameworks/projects/experimental/manifest.xml b/frameworks/projects/experimental/manifest.xml
index 440eae5ada..6ae1e5da92 100644
--- a/frameworks/projects/experimental/manifest.xml
+++ b/frameworks/projects/experimental/manifest.xml
@@ -49,6 +49,8 @@
+
+
diff --git a/frameworks/projects/experimental/spark-manifest.xml b/frameworks/projects/experimental/spark-manifest.xml
index 803a6f4231..2a92ed41b4 100644
--- a/frameworks/projects/experimental/spark-manifest.xml
+++ b/frameworks/projects/experimental/spark-manifest.xml
@@ -46,4 +46,6 @@
+
+
diff --git a/frameworks/projects/experimental/src/ExperimentalClasses.as b/frameworks/projects/experimental/src/ExperimentalClasses.as
index b11d626939..f392be0c64 100644
--- a/frameworks/projects/experimental/src/ExperimentalClasses.as
+++ b/frameworks/projects/experimental/src/ExperimentalClasses.as
@@ -32,6 +32,7 @@ package
import spark.components.itemRenderers.MenuItemRenderer; MenuItemRenderer;
import spark.components.listClasses.IListItemRenderer; IListItemRenderer;
import spark.components.supportClasses.IDropDownContainer; IDropDownContainer;
+ import spark.components.RichTextEditor; RichTextEditor;
import spark.containers.supportClasses.DeferredCreationPolicy; DeferredCreationPolicy;
import spark.containers.Accordion; Accordion;
import spark.events.ColorChangeEvent; ColorChangeEvent;
@@ -63,6 +64,7 @@ package
import spark.skins.MenuSkin; MenuSkin;
import spark.skins.NavigatorSkin; NavigatorSkin;
import spark.skins.ProgressBarSkin; ProgressBarSkin;
+ import spark.skins.RichTextEditorSkin; RichTextEditorSkin;
import spark.skins.TabNavigatorSkin; TabNavigatorSkin;
import spark.skins.VNoTrackNoThumbScrollBarSkin; VNoTrackNoThumbScrollBarSkin;
import spark.supportClasses.INavigator; INavigator;
diff --git a/frameworks/projects/experimental/src/spark/components/Alert.as b/frameworks/projects/experimental/src/spark/components/Alert.as
index 770b454415..205a07f377 100644
--- a/frameworks/projects/experimental/src/spark/components/Alert.as
+++ b/frameworks/projects/experimental/src/spark/components/Alert.as
@@ -396,7 +396,7 @@ package spark.components {
* @productversion Flex 4.5
*/
public static function show(message:String = "", title:String = "", flags:uint = OK, parent:Sprite = null, closeHandler:Function = null,
- iconClass:Class = null, defaultButtonFlag:uint = 0 /* Alert.OK */, moduleFactory:IFlexModuleFactory = null):Alert {
+ iconClass:Class = null, defaultButtonFlag:uint = Alert.OK, moduleFactory:IFlexModuleFactory = null):Alert {
var modal:Boolean = (flags & Alert.NONMODAL) ? false : true;
@@ -640,7 +640,7 @@ package spark.components {
}
override protected function partRemoved(partName:String, instance:Object):void {
- super.partAdded(partName, instance);
+ super.partRemoved(partName, instance);
if (partName == "buttonGroup") {
destroyButtons(Group(instance));
}
@@ -758,6 +758,42 @@ package spark.components {
return result;
}
+ /**
+ * @private
+ */
+ private function getDefaultButton():Button
+ {
+ var label:String;
+ switch (_defaultButtonFlag)
+ {
+ case YES :
+ label = YES_LABEL;
+ break;
+ case NO :
+ label = NO_LABEL;
+ break;
+ case OK :
+ label = OK_LABEL;
+ break;
+ case CANCEL :
+ label = CANCEL_LABEL;
+ break;
+ default :
+ label = '';
+ break;
+ }
+
+ for each (var button:Button in _buttons)
+ {
+ if (button.label === label)
+ {
+ return button;
+ }
+ }
+
+ return null;
+ }
+
/**
* @private
*/
@@ -790,9 +826,10 @@ package spark.components {
awm.activate(this);
}
if (_buttons) {
- if (_defaultButtonFlag >= 0 && _defaultButtonFlag < _buttons.length - 1) {
- _buttons[ _defaultButtonFlag ].setFocus();
- _buttons[ _defaultButtonFlag ].drawFocus(true);
+ var button:Button = getDefaultButton();
+ if (button) {
+ button.setFocus();
+ button.drawFocus(true);
}
}
}
diff --git a/frameworks/projects/experimental/src/spark/components/RichTextEditor.as b/frameworks/projects/experimental/src/spark/components/RichTextEditor.as
new file mode 100644
index 0000000000..32945f2d80
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/RichTextEditor.as
@@ -0,0 +1,789 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.components
+{
+ import flash.events.Event;
+ import flash.events.FocusEvent;
+ import flash.events.KeyboardEvent;
+ import flash.events.MouseEvent;
+ import flash.text.engine.FontPosture;
+ import flash.text.engine.FontWeight;
+ import flash.ui.Keyboard;
+ import flash.utils.Dictionary;
+
+ import mx.events.FlexEvent;
+
+ import spark.components.richTextEditorClasses.AlignTool;
+ import spark.components.richTextEditorClasses.BoldTool;
+ import spark.components.richTextEditorClasses.BulletTool;
+ import spark.components.richTextEditorClasses.ColorTool;
+ import spark.components.richTextEditorClasses.FontTool;
+ import spark.components.richTextEditorClasses.ItalicTool;
+ import spark.components.richTextEditorClasses.LinkTool;
+ import spark.components.richTextEditorClasses.SizeTool;
+ import spark.components.richTextEditorClasses.UnderlineTool;
+ import spark.components.supportClasses.SkinnableComponent;
+ import spark.events.ColorChangeEvent;
+ import spark.events.IndexChangeEvent;
+ import spark.events.TextOperationEvent;
+
+ import flashx.textLayout.conversion.ConversionType;
+ import flashx.textLayout.conversion.TextConverter;
+ import flashx.textLayout.edit.ElementRange;
+ import flashx.textLayout.edit.IEditManager;
+ import flashx.textLayout.edit.ISelectionManager;
+ import flashx.textLayout.edit.SelectionState;
+ import flashx.textLayout.elements.FlowGroupElement;
+ import flashx.textLayout.elements.FlowLeafElement;
+ import flashx.textLayout.elements.LinkElement;
+ import flashx.textLayout.elements.ListElement;
+ import flashx.textLayout.elements.ParagraphElement;
+ import flashx.textLayout.elements.TextFlow;
+ import flashx.textLayout.formats.TextAlign;
+ import flashx.textLayout.formats.TextDecoration;
+ import flashx.textLayout.formats.TextLayoutFormat;
+
+ // for asdoc
+ [Experimental]
+ [Event(name = "change", type = "flash.events.Event")]
+ [Style(name = "borderColor", inherit = "no", type = "unit")]
+ [Style(name = "focusColor", inherit = "yes", type = "unit")]
+ public class RichTextEditor extends SkinnableComponent
+ {
+ private var _htmlText:String;
+ private var _htmlTextChanged:Boolean = false;
+ private var _prompt:String = "";
+ private var _stylesChanged:Dictionary = new Dictionary;
+ private var _text:String;
+ private var _textFlow:TextFlow;
+ private var _linkSelected:Boolean = false;
+ private var _urlRegExpression:RegExp = new RegExp("^(https?://(www\\.)?|www\\.)[-._~:/?#\\[\\]@!$&'()*+,;=a-z0-9]+$", 'i');
+ private const _defaultLinkText:String = "http://";
+ private var _linkEl:LinkElement
+ private var _lastRange:ElementRange;
+
+ [SkinPart(required="true")]
+ public var textArea:TextArea;
+ [SkinPart(required="false")]
+ public var fontTool:FontTool;
+ [SkinPart(required="false")]
+ public var sizeTool:SizeTool;
+ [SkinPart(required="false")]
+ public var boldTool:BoldTool;
+ [SkinPart(required="false")]
+ public var italicTool:ItalicTool;
+ [SkinPart(required="false")]
+ public var underlineTool:UnderlineTool;
+ [SkinPart(required="false")]
+ public var colorTool:ColorTool;
+ [SkinPart(required="false")]
+ public var alignTool:AlignTool;
+ [SkinPart(required="false")]
+ public var bulletTool:BulletTool;
+ [SkinPart(required="false")]
+ public var linkTool:LinkTool;
+
+ public function RichTextEditor()
+ {
+ super();
+ this.textFlow = new TextFlow; //Prevents a stack trace that happends when you try to access the textflow on click.
+ }
+
+ [Bindable("change")]
+ /**
+ * The htmlText property is here for convenience. It converts the textFlow to TextConverter.TEXT_FIELD_HTML_FORMAT.
+ */
+ public function get htmlText():String
+ {
+ if (_htmlTextChanged)
+ {
+ if (text == "")
+ {
+ _htmlText = "";
+ }
+ else
+ {
+ _htmlText = TextConverter.export(textFlow, TextConverter.TEXT_FIELD_HTML_FORMAT, ConversionType.STRING_TYPE) as String;
+ }
+ _htmlTextChanged = false;
+ }
+ return _htmlText;
+ }
+
+ /**
+ * The htmlText property is here for convenience. It converts the textFlow to TextConverter.TEXT_FIELD_HTML_FORMAT.
+ */
+ public function set htmlText(value:String):void
+ {
+ if (htmlText != value)
+ {
+ _htmlText = value;
+ if (textFlow)
+ {
+ textFlow = TextConverter.importToFlow(_htmlText, TextConverter.TEXT_FIELD_HTML_FORMAT);
+ }
+ }
+ }
+
+ /**
+ * @private
+ */
+ public function get prompt():String
+ {
+ return _prompt;
+ }
+
+ /**
+ * @private
+ */
+ public function set prompt(value:String):void
+ {
+ _prompt = value;
+ if (textArea)
+ {
+ textArea.prompt = _prompt;
+ }
+ }
+
+ /**
+ * @private
+ */
+ public override function styleChanged(styleProp:String):void
+ {
+ super.styleChanged(styleProp);
+ _stylesChanged[styleProp] = getStyle(styleProp);
+ this.invalidateDisplayList();
+ }
+
+ [Bindable("change")]
+ /**
+ * The text in the textArea
+ */
+ public function get text():String
+ {
+ if (textArea)
+ {
+ return textArea.text;
+ }
+ else
+ {
+ return _text;
+ }
+ }
+
+ /**
+ * @private
+ */
+ public function set text(value:String):void
+ {
+ _text = value;
+ if (textArea)
+ {
+ textArea.text = value;
+ }
+ }
+
+ [Bindable("change")]
+ /**
+ * The textFlow
+ */
+ public function get textFlow():TextFlow
+ {
+ return _textFlow;
+ }
+
+ /**
+ * @private
+ */
+ public function set textFlow(value:TextFlow):void
+ {
+ _textFlow = value;
+ if (textArea)
+ {
+ textArea.textFlow = value;
+ }
+ }
+
+ /**
+ * @private
+ */
+ protected override function partAdded(partName:String, instance:Object):void
+ {
+ super.partAdded(partName, instance);
+ if (instance == textArea)
+ {
+ textArea.addEventListener(TextOperationEvent.CHANGE, handleChange);
+ textArea.addEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
+ textArea.addEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
+ textArea.prompt = prompt;
+ textArea.textFlow = textFlow;
+ if (_htmlText)
+ {
+ textFlow = TextConverter.importToFlow(_htmlText, TextConverter.TEXT_FIELD_HTML_FORMAT);
+ }
+ else if (_text)
+ {
+ textArea.text = _text;
+ }
+ }
+ if (instance == fontTool)
+ {
+ fontTool.addEventListener(IndexChangeEvent.CHANGE, handleFontChange);
+ }
+ if (instance == sizeTool)
+ {
+ sizeTool.addEventListener(IndexChangeEvent.CHANGE, handleSizeChange);
+ }
+ if (instance == boldTool)
+ {
+ boldTool.addEventListener(MouseEvent.CLICK, handleBoldClick);
+ }
+ if (instance == italicTool)
+ {
+ italicTool.addEventListener(MouseEvent.CLICK, handleItalicClick);
+ }
+ if (instance == underlineTool)
+ {
+ underlineTool.addEventListener(MouseEvent.CLICK, handleUnderlineClick);
+ }
+ if (instance == colorTool)
+ {
+ colorTool.addEventListener(ColorChangeEvent.CHOOSE, handleColorChoose);
+ }
+ if (instance == alignTool)
+ {
+ alignTool.addEventListener(IndexChangeEvent.CHANGE, handleAlignChange);
+ }
+ if (instance == bulletTool)
+ {
+ bulletTool.addEventListener(MouseEvent.CLICK, handleBulletClick);
+ }
+ if (instance == linkTool)
+ {
+ linkTool.addEventListener(KeyboardEvent.KEY_DOWN, handleLinkKeydown);
+ linkTool.addEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, handleLinkUpdate);
+ }
+ handleSelectionChange();
+ }
+
+ /**
+ * @private
+ */
+ protected override function partRemoved(partName:String, instance:Object):void
+ {
+ super.partRemoved(partName, instance);
+ if (instance == textArea)
+ {
+ textArea.removeEventListener(TextOperationEvent.CHANGE, handleChange);
+ textArea.removeEventListener(FlexEvent.SELECTION_CHANGE, handleSelectionChange);
+ textArea.removeEventListener(KeyboardEvent.KEY_DOWN, handleKeyDown);
+ }
+ if (instance == fontTool)
+ {
+ fontTool.removeEventListener(IndexChangeEvent.CHANGE, handleFontChange);
+ }
+ if (instance == sizeTool)
+ {
+ sizeTool.removeEventListener(IndexChangeEvent.CHANGE, handleSizeChange);
+ }
+ if (instance == boldTool)
+ {
+ boldTool.removeEventListener(MouseEvent.CLICK, handleBoldClick);
+ }
+ if (instance == italicTool)
+ {
+ italicTool.removeEventListener(MouseEvent.CLICK, handleItalicClick);
+ }
+ if (instance == underlineTool)
+ {
+ underlineTool.removeEventListener(MouseEvent.CLICK, handleUnderlineClick);
+ }
+ if (instance == colorTool)
+ {
+ colorTool.removeEventListener(ColorChangeEvent.CHOOSE, handleColorChoose);
+ }
+ if (instance == alignTool)
+ {
+ alignTool.removeEventListener(IndexChangeEvent.CHANGE, handleAlignChange);
+ }
+ if (instance == bulletTool)
+ {
+ bulletTool.removeEventListener(MouseEvent.CLICK, handleBulletClick);
+ }
+ if (instance == linkTool)
+ {
+ linkTool.removeEventListener(KeyboardEvent.KEY_DOWN, handleLinkKeydown);
+ linkTool.removeEventListener(FocusEvent.MOUSE_FOCUS_CHANGE, handleLinkUpdate);
+ }
+ }
+
+ /**
+ * @private
+ */
+ protected override function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+ if (textArea)
+ {
+ for (var key:String in _stylesChanged)
+ {
+ textArea.setStyle(key, _stylesChanged[key]);
+ }
+ _stylesChanged = new Dictionary; //Clear it out
+ }
+ }
+
+ /**
+ * @private
+ * Actually apply the link to the selection. Repair the formating in the process.
+ */
+ private function applyLink(href:String, target:String = null, extendToLinkBoundary:Boolean = false, operationState:SelectionState = null):void
+ {
+ if (textArea && textArea.textFlow && textArea.textFlow.interactionManager is IEditManager)
+ {
+ //Get the current format
+ var txtLayFmt:TextLayoutFormat = textArea.textFlow.interactionManager.getCommonCharacterFormat();
+ //Set the link
+ if (operationState == null && _linkEl != null)
+ {
+ operationState = new SelectionState(textArea.textFlow, _linkEl.getAbsoluteStart(), _linkEl.getAbsoluteStart() + _linkEl.textLength);
+ }
+ var linkElement:LinkElement = IEditManager(textArea.textFlow.interactionManager).applyLink(href, target, extendToLinkBoundary, operationState);
+ //Fix the formatting
+ if(linkElement)
+ {
+ IEditManager(textArea.textFlow.interactionManager).clearFormatOnElement(linkElement.getChildAt(0), txtLayFmt);
+ }
+ var selectionEnd:int = Math.max(textArea.selectionActivePosition, textArea.selectionAnchorPosition);
+ textArea.selectRange(selectionEnd, selectionEnd);
+ IEditManager(textArea.textFlow.interactionManager).applyLeafFormat(txtLayFmt);
+ }
+ }
+
+ /**
+ * @private
+ * Automatically add a link if the previous text looks like a link
+ */
+ private function checkLinks():void
+ {
+ var position:int = textArea.selectionActivePosition;
+ //Find the firt non-whitespace character
+ while (position > 0)
+ {
+ if (!isWhitespace(textArea.textFlow.getCharCodeAtPosition(position)))
+ {
+ break;
+ }
+ position--;
+ }
+ //Find the next whitespace character
+ while (position > 0)
+ {
+ if (isWhitespace(textArea.textFlow.getCharCodeAtPosition(position)))
+ {
+ position++; //Back up one character
+ break;
+ }
+ position--;
+ }
+ var testText:String = textArea.textFlow.getText(position, textArea.selectionActivePosition);
+ var result:Array = testText.match(_urlRegExpression);
+ if (result != null && result.length > 0)
+ {
+ if (textArea.textFlow.interactionManager is IEditManager)
+ {
+ var selectionState:SelectionState = new SelectionState(textArea.textFlow, position, textArea.selectionActivePosition);
+ if (testText.substr(0, 3) == "www")
+ {
+ testText = "http://" + testText; //Add a missing 'http://' if needed
+ }
+ applyLink(testText, "_blank", true, selectionState);
+ textArea.setFocus();
+ }
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function getBulletSelectionState():SelectionState
+ {
+ if (textArea.textFlow)
+ {
+ var selectionManager:ISelectionManager = textArea.textFlow.interactionManager;
+ var selectionState:SelectionState = selectionManager.getSelectionState();
+ var startleaf:FlowLeafElement = textArea.textFlow.findLeaf(selectionState.absoluteStart);
+ var endleaf:FlowLeafElement = textArea.textFlow.findLeaf(selectionState.absoluteEnd);
+ if (startleaf != null)
+ {
+ selectionState.absoluteStart = startleaf.getAbsoluteStart();
+ }
+ if (endleaf != null)
+ {
+ selectionState.absoluteEnd = endleaf.getAbsoluteStart() + endleaf.parentRelativeEnd - endleaf.parentRelativeStart;
+ }
+ return selectionState;
+ }
+ return null;
+ }
+
+ /**
+ * @private
+ */
+ private function handleAlignChange(e:Event):void
+ {
+ if (alignTool.selectedItem)
+ {
+ var txtLayFmt:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ txtLayFmt.textAlign = alignTool.selectedItem.value;
+ textArea.setFormatOfRange(txtLayFmt, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ textArea.setFocus();
+ textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleBoldClick(e:MouseEvent):void
+ {
+ var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ format.fontWeight = (format.fontWeight == FontWeight.BOLD) ? FontWeight.NORMAL : FontWeight.BOLD;
+ textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ textArea.setFocus();
+ textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ }
+
+ /**
+ * @private
+ */
+ private function handleBulletClick(e:MouseEvent):void
+ {
+ if (textArea.textFlow && textArea.textFlow.interactionManager is IEditManager)
+ {
+ var editManager:IEditManager = IEditManager(textArea.textFlow.interactionManager);
+ var doCreate:Boolean = true;
+ var selectionState:SelectionState = getBulletSelectionState();
+ var listElements:Array = textArea.textFlow.getElementsByTypeName("list");
+ for each (var listElement:ListElement in listElements)
+ {
+ var start:int = listElement.getAbsoluteStart();
+ var end:int = listElement.getAbsoluteStart() + listElement.parentRelativeEnd - listElement.parentRelativeStart;
+ if (selectionState.absoluteStart == start && selectionState.absoluteEnd == end)
+ { //Same
+ removeList(listElement);
+ doCreate = false;
+ break;
+ }
+ else if (selectionState.absoluteStart == start && selectionState.absoluteEnd <= end)
+ { //Inside touching start
+ selectionState = new SelectionState(textArea.textFlow, end, selectionState.absoluteEnd);
+ removeList(listElement);
+ editManager.createList(null, null, selectionState);
+ doCreate = false;
+ break;
+ }
+ else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd == end)
+ { //Inside touching end
+ selectionState = new SelectionState(textArea.textFlow, selectionState.absoluteStart, start);
+ removeList(listElement);
+ editManager.createList(null, null, selectionState);
+ doCreate = false;
+ break;
+ }
+ else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd <= end)
+ { //Inside
+ var firstRange:SelectionState = new SelectionState(textArea.textFlow, selectionState.absoluteStart, start);
+ var secondRange:SelectionState = new SelectionState(textArea.textFlow, end, selectionState.absoluteEnd);
+ removeList(listElement);
+ editManager.createList(null, null, firstRange);
+ editManager.createList(null, null, secondRange);
+ doCreate = false;
+ break;
+ }
+ else if ((selectionState.absoluteStart >= start && selectionState.absoluteStart <= end) || (selectionState.absoluteEnd >= start && selectionState.absoluteEnd <= end))
+ { //Overlap. Include this list in the selection
+ selectionState = new SelectionState(textArea.textFlow, Math.min(start, selectionState.absoluteStart), Math.max(end, selectionState.absoluteEnd));
+ removeList(listElement);
+ }
+ else if (selectionState.absoluteStart <= start && selectionState.absoluteEnd >= end)
+ { //surround. Remove this list since it will get added back in, only expanded.
+ removeList(listElement);
+ }
+ }
+ if (doCreate)
+ {
+ IEditManager(textArea.textFlow.interactionManager).createList(null, null, selectionState);
+ }
+ textArea.textFlow.interactionManager.setFocus();
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleColorChoose(e:ColorChangeEvent):void
+ {
+ var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ format.color = e.color
+ textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ textArea.setFocus();
+ textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ }
+
+ /**
+ * @private
+ */
+ private function handleFontChange(e:Event):void
+ {
+ if (fontTool.selectedItem)
+ {
+ var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ format.fontFamily = fontTool.selectedItem;
+ textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ textArea.setFocus();
+ textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleItalicClick(e:MouseEvent):void
+ {
+ var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ format.fontStyle = (format.fontStyle == FontPosture.ITALIC) ? FontPosture.NORMAL : FontPosture.ITALIC;
+ textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ textArea.setFocus();
+ textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ }
+
+ /**
+ * @private
+ */
+ private function handleKeyDown(e:KeyboardEvent):void
+ {
+ if (e.keyCode == Keyboard.ENTER || e.keyCode == Keyboard.SPACE || e.keyCode == Keyboard.TAB)
+ {
+ checkLinks();
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleLinkKeydown(e:KeyboardEvent):void
+ {
+ e.stopImmediatePropagation();
+ if (e.keyCode == Keyboard.ENTER)
+ {
+ handleLinkUpdate();
+ textArea.setFocus();
+ }
+ }
+
+ /**
+ * @private
+ * Handle link set by applying the link to the selected text
+ */
+ private function handleLinkUpdate(e:Event = null):void
+ {
+ var urlText:String = linkTool.selectedLink == _defaultLinkText ? '' : linkTool.selectedLink;
+ applyLink(urlText, "_blank", true);
+ //Set focus to textFlow
+ textArea.textFlow.interactionManager.setFocus();
+ }
+
+ /**
+ * @private
+ */
+ private function handleSelectionChange(e:FlexEvent = null):void
+ {
+ if (textArea != null)
+ {
+ var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ if (fontTool != null)
+ {
+ fontTool.selectedFontFamily = format.fontFamily;
+ }
+ if (sizeTool != null)
+ {
+ sizeTool.selectedFontSize = format.fontSize;
+ }
+ if (boldTool != null)
+ {
+ boldTool.selectedFontWeight = format.fontWeight;
+ }
+ if (italicTool != null)
+ {
+ italicTool.selectedFontStyle = format.fontStyle;
+ }
+ if (underlineTool != null)
+ {
+ underlineTool.selectedTextDecoration = format.textDecoration;
+ }
+ if (colorTool != null)
+ {
+ colorTool.selectedTextColor = format.color;
+ }
+ if (alignTool != null)
+ {
+ alignTool.selectedTextAlign = format.textAlign;
+ }
+ if (bulletTool != null)
+ {
+ if (textArea.textFlow)
+ {
+ var willRemoveBulletsIfClicked:Boolean = false;
+ var selectionState:SelectionState = getBulletSelectionState();
+ var listElements:Array = textArea.textFlow.getElementsByTypeName("list");
+ for each (var listElement:ListElement in listElements)
+ {
+ var start:int = listElement.getAbsoluteStart();
+ var end:int = listElement.getAbsoluteStart() + listElement.parentRelativeEnd - listElement.parentRelativeStart;
+ if (selectionState.absoluteStart == start && selectionState.absoluteEnd == end)
+ { //Same
+ willRemoveBulletsIfClicked = true;
+ break;
+ }
+ else if (selectionState.absoluteStart >= start && selectionState.absoluteEnd <= end)
+ { //Inside
+ willRemoveBulletsIfClicked = true;
+ break;
+ }
+ }
+ bulletTool.selected = willRemoveBulletsIfClicked;
+
+ }
+ }
+ if (linkTool != null)
+ {
+ var bulletSelectionState:SelectionState = textArea.textFlow.interactionManager.getSelectionState();
+ if (bulletSelectionState.absoluteStart != -1 && bulletSelectionState.absoluteEnd != -1)
+ {
+ var range:ElementRange = ElementRange.createElementRange(bulletSelectionState.textFlow, bulletSelectionState.absoluteStart, bulletSelectionState.absoluteEnd);
+ if (range)
+ {
+ var linkString:String = _defaultLinkText;
+ _linkEl = range.firstLeaf.getParentByType(LinkElement) as LinkElement;
+ if (_linkEl != null)
+ {
+ var linkElStart:int = _linkEl.getAbsoluteStart();
+ var linkElEnd:int = linkElStart + _linkEl.textLength;
+ if (linkElEnd < linkElStart)
+ {
+ var temp:int = linkElStart;
+ linkElStart = linkElEnd;
+ linkElEnd = temp;
+ }
+
+ var beginRange:int = range.absoluteStart;
+ var endRange:int = range.absoluteEnd;
+
+ var beginPara:ParagraphElement = range.firstParagraph;
+ if (endRange == (beginPara.getAbsoluteStart() + beginPara.textLength))
+ {
+ endRange--;
+ }
+
+ if ((beginRange == endRange) || (endRange <= linkElEnd))
+ {
+ linkString = LinkElement(_linkEl).href;
+ }
+ }
+ var newLinkSelected:Boolean = _linkEl != null;
+ if (_linkSelected != newLinkSelected)
+ {
+ _linkSelected = newLinkSelected;
+ this.dispatchEvent(new Event("linkSelectedChange"));
+ }
+
+ linkTool.selectedLink = linkString;
+
+ _lastRange = range;
+ }
+ else
+ {
+ _lastRange = null;
+ }
+ }
+ linkTool.enabled = textArea.selectionAnchorPosition != textArea.selectionActivePosition || _linkSelected;
+ }
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleSizeChange(e:Event):void
+ {
+ if (sizeTool.selectedItem)
+ {
+ var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ format.fontSize = sizeTool.selectedItem;
+ textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ textArea.setFocus();
+ textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function handleUnderlineClick(e:MouseEvent):void
+ {
+ var format:TextLayoutFormat = textArea.getFormatOfRange(null, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ format.textDecoration = (format.textDecoration == TextDecoration.UNDERLINE) ? TextDecoration.NONE : TextDecoration.UNDERLINE;
+ textArea.setFormatOfRange(format, textArea.selectionAnchorPosition, textArea.selectionActivePosition);
+ textArea.setFocus();
+ textArea.dispatchEvent(new TextOperationEvent(TextOperationEvent.CHANGE));
+ }
+
+ /**
+ * @private
+ */
+ private function handleChange(e:Event):void
+ {
+ _htmlTextChanged = true;
+ this.dispatchEvent(e);
+ }
+
+ /**
+ * @private
+ */
+ private function removeList(listElement:ListElement):void
+ {
+ var editManager:IEditManager = IEditManager(textArea.textFlow.interactionManager);
+
+ var target:FlowGroupElement = listElement.parent;
+ var targetIndex:int = target.getChildIndex(listElement);
+ editManager.moveChildren(listElement, 0, listElement.numChildren, target, targetIndex);
+ }
+
+ /**
+ * @private
+ * Return true if the character is a whitespace character
+ */
+ private function isWhitespace(charCode:uint):Boolean
+ {
+ return charCode === 0x0009 || charCode === 0x000A || charCode === 0x000B || charCode === 0x000C || charCode === 0x000D || charCode === 0x0020 || charCode === 0x0085 || charCode === 0x00A0 || charCode === 0x1680 || charCode === 0x180E || charCode === 0x2000 || charCode === 0x2001 || charCode === 0x2002 || charCode === 0x2003 || charCode === 0x2004 || charCode === 0x2005 || charCode === 0x2006 || charCode === 0x2007 || charCode === 0x2008 || charCode === 0x2009 || charCode === 0x200A || charCode === 0x2028 || charCode === 0x2029 || charCode === 0x202F || charCode === 0x205F || charCode === 0x3000;
+ }
+ }
+}
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml
new file mode 100644
index 0000000000..615532c94f
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/AlignTool.mxml
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml
new file mode 100644
index 0000000000..2c154f986f
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BoldTool.mxml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml
new file mode 100644
index 0000000000..e8555f2ad5
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/BulletTool.mxml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml
new file mode 100644
index 0000000000..02d954797e
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ColorTool.mxml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml
new file mode 100644
index 0000000000..292a2e3f99
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/FontTool.mxml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml
new file mode 100644
index 0000000000..c6ee382b67
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/ItalicTool.mxml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml
new file mode 100644
index 0000000000..e780acb184
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/LinkTool.mxml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml
new file mode 100644
index 0000000000..f56be1adaf
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/SizeTool.mxml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml
new file mode 100644
index 0000000000..f623dd41b0
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/components/richTextEditorClasses/UnderlineTool.mxml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/skins/AlertSkin.mxml b/frameworks/projects/experimental/src/spark/skins/AlertSkin.mxml
index 67afe58b64..f4882ee487 100644
--- a/frameworks/projects/experimental/src/spark/skins/AlertSkin.mxml
+++ b/frameworks/projects/experimental/src/spark/skins/AlertSkin.mxml
@@ -232,6 +232,7 @@
+ xmlns:fb="http://ns.adobe.com/flashbuilder/2009" minWidth="21" minHeight="21">
+
+
+
+
+ [HostComponent("spark.components.RichTextEditor")]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/experimental/src/spark/skins/richTextEditorClasses/AlignToolSkin.mxml b/frameworks/projects/experimental/src/spark/skins/richTextEditorClasses/AlignToolSkin.mxml
new file mode 100644
index 0000000000..36e58b39fd
--- /dev/null
+++ b/frameworks/projects/experimental/src/spark/skins/richTextEditorClasses/AlignToolSkin.mxml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/build.xml b/frameworks/projects/flatspark/build.xml
new file mode 100644
index 0000000000..38f9c46738
--- /dev/null
+++ b/frameworks/projects/flatspark/build.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/compile-config.xml b/frameworks/projects/flatspark/compile-config.xml
new file mode 100644
index 0000000000..5b24081ce0
--- /dev/null
+++ b/frameworks/projects/flatspark/compile-config.xml
@@ -0,0 +1,109 @@
+
+
+
+
+
+ true
+
+
+ ${env.PLAYERGLOBAL_HOME}/${playerglobal.version}/playerglobal.swc
+ ../../libs/framework.swc
+ ../../libs/spark.swc
+ ../../libs/experimental.swc
+ ../../libs/textLayout.swc
+
+
+
+
+
+
+
+
+ library://ns.adobe.com/flex/spark
+ ../../spark-manifest.xml
+
+
+
+
+ src
+
+
+ false
+
+
+
+
+ FlatSparkSkinsClasses
+
+
+
+ defaults.css
+ defaults.css
+
+
+ flatspark/assets/fonts/awesome/FontAwesome.otf
+ src/flatspark/assets/fonts/awesome/FontAwesome.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Black.otf
+ src/flatspark/assets/fonts/lato/Lato_Black.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Black_Italic.otf
+ src/flatspark/assets/fonts/lato/Lato_Black_Italic.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Bold.otf
+ src/flatspark/assets/fonts/lato/Lato_Bold.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Bold_Italic.otf
+ src/flatspark/assets/fonts/lato/Lato_Bold_Italic.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Hairline.otf
+ src/flatspark/assets/fonts/lato/Lato_Hairline.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Hairline_Italic.otf
+ src/flatspark/assets/fonts/lato/Lato_Hairline_Italic.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Light.otf
+ src/flatspark/assets/fonts/lato/Lato_Light.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Light_Italic.otf
+ src/flatspark/assets/fonts/lato/Lato_Light_Italic.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Regular.otf
+ src/flatspark/assets/fonts/lato/Lato_Regular.otf
+
+
+ flatspark/assets/fonts/lato/Lato_Regular_Italic.otf
+ src/flatspark/assets/fonts/lato/Lato_Regular_Italic.otf
+
+
+ bundles.properties
+
+ ${playerglobal.version}
+
+
diff --git a/frameworks/projects/flatspark/defaults.css b/frameworks/projects/flatspark/defaults.css
new file mode 100644
index 0000000000..f84b715494
--- /dev/null
+++ b/frameworks/projects/flatspark/defaults.css
@@ -0,0 +1,122 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* CSS file */
+@namespace s "library://ns.adobe.com/flex/spark";
+@namespace components "flatspark.components.*";
+@namespace ns "http://flex.apache.org/experimental/ns";
+
+
+@font-face {
+ src: url("flatspark/assets/fonts/awesome/FontAwesome.otf");
+ fontFamily: FontAwesome;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Regular.otf");
+ fontFamily: Lato;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Regular_Italic.otf");
+ fontFamily: Lato;
+ fontStyle: italic;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Bold.otf");
+ fontFamily: Lato;
+ fontWeight: bold;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Bold_Italic.otf");
+ fontFamily: Lato;
+ fontStyle: italic;
+ fontWeight: bold;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Light.otf");
+ fontFamily: LatoLight;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Light_Italic.otf");
+ fontFamily: LatoLight;
+ fontStyle: italic;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Hairline.otf");
+ fontFamily: LatoHairline;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Hairline_Italic.otf");
+ fontFamily: LatoHairline;
+ fontStyle: italic;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Black.otf");
+ fontFamily: LatoBlack;
+ embedAsCFF: true;
+}
+
+@font-face {
+ src:url("flatspark/assets/fonts/lato/Lato_Black_Italic.otf");
+ fontFamily: LatoBlack;
+ fontStyle: italic;
+ embedAsCFF: true;
+}
+
+global
+{
+ modal-transparency: 0.98;
+ modal-transparency-blur: 0;
+ modal-transparency-color: #2c3e50;
+}
+
+s|Application {
+ fontFamily: Lato, Helvetica, Arial, sans-serif;
+}
+
+s|Button {
+ fontSize: 14;
+}
+
+components|ButtonIcon {
+ skinClass: ClassReference("flatspark.skins.ButtonIconSkin");
+ fontSize: 14;
+ iconFontSize: 17;
+}
+
+components|TextInputIcon {
+ skinClass: ClassReference("flatspark.skins.TextInputIconSkin");
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/FlatSparkSkinsClasses.as b/frameworks/projects/flatspark/src/FlatSparkSkinsClasses.as
new file mode 100644
index 0000000000..24c3a81043
--- /dev/null
+++ b/frameworks/projects/flatspark/src/FlatSparkSkinsClasses.as
@@ -0,0 +1,51 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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
+{
+
+/**
+ * @private
+ * This class is used to link additional classes into framework.swc
+ * beyond those that are found by dependecy analysis starting
+ * from the classes specified in manifest.xml.
+ * For example, Button does not have a reference to ButtonSkin,
+ * but ButtonSkin needs to be in framework.swc along with Button.
+ */
+internal class FlatSparkSkinsClasses
+{
+ // skins
+ import flatspark.skins.AlertSkin; AlertSkin;
+ import flatspark.skins.ButtonSkin; ButtonSkin;
+ import flatspark.skins.ButtonIconSkin; ButtonIconSkin;
+ import flatspark.skins.CheckBoxSkin; CheckBoxSkin;
+ import flatspark.skins.ComboBoxSkin; ComboBoxSkin;
+ import flatspark.skins.ScrollerSkin; ScrollerSkin;
+ import flatspark.skins.DropDownListSkin; DropDownListSkin;
+ import flatspark.skins.PanelSkin; PanelSkin;
+ import flatspark.skins.ProgressBarSkin; ProgressBarSkin;
+ import flatspark.skins.RadioButtonSkin; RadioButtonSkin;
+ import flatspark.skins.TextInputSkin; TextInputSkin;
+ import flatspark.skins.TextInputIconSkin; TextInputIconSkin;
+ import flatspark.skins.TitleWindowSkin; TitleWindowSkin;
+ // Maintain alphabetical order
+}
+
+}
+
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/FontAwesome.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/FontAwesome.otf
new file mode 100644
index 0000000000..81c9ad949b
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/FontAwesome.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/OFL.txt b/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/OFL.txt
new file mode 100644
index 0000000000..d68a2c8644
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/assets/fonts/awesome/OFL.txt
@@ -0,0 +1,94 @@
+Copyright (c) 2014, Dave Gandy (http://fontawesome.io),
+with Reserved Font Name "Font Awesome".
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Black.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Black.otf
new file mode 100644
index 0000000000..237ffb70cc
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Black.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Black_Italic.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Black_Italic.otf
new file mode 100644
index 0000000000..97f1b93f62
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Black_Italic.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Bold.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Bold.otf
new file mode 100644
index 0000000000..7f0a3d3ca3
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Bold.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Bold_Italic.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Bold_Italic.otf
new file mode 100644
index 0000000000..4eb4518ae6
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Bold_Italic.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Hairline.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Hairline.otf
new file mode 100644
index 0000000000..4edb976139
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Hairline.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Hairline_Italic.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Hairline_Italic.otf
new file mode 100644
index 0000000000..50b82a25d6
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Hairline_Italic.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Light.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Light.otf
new file mode 100644
index 0000000000..3226cb93f7
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Light.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Light_Italic.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Light_Italic.otf
new file mode 100644
index 0000000000..d7557b0cf4
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Light_Italic.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Regular.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Regular.otf
new file mode 100644
index 0000000000..1f94789b5b
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Regular.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Regular_Italic.otf b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Regular_Italic.otf
new file mode 100644
index 0000000000..6341374beb
Binary files /dev/null and b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/Lato_Regular_Italic.otf differ
diff --git a/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/OFL.txt b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/OFL.txt
new file mode 100644
index 0000000000..303088c784
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/assets/fonts/lato/OFL.txt
@@ -0,0 +1,94 @@
+Copyright (c) 2014, Łukasz Dziedzic (https://www.google.com/fonts/specimen/Lato),
+with Reserved Font Name "Lato".
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded,
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/frameworks/projects/flatspark/src/flatspark/components/ButtonIcon.as b/frameworks/projects/flatspark/src/flatspark/components/ButtonIcon.as
new file mode 100644
index 0000000000..ad46678b61
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/components/ButtonIcon.as
@@ -0,0 +1,44 @@
+/**
+ 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 flatspark.components
+{
+
+ import spark.components.Button;
+
+ import flatspark.enums.BrandColorEnum;
+ [Style(name="iconFontSize", type="Number", format="Length", inherit="yes", minValue="1.0", maxValue="720.0")]
+ public class ButtonIcon extends spark.components.Button
+ {
+
+ [Bindable]
+ public var iconFont:String;
+
+ [Bindable]
+ public var brand:int = BrandColorEnum.Default;
+
+ [Bindable]
+ public var fixedFontSize:Boolean = true;
+
+
+ public function ButtonIcon()
+ {
+ super();
+ }
+
+ }
+}
diff --git a/frameworks/projects/flatspark/src/flatspark/components/TextInputIcon.as b/frameworks/projects/flatspark/src/flatspark/components/TextInputIcon.as
new file mode 100644
index 0000000000..98b6a9cc1b
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/components/TextInputIcon.as
@@ -0,0 +1,35 @@
+/**
+ 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 flatspark.components
+{
+ import flash.events.FocusEvent;
+
+ import spark.components.TextInput;
+
+ public class TextInputIcon extends spark.components.TextInput
+ {
+ [Bindable]
+ public var iconFont:String;
+
+ public function TextInputIcon()
+ {
+ super();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/enums/BrandColorEnum.as b/frameworks/projects/flatspark/src/flatspark/enums/BrandColorEnum.as
new file mode 100644
index 0000000000..93742eed3b
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/enums/BrandColorEnum.as
@@ -0,0 +1,30 @@
+/**
+ 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 flatspark.enums
+{
+ public class BrandColorEnum
+ {
+ public static const Primary:int = 1;
+ public static const Success:int = 2;
+ public static const Warning:int = 3;
+ public static const Inverse:int = 4;
+ public static const Default:int = 5;
+ public static const Info:int = 6;
+ public static const Danger:int = 7;
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/enums/ButtonColorEnum.as b/frameworks/projects/flatspark/src/flatspark/enums/ButtonColorEnum.as
new file mode 100644
index 0000000000..5eae4051c3
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/enums/ButtonColorEnum.as
@@ -0,0 +1,59 @@
+/**
+ 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 flatspark.enums
+{
+ import flatspark.utils.ColorUtils;
+
+ public class ButtonColorEnum
+ {
+ public static const PrimaryUp:uint = ColorUtils.Turquoise;
+ public static const PrimaryHover:uint = 0x48C9B0;
+ public static const PrimaryDown:uint = 0x16A085;
+ public static const PrimaryDisabled:uint = ColorUtils.Turquoise;
+
+ public static const SuccessUp:uint = ColorUtils.Emerald;
+ public static const SuccessHover:uint = 0x58D68D;
+ public static const SuccessDown:uint = 0x27AD60;
+ public static const SuccessDisabled:uint = ColorUtils.Emerald;
+
+ public static const WarningUp:uint = ColorUtils.SunFlower;
+ public static const WarningHover:uint = 0xF5D313;
+ public static const WarningDown:uint = 0xCDA70D;
+ public static const WarningDisabled:uint = ColorUtils.SunFlower;
+
+ public static const InverseUp:uint = ColorUtils.WetAsphalt;
+ public static const InverseHover:uint = 0x415B76;
+ public static const InverseDown:uint = 0x2C3E50;
+ public static const InverseDisabled:uint = ColorUtils.WetAsphalt;
+
+ public static const DefaultUp:uint = ColorUtils.Silver;
+ public static const DefaultHover:uint = 0xCACFD2;
+ public static const DefaultDown:uint = 0xA1A6A9;
+ public static const DefaultDisabled:uint = ColorUtils.Silver;
+
+ public static const InfoUp:uint = ColorUtils.PeterRiver;
+ public static const InfoHover:uint = 0x5DADE2;
+ public static const InfoDown:uint = 0x2C81BA;
+ public static const InfoDisabled:uint = ColorUtils.PeterRiver;
+
+ public static const DangerUp:uint = ColorUtils.Alizarin;
+ public static const DangerHover:uint = 0xEC7063;
+ public static const DangerDown:uint = 0xC44133;
+ public static const DangerDisabled:uint = ColorUtils.Alizarin;
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/enums/ButtonSizeEnum.as b/frameworks/projects/flatspark/src/flatspark/enums/ButtonSizeEnum.as
new file mode 100644
index 0000000000..63b6f2c397
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/enums/ButtonSizeEnum.as
@@ -0,0 +1,31 @@
+/**
+ 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 flatspark.enums
+{
+ public class ButtonSizeEnum
+ {
+ public static const Large:int = 43;
+ public static const Normal:int = 32;
+ public static const Small:int = 28;
+ public static const ExtraSmall:int = 20;
+
+ public function ButtonSizeEnum()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/enums/ColorSwatchEnum.as b/frameworks/projects/flatspark/src/flatspark/enums/ColorSwatchEnum.as
new file mode 100644
index 0000000000..f497f62d7d
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/enums/ColorSwatchEnum.as
@@ -0,0 +1,40 @@
+/**
+ 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 flatspark.enums
+{
+ public class ColorSwatchEnum
+ {
+ public static const Turquoise_GreenSea:int = 1;
+ public static const Emerald_Nephritis:int = 2;
+ public static const PeterRiver_BelizeHole:int = 3;
+ public static const Amethyst_Wisteria:int = 4;
+ public static const WetAsphalt_MidnightBlue:int = 5;
+ public static const SunFlower_Orange:int = 6;
+ public static const Carrot_Pumpkin:int = 7;
+ public static const Alizarin_Pomegranate:int = 8;
+ public static const Clouds_Silver:int = 9;
+ public static const Concrete_Asbestos:int = 10;
+
+
+ private var _colorSwatch:int;
+
+ public function ColorSwatchEnum(colorSwatch:int = 3) {
+ _colorSwatch = colorSwatch;
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/enums/SizeEnum.as b/frameworks/projects/flatspark/src/flatspark/enums/SizeEnum.as
new file mode 100644
index 0000000000..fd68aeeb70
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/enums/SizeEnum.as
@@ -0,0 +1,32 @@
+/**
+ 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 flatspark.enums
+{
+ public class SizeEnum
+ {
+ public static const Small:int = 10;
+ public static const Medium:int = 12;
+ public static const Large:int = 14;
+
+ private var _size:int;
+
+ public function SizeEnum(size:int = 12) {
+ _size = size;
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/enums/TextInputSizeEnum.as b/frameworks/projects/flatspark/src/flatspark/enums/TextInputSizeEnum.as
new file mode 100644
index 0000000000..2b2568ed38
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/enums/TextInputSizeEnum.as
@@ -0,0 +1,30 @@
+/**
+ 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 flatspark.enums
+{
+ public class TextInputSizeEnum
+ {
+ public static const Large:int = 41;
+ public static const Normal:int = 38;
+ public static const Small:int = 31;
+
+ public function TextInputSizeEnum()
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/itemRenderers/DefaultItemRenderer.mxml b/frameworks/projects/flatspark/src/flatspark/itemRenderers/DefaultItemRenderer.mxml
new file mode 100644
index 0000000000..7b2a9147dd
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/itemRenderers/DefaultItemRenderer.mxml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/AlertSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/AlertSkin.mxml
new file mode 100644
index 0000000000..0e9a104f90
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/AlertSkin.mxml
@@ -0,0 +1,230 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ButtonIconSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ButtonIconSkin.mxml
new file mode 100644
index 0000000000..f4a71fa358
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ButtonIconSkin.mxml
@@ -0,0 +1,189 @@
+
+
+
+
+
+
+ [HostComponent("flatspark.components.ButtonIcon")]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ButtonSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ButtonSkin.mxml
new file mode 100644
index 0000000000..fc12a06c78
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ButtonSkin.mxml
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+ [HostComponent("spark.components.Button")]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/CheckBoxSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/CheckBoxSkin.mxml
new file mode 100644
index 0000000000..79584bde8d
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/CheckBoxSkin.mxml
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ /* Define the skin elements that should not be colorized.
+ For button, the graphics are colorized but the label is not. */
+ static private const exclusions:Array = ["labelDisplay"];
+
+ /**
+ * @private
+ */
+ override public function get colorizeExclusions():Array {return exclusions;}
+
+ /* Define the symbol fill items that should be colored by the "symbolColor" style. */
+ static private const symbols:Array = [];
+
+ /**
+ * @private
+ */
+ override public function get symbolItems():Array {return symbols};
+
+ /**
+ * @private
+ */
+ override protected function initializationComplete():void
+ {
+ useChromeColor = true;
+ super.initializationComplete();
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxButtonSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxButtonSkin.mxml
new file mode 100644
index 0000000000..5ca63a7796
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxButtonSkin.mxml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxSkin.mxml
new file mode 100644
index 0000000000..c4123653b5
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxSkin.mxml
@@ -0,0 +1,127 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxTextInputSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxTextInputSkin.mxml
new file mode 100644
index 0000000000..92acf4f2fd
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ComboBoxTextInputSkin.mxml
@@ -0,0 +1,218 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/DropDownListButtonSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/DropDownListButtonSkin.mxml
new file mode 100644
index 0000000000..2d284a4744
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/DropDownListButtonSkin.mxml
@@ -0,0 +1,109 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/DropDownListSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/DropDownListSkin.mxml
new file mode 100644
index 0000000000..d0a0a5fc95
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/DropDownListSkin.mxml
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarSkin.mxml
new file mode 100644
index 0000000000..9280a7d08f
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarSkin.mxml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ /* Define the skin elements that should not be colorized.
+ For scroll bar, the skin itself is colorized but the individual parts are not. */
+ static private const exclusions:Array = ["track", "thumb"];
+
+ /**
+ * @private
+ */
+ override public function get colorizeExclusions():Array {return exclusions;}
+
+ /**
+ * @private
+ */
+ override protected function initializationComplete():void
+ {
+ useChromeColor = true;
+ super.initializationComplete();
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarThumbSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarThumbSkin.mxml
new file mode 100644
index 0000000000..6c510d72a1
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarThumbSkin.mxml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarTrackSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarTrackSkin.mxml
new file mode 100644
index 0000000000..ef2c5511fe
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/HScrollBarTrackSkin.mxml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/PanelSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/PanelSkin.mxml
new file mode 100644
index 0000000000..00fdd7493d
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/PanelSkin.mxml
@@ -0,0 +1,253 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ProgressBarSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ProgressBarSkin.mxml
new file mode 100644
index 0000000000..e9bcb45200
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ProgressBarSkin.mxml
@@ -0,0 +1,54 @@
+
+
+
+
+ [HostComponent("spark.components.ProgressBar")]
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/RadioButtonSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/RadioButtonSkin.mxml
new file mode 100644
index 0000000000..63c10feb40
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/RadioButtonSkin.mxml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ [HostComponent("spark.components.RadioButton")]
+
+
+ /* Define the skin elements that should not be colorized.
+ For button, the graphics are colorized but the label is not. */
+ static private const exclusions:Array = ["labelDisplay"];
+
+ /**
+ * @private
+ */
+ override public function get colorizeExclusions():Array {return exclusions;}
+
+ /* Define the symbol fill items that should be colored by the "symbolColor" style. */
+ static private const symbols:Array = [];
+
+ /**
+ * @private
+ */
+ override public function get symbolItems():Array {return symbols};
+
+ /**
+ * @private
+ */
+ override protected function initializationComplete():void
+ {
+ useChromeColor = true;
+ super.initializationComplete();
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/ScrollerSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/ScrollerSkin.mxml
new file mode 100644
index 0000000000..88527788a6
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/ScrollerSkin.mxml
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/TextInputIconSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/TextInputIconSkin.mxml
new file mode 100644
index 0000000000..92df0146cb
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/TextInputIconSkin.mxml
@@ -0,0 +1,338 @@
+
+
+
+
+
+
+
+
+
+
+ @namespace s "library://ns.adobe.com/flex/spark";
+ @namespace fb "http://ns.adobe.com/flashbuilder/2009";
+ @namespace spark "spark.skins.spark.*";
+
+ *
+ {
+ /*focusColor: #FFFFFF;
+ focusThickness: 1px;
+ focusAlpha: 1;*/
+ /*focusAlpha: 0;*/
+ errorColor: #E74C3C;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/TextInputSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/TextInputSkin.mxml
new file mode 100644
index 0000000000..caf35d7a8f
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/TextInputSkin.mxml
@@ -0,0 +1,330 @@
+
+
+
+
+
+
+
+
+
+
+ @namespace s "library://ns.adobe.com/flex/spark";
+ @namespace fb "http://ns.adobe.com/flashbuilder/2009";
+ @namespace spark "spark.skins.spark.*";
+
+ *
+ {
+ /*focusColor: #FFFFFF;
+ focusThickness: 1px;
+ focusAlpha: 1;*/
+ /*focusAlpha: 0;*/
+ errorColor: #E74C3C;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/TitleWindowCloseButtonSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/TitleWindowCloseButtonSkin.mxml
new file mode 100644
index 0000000000..cfbfa7c965
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/TitleWindowCloseButtonSkin.mxml
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/TitleWindowSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/TitleWindowSkin.mxml
new file mode 100644
index 0000000000..86a37a2dd4
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/TitleWindowSkin.mxml
@@ -0,0 +1,256 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarSkin.mxml
new file mode 100644
index 0000000000..ef9f400ed8
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarSkin.mxml
@@ -0,0 +1,87 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ /* Define the skin elements that should not be colorized.
+ For scroll bar, the skin itself is colorized but the individual parts are not. */
+ static private const exclusions:Array = ["track", "thumb"];
+
+ /**
+ * @private
+ */
+ override public function get colorizeExclusions():Array {return exclusions;}
+
+ /**
+ * @private
+ */
+ override protected function initializationComplete():void
+ {
+ useChromeColor = true;
+ super.initializationComplete();
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarThumbSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarThumbSkin.mxml
new file mode 100644
index 0000000000..b73234379d
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarThumbSkin.mxml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarTrackSkin.mxml b/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarTrackSkin.mxml
new file mode 100644
index 0000000000..b7d504d6a9
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/skins/VScrollBarTrackSkin.mxml
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as b/frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as
new file mode 100644
index 0000000000..07782c51c7
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/utils/AwesomeUtils.as
@@ -0,0 +1,441 @@
+/**
+ 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 flatspark.utils
+{
+ public class AwesomeUtils
+ {
+
+ public function AwesomeUtils()
+ {
+
+ }
+
+ public static const fa_glass:String = "\uf000";
+ public static const fa_music:String = "\uf001";
+ public static const fa_search:String = "\uf002";
+ public static const fa_envelope_o:String = "\uf003";
+ public static const fa_heart:String = "\uf004";
+ public static const fa_star:String = "\uf005";
+ public static const fa_star_o:String = "\uf006";
+ public static const fa_user:String = "\uf007";
+ public static const fa_film:String = "\uf008";
+ public static const fa_th_large:String = "\uf009";
+ public static const fa_th:String = "\uf00a";
+ public static const fa_th_list:String = "\uf00b";
+ public static const fa_check:String = "\uf00c";
+ public static const fa_times:String = "\uf00d";
+ public static const fa_search_plus:String = "\uf00e";
+ public static const fa_search_minus:String = "\uf010";
+ public static const fa_power_off:String = "\uf011";
+ public static const fa_signal:String = "\uf012";
+ public static const fa_cog:String = "\uf013";
+ public static const fa_trash_o:String = "\uf014";
+ public static const fa_home:String = "\uf015";
+ public static const fa_file_o:String = "\uf016";
+ public static const fa_clock_o:String = "\uf017";
+ public static const fa_road:String = "\uf018";
+ public static const fa_download:String = "\uf019";
+ public static const fa_arrow_circle_o_down:String = "\uf01a";
+ public static const fa_arrow_circle_o_up:String = "\uf01b";
+ public static const fa_inbox:String = "\uf01c";
+ public static const fa_play_circle_o:String = "\uf01d";
+ public static const fa_repeat:String = "\uf01e";
+ public static const fa_refresh:String = "\uf021";
+ public static const fa_list_alt:String = "\uf022";
+ public static const fa_lock:String = "\uf023";
+ public static const fa_flag:String = "\uf024";
+ public static const fa_headphones:String = "\uf025";
+ public static const fa_volume_off:String = "\uf026";
+ public static const fa_volume_down:String = "\uf027";
+ public static const fa_volume_up:String = "\uf028";
+ public static const fa_qrcode:String = "\uf029";
+ public static const fa_barcode:String = "\uf02a";
+ public static const fa_tag:String = "\uf02b";
+ public static const fa_tags:String = "\uf02c";
+ public static const fa_book:String = "\uf02d";
+ public static const fa_bookmark:String = "\uf02e";
+ public static const fa_print:String = "\uf02f";
+ public static const fa_camera:String = "\uf030";
+ public static const fa_font:String = "\uf031";
+ public static const fa_bold:String = "\uf032";
+ public static const fa_italic:String = "\uf033";
+ public static const fa_text_height:String = "\uf034";
+ public static const fa_text_width:String = "\uf035";
+ public static const fa_align_left:String = "\uf036";
+ public static const fa_align_center:String = "\uf037";
+ public static const fa_align_right:String = "\uf038";
+ public static const fa_align_justify:String = "\uf039";
+ public static const fa_list:String = "\uf03a";
+ public static const fa_outdent:String = "\uf03b";
+ public static const fa_indent:String = "\uf03c";
+ public static const fa_video_camera:String = "\uf03d";
+ public static const fa_picture_o:String = "\uf03e";
+ public static const fa_pencil:String = "\uf040";
+ public static const fa_map_marker:String = "\uf041";
+ public static const fa_adjust:String = "\uf042";
+ public static const fa_tint:String = "\uf043";
+ public static const fa_pencil_square_o:String = "\uf044";
+ public static const fa_share_square_o:String = "\uf045";
+ public static const fa_check_square_o:String = "\uf046";
+ public static const fa_arrows:String = "\uf047";
+ public static const fa_step_backward:String = "\uf048";
+ public static const fa_fast_backward:String = "\uf049";
+ public static const fa_backward:String = "\uf04a";
+ public static const fa_play:String = "\uf04b";
+ public static const fa_pause:String = "\uf04c";
+ public static const fa_stop:String = "\uf04d";
+ public static const fa_forward:String = "\uf04e";
+ public static const fa_fast_forward:String = "\uf050";
+ public static const fa_step_forward:String = "\uf051";
+ public static const fa_eject:String = "\uf052";
+ public static const fa_chevron_left:String = "\uf053";
+ public static const fa_chevron_right:String = "\uf054";
+ public static const fa_plus_circle:String = "\uf055";
+ public static const fa_minus_circle:String = "\uf056";
+ public static const fa_times_circle:String = "\uf057";
+ public static const fa_check_circle:String = "\uf058";
+ public static const fa_question_circle:String = "\uf059";
+ public static const fa_info_circle:String = "\uf05a";
+ public static const fa_crosshairs:String = "\uf05b";
+ public static const fa_times_circle_o:String = "\uf05c";
+ public static const fa_check_circle_o:String = "\uf05d";
+ public static const fa_ban:String = "\uf05e";
+ public static const fa_arrow_left:String = "\uf060";
+ public static const fa_arrow_right:String = "\uf061";
+ public static const fa_arrow_up:String = "\uf062";
+ public static const fa_arrow_down:String = "\uf063";
+ public static const fa_share:String = "\uf064";
+ public static const fa_expand:String = "\uf065";
+ public static const fa_compress:String = "\uf066";
+ public static const fa_plus:String = "\uf067";
+ public static const fa_minus:String = "\uf068";
+ public static const fa_asterisk:String = "\uf069";
+ public static const fa_exclamation_circle:String = "\uf06a";
+ public static const fa_gift:String = "\uf06b";
+ public static const fa_leaf:String = "\uf06c";
+ public static const fa_fire:String = "\uf06d";
+ public static const fa_eye:String = "\uf06e";
+ public static const fa_eye_slash:String = "\uf070";
+ public static const fa_exclamation_triangle:String = "\uf071";
+ public static const fa_plane:String = "\uf072";
+ public static const fa_calendar:String = "\uf073";
+ public static const fa_random:String = "\uf074";
+ public static const fa_comment:String = "\uf075";
+ public static const fa_magnet:String = "\uf076";
+ public static const fa_chevron_up:String = "\uf077";
+ public static const fa_chevron_down:String = "\uf078";
+ public static const fa_retweet:String = "\uf079";
+ public static const fa_shopping_cart:String = "\uf07a";
+ public static const fa_folder:String = "\uf07b";
+ public static const fa_folder_open:String = "\uf07c";
+ public static const fa_arrows_v:String = "\uf07d";
+ public static const fa_arrows_h:String = "\uf07e";
+ public static const fa_bar_chart_o:String = "\uf080";
+ public static const fa_twitter_square:String = "\uf081";
+ public static const fa_facebook_square:String = "\uf082";
+ public static const fa_camera_retro:String = "\uf083";
+ public static const fa_key:String = "\uf084";
+ public static const fa_cogs:String = "\uf085";
+ public static const fa_comments:String = "\uf086";
+ public static const fa_thumbs_o_up:String = "\uf087";
+ public static const fa_thumbs_o_down:String = "\uf088";
+ public static const fa_star_half:String = "\uf089";
+ public static const fa_heart_o:String = "\uf08a";
+ public static const fa_sign_out:String = "\uf08b";
+ public static const fa_linkedin_square:String = "\uf08c";
+ public static const fa_thumb_tack:String = "\uf08d";
+ public static const fa_external_link:String = "\uf08e";
+ public static const fa_sign_in:String = "\uf090";
+ public static const fa_trophy:String = "\uf091";
+ public static const fa_github_square:String = "\uf092";
+ public static const fa_upload:String = "\uf093";
+ public static const fa_lemon_o:String = "\uf094";
+ public static const fa_phone:String = "\uf095";
+ public static const fa_square_o:String = "\uf096";
+ public static const fa_bookmark_o:String = "\uf097";
+ public static const fa_phone_square:String = "\uf098";
+ public static const fa_twitter:String = "\uf099";
+ public static const fa_facebook:String = "\uf09a";
+ public static const fa_github:String = "\uf09b";
+ public static const fa_unlock:String = "\uf09c";
+ public static const fa_credit_card:String = "\uf09d";
+ public static const fa_rss:String = "\uf09e";
+ public static const fa_hdd_o:String = "\uf0a0";
+ public static const fa_bullhorn:String = "\uf0a1";
+ public static const fa_bell:String = "\uf0f3";
+ public static const fa_certificate:String = "\uf0a3";
+ public static const fa_hand_o_right:String = "\uf0a4";
+ public static const fa_hand_o_left:String = "\uf0a5";
+ public static const fa_hand_o_up:String = "\uf0a6";
+ public static const fa_hand_o_down:String = "\uf0a7";
+ public static const fa_arrow_circle_left:String = "\uf0a8";
+ public static const fa_arrow_circle_right:String = "\uf0a9";
+ public static const fa_arrow_circle_up:String = "\uf0aa";
+ public static const fa_arrow_circle_down:String = "\uf0ab";
+ public static const fa_globe:String = "\uf0ac";
+ public static const fa_wrench:String = "\uf0ad";
+ public static const fa_tasks:String = "\uf0ae";
+ public static const fa_filter:String = "\uf0b0";
+ public static const fa_briefcase:String = "\uf0b1";
+ public static const fa_arrows_alt:String = "\uf0b2";
+ public static const fa_users:String = "\uf0c0";
+ public static const fa_link:String = "\uf0c1";
+ public static const fa_cloud:String = "\uf0c2";
+ public static const fa_flask:String = "\uf0c3";
+ public static const fa_scissors:String = "\uf0c4";
+ public static const fa_files_o:String = "\uf0c5";
+ public static const fa_paperclip:String = "\uf0c6";
+ public static const fa_floppy_o:String = "\uf0c7";
+ public static const fa_square:String = "\uf0c8";
+ public static const fa_bars:String = "\uf0c9";
+ public static const fa_list_ul:String = "\uf0ca";
+ public static const fa_list_ol:String = "\uf0cb";
+ public static const fa_strikethrough:String = "\uf0cc";
+ public static const fa_underline:String = "\uf0cd";
+ public static const fa_table:String = "\uf0ce";
+ public static const fa_magic:String = "\uf0d0";
+ public static const fa_truck:String = "\uf0d1";
+ public static const fa_pinterest:String = "\uf0d2";
+ public static const fa_pinterest_square:String = "\uf0d3";
+ public static const fa_google_plus_square:String = "\uf0d4";
+ public static const fa_google_plus:String = "\uf0d5";
+ public static const fa_money:String = "\uf0d6";
+ public static const fa_caret_down:String = "\uf0d7";
+ public static const fa_caret_up:String = "\uf0d8";
+ public static const fa_caret_left:String = "\uf0d9";
+ public static const fa_caret_right:String = "\uf0da";
+ public static const fa_columns:String = "\uf0db";
+ public static const fa_sort:String = "\uf0dc";
+ public static const fa_sort_asc:String = "\uf0dd";
+ public static const fa_sort_desc:String = "\uf0de";
+ public static const fa_envelope:String = "\uf0e0";
+ public static const fa_linkedin:String = "\uf0e1";
+ public static const fa_undo:String = "\uf0e2";
+ public static const fa_gavel:String = "\uf0e3";
+ public static const fa_tachometer:String = "\uf0e4";
+ public static const fa_comment_o:String = "\uf0e5";
+ public static const fa_comments_o:String = "\uf0e6";
+ public static const fa_bolt:String = "\uf0e7";
+ public static const fa_sitemap:String = "\uf0e8";
+ public static const fa_umbrella:String = "\uf0e9";
+ public static const fa_clipboard:String = "\uf0ea";
+ public static const fa_lightbulb_o:String = "\uf0eb";
+ public static const fa_exchange:String = "\uf0ec";
+ public static const fa_cloud_download:String = "\uf0ed";
+ public static const fa_cloud_upload:String = "\uf0ee";
+ public static const fa_user_md:String = "\uf0f0";
+ public static const fa_stethoscope:String = "\uf0f1";
+ public static const fa_suitcase:String = "\uf0f2";
+ public static const fa_bell_o:String = "\uf0a2";
+ public static const fa_coffee:String = "\uf0f4";
+ public static const fa_cutlery:String = "\uf0f5";
+ public static const fa_file_text_o:String = "\uf0f6";
+ public static const fa_building_o:String = "\uf0f7";
+ public static const fa_hospital_o:String = "\uf0f8";
+ public static const fa_ambulance:String = "\uf0f9";
+ public static const fa_medkit:String = "\uf0fa";
+ public static const fa_fighter_jet:String = "\uf0fb";
+ public static const fa_beer:String = "\uf0fc";
+ public static const fa_h_square:String = "\uf0fd";
+ public static const fa_plus_square:String = "\uf0fe";
+ public static const fa_angle_double_left:String = "\uf100";
+ public static const fa_angle_double_right:String = "\uf101";
+ public static const fa_angle_double_up:String = "\uf102";
+ public static const fa_angle_double_down:String = "\uf103";
+ public static const fa_angle_left:String = "\uf104";
+ public static const fa_angle_right:String = "\uf105";
+ public static const fa_angle_up:String = "\uf106";
+ public static const fa_angle_down:String = "\uf107";
+ public static const fa_desktop:String = "\uf108";
+ public static const fa_laptop:String = "\uf109";
+ public static const fa_tablet:String = "\uf10a";
+ public static const fa_mobile:String = "\uf10b";
+ public static const fa_circle_o:String = "\uf10c";
+ public static const fa_quote_left:String = "\uf10d";
+ public static const fa_quote_right:String = "\uf10e";
+ public static const fa_spinner:String = "\uf110";
+ public static const fa_circle:String = "\uf111";
+ public static const fa_reply:String = "\uf112";
+ public static const fa_github_alt:String = "\uf113";
+ public static const fa_folder_o:String = "\uf114";
+ public static const fa_folder_open_o:String = "\uf115";
+ public static const fa_smile_o:String = "\uf118";
+ public static const fa_frown_o:String = "\uf119";
+ public static const fa_meh_o:String = "\uf11a";
+ public static const fa_gamepad:String = "\uf11b";
+ public static const fa_keyboard_o:String = "\uf11c";
+ public static const fa_flag_o:String = "\uf11d";
+ public static const fa_flag_checkered:String = "\uf11e";
+ public static const fa_terminal:String = "\uf120";
+ public static const fa_code:String = "\uf121";
+ public static const fa_reply_all:String = "\uf122";
+ public static const fa_mail_reply_all:String = "\uf122";
+ public static const fa_star_half_o:String = "\uf123";
+ public static const fa_location_arrow:String = "\uf124";
+ public static const fa_crop:String = "\uf125";
+ public static const fa_code_fork:String = "\uf126";
+ public static const fa_chain_broken:String = "\uf127";
+ public static const fa_question:String = "\uf128";
+ public static const fa_info:String = "\uf129";
+ public static const fa_exclamation:String = "\uf12a";
+ public static const fa_superscript:String = "\uf12b";
+ public static const fa_subscript:String = "\uf12c";
+ public static const fa_eraser:String = "\uf12d";
+ public static const fa_puzzle_piece:String = "\uf12e";
+ public static const fa_microphone:String = "\uf130";
+ public static const fa_microphone_slash:String = "\uf131";
+ public static const fa_shield:String = "\uf132";
+ public static const fa_calendar_o:String = "\uf133";
+ public static const fa_fire_extinguisher:String = "\uf134";
+ public static const fa_rocket:String = "\uf135";
+ public static const fa_maxcdn:String = "\uf136";
+ public static const fa_chevron_circle_left:String = "\uf137";
+ public static const fa_chevron_circle_right:String = "\uf138";
+ public static const fa_chevron_circle_up:String = "\uf139";
+ public static const fa_chevron_circle_down:String = "\uf13a";
+ public static const fa_html5:String = "\uf13b";
+ public static const fa_css3:String = "\uf13c";
+ public static const fa_anchor:String = "\uf13d";
+ public static const fa_unlock_alt:String = "\uf13e";
+ public static const fa_bullseye:String = "\uf140";
+ public static const fa_ellipsis_h:String = "\uf141";
+ public static const fa_ellipsis_v:String = "\uf142";
+ public static const fa_rss_square:String = "\uf143";
+ public static const fa_play_circle:String = "\uf144";
+ public static const fa_ticket:String = "\uf145";
+ public static const fa_minus_square:String = "\uf146";
+ public static const fa_minus_square_o:String = "\uf147";
+ public static const fa_level_up:String = "\uf148";
+ public static const fa_level_down:String = "\uf149";
+ public static const fa_check_square:String = "\uf14a";
+ public static const fa_pencil_square:String = "\uf14b";
+ public static const fa_external_link_square:String = "\uf14c";
+ public static const fa_share_square:String = "\uf14d";
+ public static const fa_compass:String = "\uf14e";
+ public static const fa_caret_square_o_down:String = "\uf150";
+ public static const fa_caret_square_o_up:String = "\uf151";
+ public static const fa_caret_square_o_right:String = "\uf152";
+ public static const fa_eur:String = "\uf153";
+ public static const fa_gbp:String = "\uf154";
+ public static const fa_usd:String = "\uf155";
+ public static const fa_inr:String = "\uf156";
+ public static const fa_jpy:String = "\uf157";
+ public static const fa_rub:String = "\uf158";
+ public static const fa_krw:String = "\uf159";
+ public static const fa_btc:String = "\uf15a";
+ public static const fa_file:String = "\uf15b";
+ public static const fa_file_text:String = "\uf15c";
+ public static const fa_sort_alpha_asc:String = "\uf15d";
+ public static const fa_sort_alpha_desc:String = "\uf15e";
+ public static const fa_sort_amount_asc:String = "\uf160";
+ public static const fa_sort_amount_desc:String = "\uf161";
+ public static const fa_sort_numeric_asc:String = "\uf162";
+ public static const fa_sort_numeric_desc:String = "\uf163";
+ public static const fa_thumbs_up:String = "\uf164";
+ public static const fa_thumbs_down:String = "\uf165";
+ public static const fa_youtube_square:String = "\uf166";
+ public static const fa_youtube:String = "\uf167";
+ public static const fa_xing:String = "\uf168";
+ public static const fa_xing_square:String = "\uf169";
+ public static const fa_youtube_play:String = "\uf16a";
+ public static const fa_dropbox:String = "\uf16b";
+ public static const fa_stack_overflow:String = "\uf16c";
+ public static const fa_instagram:String = "\uf16d";
+ public static const fa_flickr:String = "\uf16e";
+ public static const fa_adn:String = "\uf170";
+ public static const fa_bitbucket:String = "\uf171";
+ public static const fa_bitbucket_square:String = "\uf172";
+ public static const fa_tumblr:String = "\uf173";
+ public static const fa_tumblr_square:String = "\uf174";
+ public static const fa_long_arrow_down:String = "\uf175";
+ public static const fa_long_arrow_up:String = "\uf176";
+ public static const fa_long_arrow_left:String = "\uf177";
+ public static const fa_long_arrow_right:String = "\uf178";
+ public static const fa_apple:String = "\uf179";
+ public static const fa_windows:String = "\uf17a";
+ public static const fa_android:String = "\uf17b";
+ public static const fa_linux:String = "\uf17c";
+ public static const fa_dribbble:String = "\uf17d";
+ public static const fa_skype:String = "\uf17e";
+ public static const fa_foursquare:String = "\uf180";
+ public static const fa_trello:String = "\uf181";
+ public static const fa_female:String = "\uf182";
+ public static const fa_male:String = "\uf183";
+ public static const fa_gittip:String = "\uf184";
+ public static const fa_sun_o:String = "\uf185";
+ public static const fa_moon_o:String = "\uf186";
+ public static const fa_archive:String = "\uf187";
+ public static const fa_bug:String = "\uf188";
+ public static const fa_vk:String = "\uf189";
+ public static const fa_weibo:String = "\uf18a";
+ public static const fa_renren:String = "\uf18b";
+ public static const fa_pagelines:String = "\uf18c";
+ public static const fa_stack_exchange:String = "\uf18d";
+ public static const fa_arrow_circle_o_right:String = "\uf18e";
+ public static const fa_arrow_circle_o_left:String = "\uf190";
+ public static const fa_caret_square_o_left:String = "\uf191";
+ public static const fa_dot_circle_o:String = "\uf192";
+ public static const fa_wheelchair:String = "\uf193";
+ public static const fa_vimeo_square:String = "\uf194";
+ public static const fa_try:String = "\uf195";
+ public static const fa_plus_square_o:String = "\uf196";
+ public static const fa_angellist:String = "\uf209";
+ public static const fa_area_chart:String = "\uf1fe";
+ public static const fa_at:String = "\uf1fa";
+ public static const fa_bell_slash:String = "\uf1f6";
+ public static const fa_bell_slash_o:String = "\uf1f7";
+ public static const fa_bicycle:String = "\uf206";
+ public static const fa_binoculars:String = "\uf1e5";
+ public static const fa_birthday_cake:String = "\uf1fd";
+ public static const fa_bus:String = "\uf207";
+ public static const fa_calculator:String = "\uf1ec";
+ public static const fa_cc:String = "\uf20a";
+ public static const fa_cc_amex:String = "\uf1f3";
+ public static const fa_cc_discover:String = "\uf1f2";
+ public static const fa_cc_mastercard:String = "\uf1f1";
+ public static const fa_cc_paypal:String = "\uf1f4";
+ public static const fa_cc_stripe:String = "\uf1f5";
+ public static const fa_cc_visa:String = "\uf1f0";
+ public static const fa_copyright:String = "\uf1f9";
+ public static const fa_eyedropper:String = "\uf1fb";
+ public static const fa_futbol_o:String = "\uf1e3";
+ public static const fa_google_wallet:String = "\uf1ee";
+ public static const fa_ils:String = "\uf20b";
+ public static const fa_ioxhost:String = "\uf208";
+ public static const fa_lastfm:String = "\uf202";
+ public static const fa_lastfm_square:String = "\uf203";
+ public static const fa_line_chart:String = "\uf201";
+ public static const fa_meanpath:String = "\uf20c";
+ public static const fa_newspaper_o:String = "\uf1ea";
+ public static const fa_paint_brush:String = "\uf1fc";
+ public static const fa_paypal:String = "\uf1ed";
+ public static const fa_pie_chart:String = "\uf200";
+ public static const fa_plug:String = "\uf1e6";
+ public static const fa_shekel:String = "\uf20b";
+ public static const fa_sheqel:String = "\uf20b";
+ public static const fa_slideshare:String = "\uf1e7";
+ public static const fa_soccer_ball_o:String = "\uf1e3";
+ public static const fa_toggle_off:String = "\uf204";
+ public static const fa_toggle_on:String = "\uf205";
+ public static const fa_trash:String = "\uf1f8";
+ public static const fa_tty:String = "\uf1e4";
+ public static const fa_twitch:String = "\uf1e8";
+ public static const fa_wifi:String = "\uf1eb";
+ public static const fa_yelp:String = "\uf1e9";
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/utils/ColorUtils.as b/frameworks/projects/flatspark/src/flatspark/utils/ColorUtils.as
new file mode 100644
index 0000000000..09f9cb2252
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/utils/ColorUtils.as
@@ -0,0 +1,90 @@
+/**
+ 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 flatspark.utils
+{
+ import mx.states.State;
+
+ import flatspark.enums.BrandColorEnum;
+ import flatspark.enums.ButtonColorEnum;
+
+ public class ColorUtils
+ {
+ public static const Turquoise:uint = 0x1ABC9C;
+ public static const GreenSea:uint = 0x16A085;
+ public static const Emerald:uint = 0x2ECC71;
+ public static const Nephritis:uint = 0x27AE60;
+ public static const PeterRiver:uint = 0x3498DB;
+ public static const BelizeHole:uint = 0x2980B9;
+ public static const Amethyst:uint = 0x9B59B6;
+ public static const Wisteria:uint = 0x8E44AD;
+ public static const WetAsphalt:uint = 0x34495E;
+ public static const MidnightBlue:uint = 0x2C3E50;
+ public static const SunFlower:uint = 0xF1C40F;
+ public static const Orange:uint = 0xF39C12;
+ public static const Carrot:uint = 0xE67E22;
+ public static const Pumpkin:uint = 0xD35400;
+ public static const Alizarin:uint = 0xE74C3C;
+ public static const Pomegranate:uint = 0xC0392B;
+ public static const Clouds:uint = 0xECF0F1;
+ public static const Silver:uint = 0xBDC3C7;
+ public static const Concrete:uint = 0x95A5A6;
+ public static const Asbestos:uint = 0x7F8C8D;
+
+ public function ColorUtils()
+ {
+
+ }
+
+ public static function ButtonColor(brand:int, estado:State):uint
+ {
+ // All the possible colors
+ var cores:Array = new Array(
+ ButtonColorEnum.PrimaryUp, ButtonColorEnum.PrimaryHover, ButtonColorEnum.PrimaryDown, ButtonColorEnum.PrimaryDisabled,
+ ButtonColorEnum.SuccessUp, ButtonColorEnum.SuccessHover, ButtonColorEnum.SuccessDown, ButtonColorEnum.SuccessDisabled,
+ ButtonColorEnum.WarningUp, ButtonColorEnum.WarningHover, ButtonColorEnum.WarningDown, ButtonColorEnum.WarningDisabled,
+ ButtonColorEnum.InverseUp, ButtonColorEnum.InverseHover, ButtonColorEnum.InverseDown, ButtonColorEnum.InverseDisabled,
+ ButtonColorEnum.DefaultUp, ButtonColorEnum.DefaultHover, ButtonColorEnum.DefaultDown, ButtonColorEnum.DefaultDisabled,
+ ButtonColorEnum.InfoUp, ButtonColorEnum.InfoHover, ButtonColorEnum.InfoDown, ButtonColorEnum.InfoDisabled,
+ ButtonColorEnum.DangerUp, ButtonColorEnum.DangerHover, ButtonColorEnum.DangerDown, ButtonColorEnum.DangerDisabled
+ );
+
+ // Map all the allowed states
+ var numeroEstado:int = 1;
+ switch (estado.name)
+ {
+ case "up":
+ numeroEstado = 1;
+ break;
+ case "over":
+ numeroEstado = 2;
+ break;
+ case "down":
+ numeroEstado = 3;
+ break;
+ case "disabled":
+ numeroEstado = 3;
+ break;
+ }
+
+ var posicao:int = 1;
+ posicao = 4 * (brand - 1) + (numeroEstado - 1);
+
+ return cores[posicao];
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/flatspark/src/flatspark/utils/ConfigSkin.as b/frameworks/projects/flatspark/src/flatspark/utils/ConfigSkin.as
new file mode 100644
index 0000000000..5889da1c1d
--- /dev/null
+++ b/frameworks/projects/flatspark/src/flatspark/utils/ConfigSkin.as
@@ -0,0 +1,44 @@
+/**
+ 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 flatspark.utils
+{
+
+ import flatspark.enums.ColorSwatchEnum;
+ import flatspark.enums.SizeEnum;
+
+ public final class ConfigSkin
+ {
+
+ /*
+ * Default size
+ */
+ public static var sizeEnum:SizeEnum=new SizeEnum();
+
+ /*
+ * Default color
+ */
+ public static var colorSwatch:ColorSwatchEnum=new ColorSwatchEnum();
+
+
+ public function ConfigSkin()
+ {
+
+ }
+
+ }
+}
diff --git a/frameworks/projects/framework/bundles/en_AU/validators.properties b/frameworks/projects/framework/bundles/en_AU/validators.properties
index e70cd91ae2..8a5a6feb3c 100644
--- a/frameworks/projects/framework/bundles/en_AU/validators.properties
+++ b/frameworks/projects/framework/bundles/en_AU/validators.properties
@@ -100,9 +100,9 @@ formatError=Configuration error: Incorrect formatting string.
invalidCharErrorEV=Your email address contains invalid characters.
invalidDomainErrorEV=The domain in your email address is incorrectly formatted.
invalidIPDomainError=The IP domain in your email address is incorrectly formatted.
-invalidPeriodsInDomainError=The domain in your email address has consecutive periods.
+invalidPeriodsInDomainError=The domain in your email address has consecutive full stops.
missingAtSignError=An at sign (@) is missing in your email address.
-missingPeriodInDomainError=The domain in your email address is missing a period.
+missingPeriodInDomainError=The domain in your email address is missing a full stop.
missingUsernameError=The user name in your email address is missing.
tooManyAtSignsError=Your email address contains too many @ characters.
diff --git a/frameworks/projects/framework/src/FrameworkClasses.as b/frameworks/projects/framework/src/FrameworkClasses.as
index cd6b13cbae..bb622d35eb 100644
--- a/frameworks/projects/framework/src/FrameworkClasses.as
+++ b/frameworks/projects/framework/src/FrameworkClasses.as
@@ -155,6 +155,7 @@ internal class FrameworkClasses
import mx.styles.IStyleModule; IStyleModule;
import mx.styles.AdvancedStyleClient; AdvancedStyleClient;
import mx.utils.ArrayUtil; ArrayUtil;
+ import mx.utils.AndroidPlatformVersionOverride; AndroidPlatformVersionOverride;
import mx.utils.Base64Decoder; Base64Decoder;
import mx.utils.Base64Encoder; Base64Encoder;
import mx.utils.BitFlagUtil; BitFlagUtil;
@@ -163,6 +164,8 @@ internal class FrameworkClasses
import mx.utils.DisplayUtil; DisplayUtil;
import mx.utils.GetTimerUtil; GetTimerUtil;
import mx.utils.HSBColor; HSBColor;
+ import mx.utils.IOSPlatformVersionOverride; IOSPlatformVersionOverride;
+ import mx.utils.LegacyMobileThemeOverride; LegacyMobileThemeOverride;
import mx.utils.LinkedList; LinkedList;
import mx.utils.LinkedListNode; LinkedListNode;
import mx.utils.OnDemandEventDispatcher; OnDemandEventDispatcher;
diff --git a/frameworks/projects/framework/src/mx/binding/Binding.as b/frameworks/projects/framework/src/mx/binding/Binding.as
index b2e059868e..6122921613 100644
--- a/frameworks/projects/framework/src/mx/binding/Binding.as
+++ b/frameworks/projects/framework/src/mx/binding/Binding.as
@@ -423,46 +423,44 @@ public class Binding
wrappedFunctionSuccessful = true;
return result;
}
- catch(itemPendingError:ItemPendingError)
- {
- itemPendingError.addResponder(new EvalBindingResponder(this, object));
- if (BindingManager.debugDestinationStrings[destString])
- {
- trace("Binding: destString = " + destString + ", error = " + itemPendingError);
- }
- }
- catch(rangeError:RangeError)
- {
- if (BindingManager.debugDestinationStrings[destString])
- {
- trace("Binding: destString = " + destString + ", error = " + rangeError);
- }
- }
catch(error:Error)
{
- // Certain errors are normal when executing a srcFunc or destFunc,
- // so we swallow them:
- // Error #1006: Call attempted on an object that is not a function.
- // Error #1009: null has no properties.
- // Error #1010: undefined has no properties.
- // Error #1055: - has no properties.
- // Error #1069: Property - not found on - and there is no default value
- // We allow any other errors to be thrown.
- if ((error.errorID != 1006) &&
- (error.errorID != 1009) &&
- (error.errorID != 1010) &&
- (error.errorID != 1055) &&
- (error.errorID != 1069))
- {
- throw error;
- }
- else
- {
- if (BindingManager.debugDestinationStrings[destString])
- {
- trace("Binding: destString = " + destString + ", error = " + error);
- }
- }
+ if (error is ItemPendingError) {
+ error.addResponder(new EvalBindingResponder(this, object));
+ if (BindingManager.debugDestinationStrings[destString])
+ {
+ trace("Binding: destString = " + destString + ", error = " + error);
+ }
+ } else if (error is RangeError) {
+ if (BindingManager.debugDestinationStrings[destString])
+ {
+ trace("Binding: destString = " + destString + ", error = " + error);
+ }
+ } else {
+ // Certain errors are normal when executing a srcFunc or destFunc,
+ // so we swallow them:
+ // Error #1006: Call attempted on an object that is not a function.
+ // Error #1009: null has no properties.
+ // Error #1010: undefined has no properties.
+ // Error #1055: - has no properties.
+ // Error #1069: Property - not found on - and there is no default value
+ // We allow any other errors to be thrown.
+ if ((error.errorID != 1006) &&
+ (error.errorID != 1009) &&
+ (error.errorID != 1010) &&
+ (error.errorID != 1055) &&
+ (error.errorID != 1069))
+ {
+ throw error;
+ }
+ else
+ {
+ if (BindingManager.debugDestinationStrings[destString])
+ {
+ trace("Binding: destString = " + destString + ", error = " + error);
+ }
+ }
+ }
}
return null;
diff --git a/frameworks/projects/framework/src/mx/binding/Watcher.as b/frameworks/projects/framework/src/mx/binding/Watcher.as
index ac35300e18..fef6ee3868 100644
--- a/frameworks/projects/framework/src/mx/binding/Watcher.as
+++ b/frameworks/projects/framework/src/mx/binding/Watcher.as
@@ -199,37 +199,35 @@ public class Watcher
{
wrappedFunction.apply(this);
}
- catch(itemPendingError:ItemPendingError)
- {
- // The parent's value is not yet available. This is being ignored for now -
- // updateParent() will be called when the parent has a value.
- value = null;
- }
- catch(rangeError:RangeError)
- {
- // The parent's value is not yet available. This is being ignored for now -
- // updateParent() will be called when the parent has a value.
- value = null;
- }
catch(error:Error)
{
- // Certain errors are normal when executing an update, so we swallow them:
- // Error #1006: Call attempted on an object that is not a function.
- // Error #1009: null has no properties.
- // Error #1010: undefined has no properties.
- // Error #1055: - has no properties.
- // Error #1069: Property - not found on - and there is no default value
- // Error #1507: - invalid null argument.
- // We allow any other errors to be thrown.
- if ((error.errorID != 1006) &&
- (error.errorID != 1009) &&
- (error.errorID != 1010) &&
- (error.errorID != 1055) &&
- (error.errorID != 1069) &&
- (error.errorID != 1507))
- {
- throw error;
- }
+ if (error is ItemPendingError) {
+ // The parent's value is not yet available. This is being ignored for now -
+ // updateParent() will be called when the parent has a value.
+ value = null;
+ } else if (error is RangeError) {
+ // The parent's value is not yet available. This is being ignored for now -
+ // updateParent() will be called when the parent has a value.
+ value = null;
+ } else {
+ // Certain errors are normal when executing an update, so we swallow them:
+ // Error #1006: Call attempted on an object that is not a function.
+ // Error #1009: null has no properties.
+ // Error #1010: undefined has no properties.
+ // Error #1055: - has no properties.
+ // Error #1069: Property - not found on - and there is no default value
+ // Error #1507: - invalid null argument.
+ // We allow any other errors to be thrown.
+ if ((error.errorID != 1006) &&
+ (error.errorID != 1009) &&
+ (error.errorID != 1010) &&
+ (error.errorID != 1055) &&
+ (error.errorID != 1069) &&
+ (error.errorID != 1507))
+ {
+ throw error;
+ }
+ }
}
}
diff --git a/frameworks/projects/framework/src/mx/collections/XMLListAdapter.as b/frameworks/projects/framework/src/mx/collections/XMLListAdapter.as
index 17d2173b17..0a8b5e6e02 100644
--- a/frameworks/projects/framework/src/mx/collections/XMLListAdapter.as
+++ b/frameworks/projects/framework/src/mx/collections/XMLListAdapter.as
@@ -420,7 +420,7 @@ public class XMLListAdapter extends EventDispatcher implements IList, IXMLNotifi
*/
public function removeItem( item:Object ):Boolean
{
- var _item:Object = removeItemAt[getItemIndex(item)];
+ var _item:Object = removeItemAt(getItemIndex(item));
return _item != null;
}
diff --git a/frameworks/projects/framework/src/mx/core/FlexVersion.as b/frameworks/projects/framework/src/mx/core/FlexVersion.as
index 41c63fcb1c..f99b634ab4 100644
--- a/frameworks/projects/framework/src/mx/core/FlexVersion.as
+++ b/frameworks/projects/framework/src/mx/core/FlexVersion.as
@@ -56,8 +56,22 @@ public class FlexVersion
* @playerversion AIR 1.1
* @productversion Flex 3
*/
- public static const CURRENT_VERSION:uint = 0x040D0000;
+ public static const CURRENT_VERSION:uint = 0x040E0000;
+ /**
+ * The compatibilityVersion value of Flex 4.14,
+ * encoded numerically as a uint.
+ * Code can compare this constant against
+ * the compatibilityVersion
+ * to implement version-specific behavior.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 11
+ * @playerversion AIR 3
+ * @productversion Apache Flex 4.14
+ */
+ public static const VERSION_4_14:uint = 0x040E0000;
+
/**
* The compatibilityVersion value of Flex 4.13,
* encoded numerically as a uint.
diff --git a/frameworks/projects/framework/src/mx/core/RuntimeDPIProvider.as b/frameworks/projects/framework/src/mx/core/RuntimeDPIProvider.as
index 7ce8cc7b48..7d82fb8b55 100644
--- a/frameworks/projects/framework/src/mx/core/RuntimeDPIProvider.as
+++ b/frameworks/projects/framework/src/mx/core/RuntimeDPIProvider.as
@@ -118,31 +118,34 @@ public class RuntimeDPIProvider
*/
public function get runtimeDPI():Number
- {
- var isIOS:Boolean = Platform.isIOS;
- var screenDPI:Number = Capabilities.screenDPI;
-
- if (isIOS) // as isIPad returns false in the simulator
+ {
+ if (Platform.isIOS) // as isIPad returns false in the simulator
{
- var root:DisplayObject = SystemManager.getSWFRoot(this);
- if (root != null ) {
- var stage:Stage = root.stage;
- if (stage != null){
- var scX:Number = stage.fullScreenWidth;
- var scY:Number = stage.fullScreenHeight;
- /* as of Dec 2013, iPad (resp. iPad retina) are the only iOS devices to have 1024 (resp. 2048) screen width or height
- cf http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density#Apple
- * */
- if ((scX == IPAD_RETINA_MAX_EXTENT || scY == IPAD_RETINA_MAX_EXTENT))
- return DPIClassification.DPI_320;
- else if (scX == IPAD_MAX_EXTENT || scY == IPAD_MAX_EXTENT)
- return DPIClassification.DPI_160;
- }
- }
- }
-
- return classifyDPI(screenDPI);
- }
+ var scX:Number = Capabilities.screenResolutionX;
+ var scY:Number = Capabilities.screenResolutionY;
+
+ // Use the stage width/height only when debugging, because Capabilities reports the computer resolution
+ if (Capabilities.isDebugger)
+ {
+ var root:DisplayObject = SystemManager.getSWFRoot(this);
+ if (root && root.stage)
+ {
+ scX = root.stage.fullScreenWidth;
+ scY = root.stage.fullScreenHeight;
+ }
+ }
+
+ /* as of Dec 2013, iPad (resp. iPad retina) are the only iOS devices to have 1024 (resp. 2048) screen width or height
+ cf http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density#Apple
+ * */
+ if (scX == IPAD_MAX_EXTENT || scY == IPAD_MAX_EXTENT)
+ return DPIClassification.DPI_160;
+ else if ((scX == IPAD_RETINA_MAX_EXTENT || scY == IPAD_RETINA_MAX_EXTENT))
+ return DPIClassification.DPI_320;
+ }
+
+ return classifyDPI(Capabilities.screenDPI);
+ }
/**
* @private
diff --git a/frameworks/projects/framework/src/mx/core/UIComponent.as b/frameworks/projects/framework/src/mx/core/UIComponent.as
index 06ae5864a0..7432f5238f 100644
--- a/frameworks/projects/framework/src/mx/core/UIComponent.as
+++ b/frameworks/projects/framework/src/mx/core/UIComponent.as
@@ -13659,6 +13659,12 @@ public class UIComponent extends FlexSprite
* Dispatches an event into the event flow.
* The event target is the EventDispatcher object upon which
* the dispatchEvent() method is called.
+ *
+ * Note that when dispatchEvent() is called by code inside a
+ * try block, any error thrown thereafter can be caught by
+ * listening to LoaderInfo.uncaughtErrorEvents. It will NOT reach the
+ * catch block.
+ *
*
* @param event The Event object that is dispatched into the event flow.
* If the event is being redispatched, a clone of the event is created automatically.
diff --git a/frameworks/projects/framework/src/mx/core/Version.as b/frameworks/projects/framework/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/framework/src/mx/core/Version.as
+++ b/frameworks/projects/framework/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/framework/src/mx/managers/PopUpManagerImpl.as b/frameworks/projects/framework/src/mx/managers/PopUpManagerImpl.as
index a6923a3c18..55a40d2b3f 100644
--- a/frameworks/projects/framework/src/mx/managers/PopUpManagerImpl.as
+++ b/frameworks/projects/framework/src/mx/managers/PopUpManagerImpl.as
@@ -34,6 +34,7 @@ import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
import flash.system.Capabilities;
+import flash.utils.Dictionary;
import mx.automation.IAutomationObject;
import mx.core.FlexGlobals;
@@ -176,6 +177,14 @@ public class PopUpManagerImpl extends EventDispatcher implements IPopUpManager
* An array of information about currently active popups
*/
mx_internal var popupInfo:Array = [];
+
+ /**
+ * @private
+ * The first popup to use a blur per systemManager.
+ * We need to track that in order to know when to remove the blur
+ * if stacks of modal popups are created and then taken down.
+ */
+ private var blurOwners:Dictionary = new Dictionary(true);
//--------------------------------------------------------------------------
//
@@ -956,6 +965,9 @@ public class PopUpManagerImpl extends EventDispatcher implements IPopUpManager
if (blurAmount)
{
+ if (blurOwners[sm] == null)
+ blurOwners[sm] = o.owner;
+
// Ensure we blur the appropriate top level document.
if (DisplayObject(sm).parent is Stage)
{
@@ -1031,12 +1043,10 @@ public class PopUpManagerImpl extends EventDispatcher implements IPopUpManager
fade.play();
var sm:ISystemManager = o.systemManager;
- var awm:IActiveWindowManager =
- IActiveWindowManager(sm.getImplementation("mx.managers::IActiveWindowManager"));
- // don't remove blur unless this is the last modal window
- if (awm.numModalWindows == 1)
+
+ // don't remove blur unless this is the first modal window to put up the blur
+ if (blurOwners[sm] != null && blurOwners[sm] == o.owner)
{
-
// Blur effect on the application
const blurAmount:Number = popUpStyleClient.getStyle("modalTransparencyBlur");
@@ -1268,6 +1278,8 @@ public class PopUpManagerImpl extends EventDispatcher implements IPopUpManager
awm.numModalWindows--;
}
+ if (blurOwners[sm] == o.owner)
+ blurOwners[sm] = null;
popupInfo.splice(i, 1);
break;
}
@@ -1326,7 +1338,6 @@ public class PopUpManagerImpl extends EventDispatcher implements IPopUpManager
if (obj.parent) // Mustella can already take you off stage
obj.parent.removeChild(obj);
}
-
}
/**
diff --git a/frameworks/projects/framework/src/mx/managers/SystemManager.as b/frameworks/projects/framework/src/mx/managers/SystemManager.as
index 61d41ce9c2..9eb9bea653 100644
--- a/frameworks/projects/framework/src/mx/managers/SystemManager.as
+++ b/frameworks/projects/framework/src/mx/managers/SystemManager.as
@@ -1752,7 +1752,7 @@ public class SystemManager extends MovieClip
{
// Adjust the partition indexes before the
// "added" event is dispatched.
- noTopMostIndex++;
+ noTopMostIndex = noTopMostIndex + 1;
var oldParent:DisplayObjectContainer = child.parent;
if (oldParent)
@@ -1790,7 +1790,7 @@ public class SystemManager extends MovieClip
{
// Adjust the partition indexes
// before the "removed" event is dispatched.
- noTopMostIndex--;
+ noTopMostIndex = noTopMostIndex - 1;
return rawChildren_removeChild(child);
}
@@ -1802,7 +1802,7 @@ public class SystemManager extends MovieClip
{
// Adjust the partition indexes
// before the "removed" event is dispatched.
- noTopMostIndex--;
+ noTopMostIndex = noTopMostIndex - 1;
return rawChildren_removeChildAt(applicationIndex + index);
}
@@ -2658,7 +2658,7 @@ public class SystemManager extends MovieClip
mouseCatcher.name = "mouseCatcher";
// Must use addChildAt because a creationComplete handler can create a
// dialog and insert it at 0.
- noTopMostIndex++;
+ noTopMostIndex = noTopMostIndex + 1;
super.addChildAt(mouseCatcher, 0);
resizeMouseCatcher();
if (!topLevel)
@@ -2668,7 +2668,7 @@ public class SystemManager extends MovieClip
}
// Add the application as child 1.
- noTopMostIndex++;
+ noTopMostIndex = noTopMostIndex + 1;
super.addChildAt(DisplayObject(app), 1);
CONFIG::performanceInstrumentation
diff --git a/frameworks/projects/framework/src/mx/utils/AndroidPlatformVersionOverride.as b/frameworks/projects/framework/src/mx/utils/AndroidPlatformVersionOverride.as
new file mode 100644
index 0000000000..b19e505342
--- /dev/null
+++ b/frameworks/projects/framework/src/mx/utils/AndroidPlatformVersionOverride.as
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.utils
+{
+ import flash.display.DisplayObject;
+ import flash.system.Capabilities;
+
+ import mx.core.mx_internal;
+
+ [Mixin]
+ public class AndroidPlatformVersionOverride
+ {
+ public static function init(root:DisplayObject):void
+ {
+ var c:Class = Capabilities;
+ //Set this override value on if we are
+ // a. on the AIR Simulator
+ // b. simulating Android
+ if(c.version.indexOf("AND") > -1 && c.manufacturer != "Android Linux")
+ {
+ Platform.mx_internal::androidVersionOverride = "4.1.2";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/src/mx/utils/IOSPlatformVersionOverride.as b/frameworks/projects/framework/src/mx/utils/IOSPlatformVersionOverride.as
new file mode 100644
index 0000000000..b1cf61e935
--- /dev/null
+++ b/frameworks/projects/framework/src/mx/utils/IOSPlatformVersionOverride.as
@@ -0,0 +1,42 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.utils
+{
+ import flash.display.DisplayObject;
+ import flash.system.Capabilities;
+
+ import mx.core.mx_internal;
+
+ [Mixin]
+ public class IOSPlatformVersionOverride
+ {
+ public static function init(root:DisplayObject):void
+ {
+ var c:Class = Capabilities;
+ //Set this override value on if we are
+ // a. on the AIR Simulator
+ // b. simulating iOS
+ if(c.version.indexOf("IOS") > -1 && c.manufacturer != "Adobe iOS")
+ {
+ Platform.mx_internal::iosVersionOverride = "7.0";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/src/mx/utils/LegacyMobileThemeOverride.as b/frameworks/projects/framework/src/mx/utils/LegacyMobileThemeOverride.as
new file mode 100644
index 0000000000..31e16212d4
--- /dev/null
+++ b/frameworks/projects/framework/src/mx/utils/LegacyMobileThemeOverride.as
@@ -0,0 +1,47 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.utils
+{
+
+ import flash.display.DisplayObject;
+ import flash.system.Capabilities;
+
+ import mx.core.mx_internal;
+
+ [Mixin]
+ /**
+ * Set OS version to older values to force legacy mobile theme
+ */
+ public class LegacyMobileThemeOverride
+ {
+ public static function init(root:DisplayObject):void
+ {
+ var c:Class = Capabilities;
+ if(c.version.indexOf("AND") > -1)
+ {
+ Platform.mx_internal::androidVersionOverride = "2.0.0";
+ }
+ else if(c.version.indexOf("IOS") > -1)
+ {
+ Platform.mx_internal::iosVersionOverride = "6.0.0";
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/framework/src/mx/utils/Platform.as b/frameworks/projects/framework/src/mx/utils/Platform.as
index 9f3cd26797..6a19b2ecdb 100644
--- a/frameworks/projects/framework/src/mx/utils/Platform.as
+++ b/frameworks/projects/framework/src/mx/utils/Platform.as
@@ -51,6 +51,18 @@ public class Platform
protected static var _isBrowser:Boolean;
protected static var _isAir:Boolean;
private static var _osVersion: String = null;
+
+ /**
+ * This value is set from AndroidPlatformVersionOverride
+ *
+ */
+ mx_internal static var androidVersionOverride:String;
+
+ /**
+ * This value is set from IOSPlatformVersionOverride
+ *
+ */
+ mx_internal static var iosVersionOverride:String;
/**
* Returns true if the application is running on IOS.
@@ -230,7 +242,18 @@ public class Platform
{
//We needed to compute _osVersion later than getPlatforms, because it relies on resources that ready later
if (_osVersion == null){
- _osVersion = computeOSVersionString();
+ if(mx_internal::androidVersionOverride == null && mx_internal::iosVersionOverride == null)
+ {
+ _osVersion = computeOSVersionString();
+ }
+ else if(mx_internal::androidVersionOverride != null)
+ {
+ _osVersion = mx_internal::androidVersionOverride;
+ }
+ else if(mx_internal::iosVersionOverride != null)
+ {
+ _osVersion = mx_internal::iosVersionOverride;
+ }
}
return _osVersion;
}
@@ -259,7 +282,7 @@ public class Platform
_isDesktop = !_isMobile;
_isAir = playerType == "Desktop";
- _isBrowser = (playerType == "Plugin" || playerType == "ActiveX");
+ _isBrowser = (playerType == "PlugIn" || playerType == "ActiveX");
_initialized = true;
}
diff --git a/frameworks/projects/framework/src/mx/validators/DateValidator.as b/frameworks/projects/framework/src/mx/validators/DateValidator.as
index 89138cc14a..f833ee293a 100644
--- a/frameworks/projects/framework/src/mx/validators/DateValidator.as
+++ b/frameworks/projects/framework/src/mx/validators/DateValidator.as
@@ -211,7 +211,7 @@ public class DateValidator extends Validator
else
{
noSeperators = false;
- formatParts[part] = formatChar;
+ formatParts[part] += formatChar;
}
lastFormatChar = formatChar;
@@ -388,6 +388,19 @@ public class DateValidator extends Validator
dateObj.year = dateParts[part];
yearPart = formatParts[part];
}
+ else if (!noSeperators)
+ {
+ // separator part, we have valid separator characters just validate against
+ // repeating separator values, validate now as we could have multiple separators
+ if (dateParts[part].length != formatParts[part].length)
+ {
+ results.push(new ValidationResult(
+ true, baseField, "wrongLength",
+ validator.wrongLengthError
+ + (DateValidator._includeFormatInError?" " + inputFormat:"")));
+ return results;
+ }
+ }
}
// DD or D format
diff --git a/frameworks/projects/framework/src/mx/validators/EmailValidator.as b/frameworks/projects/framework/src/mx/validators/EmailValidator.as
index f928371b08..9776db360c 100644
--- a/frameworks/projects/framework/src/mx/validators/EmailValidator.as
+++ b/frameworks/projects/framework/src/mx/validators/EmailValidator.as
@@ -217,16 +217,6 @@ public class EmailValidator extends Validator
if (nextPeriodPos == -1)
{
lastDomain = domain.substring(periodPos + 1);
- if (lastDomain.length != 3 &&
- lastDomain.length != 2 &&
- lastDomain.length != 4 &&
- lastDomain.length != 6)
- {
- results.push(new ValidationResult(
- true, baseField, "invalidDomain",
- validator.invalidDomainError));
- return results;
- }
break;
}
else if (nextPeriodPos == periodPos + 1)
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/SpinnerList.as b/frameworks/projects/mobilecomponents/src/spark/components/SpinnerList.as
index f674806d01..76889dea0b 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/SpinnerList.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/SpinnerList.as
@@ -41,7 +41,6 @@ import spark.layouts.supportClasses.LayoutBase;
use namespace mx_internal;
-[Exclude(name="accentColor", kind="style")]
[Exclude(name="chromeColor", kind="style")]
[Exclude(name="layout", kind="property")]
[Exclude(name="requireSelection", kind="property")]
@@ -396,6 +395,18 @@ public class SpinnerList extends ListBase
}
}
}
+
+ override protected function itemSelected(index:int, selected:Boolean):void
+ {
+ super.itemSelected(index, selected);
+
+ var renderer:Object = dataGroup ? dataGroup.getElementAt(index) : null;
+
+ if (renderer is IItemRenderer)
+ {
+ IItemRenderer(renderer).selected = selected;
+ }
+ }
/**
* @private
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/SpinnerListItemRenderer.as b/frameworks/projects/mobilecomponents/src/spark/components/SpinnerListItemRenderer.as
index 1a5f26a841..80711a8672 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/SpinnerListItemRenderer.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/SpinnerListItemRenderer.as
@@ -21,6 +21,8 @@ package spark.components
import mx.core.DPIClassification;
import mx.core.mx_internal;
+
+import spark.components.supportClasses.ListBase;
use namespace mx_internal;
@@ -83,12 +85,48 @@ public class SpinnerListItemRenderer extends LabelItemRenderer
}
}
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ private var _colorName:String = "color";
+
//--------------------------------------------------------------------------
//
// Overridden Methods
//
//--------------------------------------------------------------------------
+ override public function set selected(value:Boolean):void
+ {
+ var oldValue:Boolean = selected;
+ super.selected = value;
+ if(oldValue != selected)
+ {
+ if(selected)
+ {
+ if (getStyle("useAccentColor"))
+ _colorName = "accentColor"; // highlighted item
+ else
+ _colorName = "color";
+ }else{
+ _colorName = "color"; // reset to use standard color
+ }
+ setTextProperties();
+ }
+ }
+
+ private function setTextProperties():void
+ {
+ if (labelDisplay)
+ {
+ labelDisplay.colorName = _colorName;
+ labelDisplay.alpha = enabled ? 1 : .5;
+ }
+ }
+
/**
* @private
*
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/calendarClasses/DateSpinnerItemRenderer.as b/frameworks/projects/mobilecomponents/src/spark/components/calendarClasses/DateSpinnerItemRenderer.as
index 19d2481a56..eefc4cb13b 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/calendarClasses/DateSpinnerItemRenderer.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/calendarClasses/DateSpinnerItemRenderer.as
@@ -150,5 +150,27 @@ public class DateSpinnerItemRenderer extends SpinnerListItemRenderer
labelDisplay.alpha = enabled ? 1 : .5;
}
}
+
+ override public function set selected(value:Boolean):void
+ {
+ var oldValue:Boolean = selected;
+ super.selected = value;
+ if(oldValue != selected)
+ {
+ try
+ {
+ if (data["_emphasized_"] != undefined)
+ _colorName = "accentColor"; // highlighted item
+ else
+ _colorName = "color"; // reset to use standard color
+ }
+ catch (e:Error)
+ {
+ // Do nothing
+ }
+ setTextProperties();
+ }
+ }
+
}
}
\ No newline at end of file
diff --git a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
index 200265ecff..de6cff1385 100644
--- a/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
+++ b/frameworks/projects/mobilecomponents/src/spark/components/supportClasses/ScrollableStageText.as
@@ -1580,12 +1580,9 @@ public class ScrollableStageText extends UIComponent implements IStyleableEdita
protected function disposeProxy():void
{
- var bd: BitmapData = Bitmap(proxy).bitmapData;
+ var bd:BitmapData = Bitmap(proxy).bitmapData;
if (bd)
bd.dispose();
- else {
- trace("[WARN] SST found empty bitmap data in:", debugId) ;
- }
}
diff --git a/frameworks/projects/mobiletheme/.flexLibProperties b/frameworks/projects/mobiletheme/.flexLibProperties
index 1627cbbb8c..bc40160506 100644
--- a/frameworks/projects/mobiletheme/.flexLibProperties
+++ b/frameworks/projects/mobiletheme/.flexLibProperties
@@ -1,26 +1,29 @@
-
+
-
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/compile-config.xml b/frameworks/projects/mobiletheme/compile-config.xml
index ec37add414..b788911a02 100644
--- a/frameworks/projects/mobiletheme/compile-config.xml
+++ b/frameworks/projects/mobiletheme/compile-config.xml
@@ -55,6 +55,14 @@
defaults.cssdefaults.css
+
+ spark/skins/android4/assets/fonts/Roboto-Regular.ttf
+ src/spark/skins/android4/assets/fonts/Roboto-Regular.ttf
+
+
+ spark/skins/android4/assets/fonts/Roboto-Bold.ttf
+ src/spark/skins/android4/assets/fonts/Roboto-Bold.ttf
+ bundles.properties
diff --git a/frameworks/projects/mobiletheme/defaults.css b/frameworks/projects/mobiletheme/defaults.css
index 66f7fb79be..c39de85099 100644
--- a/frameworks/projects/mobiletheme/defaults.css
+++ b/frameworks/projects/mobiletheme/defaults.css
@@ -1,24 +1,25 @@
/*
- *
- * 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.
- *
- */
+*
+* 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.
+*
+*/
@namespace "library://ns.adobe.com/flex/spark";
+
/*
Default Mobile Flex skins and styles. Defaults sizes are based on
application-dpi=240.
@@ -26,153 +27,159 @@ application-dpi=240.
ActionBar
{
- chromeColor: #484848;
- defaultButtonAppearance: normal;
- skinClass: ClassReference("spark.skins.mobile.ActionBarSkin");
- textShadowAlpha: .65;
- textShadowColor: #000000;
- paddingBottom: 1;
- paddingLeft: 0;
- paddingRight: 0;
- paddingTop: 1;
+ chromeColor: #484848;
+ defaultButtonAppearance: normal;
+ skinClass: ClassReference("spark.skins.mobile.ActionBarSkin");
+ textShadowAlpha: .65;
+ textShadowColor: #000000;
+ paddingBottom: 1;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 1;
}
ActionBar.beveled
{
- paddingLeft: 7;
- paddingRight: 7;
- titleAlign: center;
+ paddingLeft: 7;
+ paddingRight: 7;
+ titleAlign: center;
}
ActionBar #titleDisplay
{
- color: #FFFFFF;
- fontSize: 28;
- fontWeight: bold;
+ color: #FFFFFF;
+ fontSize: 28;
+ fontWeight: bold;
}
ActionBar ButtonBase
{
- color: #FFFFFF;
+ color: #FFFFFF;
}
ActionBar Group#navigationGroup Button
{
- skinClass: ClassReference("spark.skins.mobile.TransparentNavigationButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.TransparentNavigationButtonSkin");
}
ActionBar Group#navigationGroup Button.emphasized
{
- skinClass: ClassReference("spark.skins.mobile.DefaultTransparentNavigationButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.DefaultTransparentNavigationButtonSkin");
}
ActionBar.beveled Group#navigationGroup Button
{
- fontSize: 18;
- skinClass: ClassReference("spark.skins.mobile.BeveledBackButtonSkin");
+ fontSize: 18;
+ skinClass: ClassReference("spark.skins.mobile.BeveledBackButtonSkin");
}
ActionBar.beveled Group#navigationGroup Button.emphasized
{
- skinClass: ClassReference("spark.skins.mobile.DefaultBeveledBackButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.DefaultBeveledBackButtonSkin");
}
ActionBar Group#actionGroup Button
{
- skinClass: ClassReference("spark.skins.mobile.TransparentActionButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.TransparentActionButtonSkin");
}
ActionBar Group#actionGroup Button.emphasized
{
- skinClass: ClassReference("spark.skins.mobile.DefaultTransparentActionButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.DefaultTransparentActionButtonSkin");
}
ActionBar.beveled Group#actionGroup Button
{
- fontSize: 18;
- skinClass: ClassReference("spark.skins.mobile.BeveledActionButtonSkin");
+ fontSize: 18;
+ skinClass: ClassReference("spark.skins.mobile.BeveledActionButtonSkin");
}
ActionBar.beveled Group#actionGroup Button.emphasized
{
- skinClass: ClassReference("spark.skins.mobile.DefaultBeveledActionButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.DefaultBeveledActionButtonSkin");
}
BusyIndicator
{
- rotationInterval: 50;
+ skinClass: ClassReference("spark.skins.mobile.BusyIndicatorSkin");
+ rotationInterval: 50;
}
Button
{
- fontWeight: "bold";
- skinClass: ClassReference("spark.skins.mobile.ButtonSkin");
+ fontWeight: "bold";
+ skinClass: ClassReference("spark.skins.mobile.ButtonSkin");
}
Button.emphasized
{
- skinClass: ClassReference("spark.skins.mobile.DefaultButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.DefaultButtonSkin");
}
ButtonBar
{
- fontWeight: "bold";
- skinClass: ClassReference("spark.skins.mobile.ButtonBarSkin");
+ fontWeight: "bold";
+ skinClass: ClassReference("spark.skins.mobile.ButtonBarSkin");
}
ButtonBase
{
- iconPlacement: "left";
+ iconPlacement: "left";
}
Callout
{
- backgroundColor: #484848;
- contentBackgroundAppearance: inset;
- contentBackgroundColor: #FFFFFF;
- gap: 12;
- skinClass: ClassReference("spark.skins.mobile.CalloutSkin");
- borderThickness: NaN;
- borderColor: 0;
+ backgroundColor: #484848;
+ contentBackgroundAppearance: inset;
+ contentBackgroundColor: #FFFFFF;
+ gap: 12;
+ skinClass: ClassReference("spark.skins.mobile.CalloutSkin");
+ borderThickness: NaN;
+ borderColor: 0;
+}
+
+CalloutButton
+{
+ rollOverOpenDelay: NaN;
}
Callout ViewNavigator
{
- skinClass: ClassReference("spark.skins.mobile.CalloutViewNavigatorSkin");
+ skinClass: ClassReference("spark.skins.mobile.CalloutViewNavigatorSkin");
}
Callout ViewNavigator ActionBar
{
- skinClass: ClassReference("spark.skins.mobile.CalloutActionBarSkin");
- defaultButtonAppearance: beveled;
- paddingLeft: 0;
- paddingRight: 0;
+ skinClass: ClassReference("spark.skins.mobile.CalloutActionBarSkin");
+ defaultButtonAppearance: beveled;
+ paddingLeft: 0;
+ paddingRight: 0;
}
Callout ViewNavigator ActionBar.beveled
{
- paddingLeft: 0;
- paddingRight: 0;
+ paddingLeft: 0;
+ paddingRight: 0;
}
Callout ViewNavigator ActionBar.beveled Group#navigationGroup Button
{
- skinClass: ClassReference("spark.skins.mobile.BeveledActionButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.BeveledActionButtonSkin");
}
Callout ViewNavigator ActionBar.beveled Group#navigationGroup Button.emphasized
{
- skinClass: ClassReference("spark.skins.mobile.DefaultBeveledActionButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.DefaultBeveledActionButtonSkin");
}
Callout#viewNavigatorPopUp
{
- contentBackgroundAppearance: none;
+ contentBackgroundAppearance: none;
}
CheckBox
{
- skinClass: ClassReference("spark.skins.mobile.CheckBoxSkin");
+ skinClass: ClassReference("spark.skins.mobile.CheckBoxSkin");
}
DateSpinner
@@ -182,85 +189,86 @@ DateSpinner
HScrollBar
{
- skinClass: ClassReference("spark.skins.mobile.HScrollBarSkin");
+ skinClass: ClassReference("spark.skins.mobile.HScrollBarSkin");
}
HSlider
{
- skinClass: ClassReference("spark.skins.mobile.HSliderSkin");
+ skinClass: ClassReference("spark.skins.mobile.HSliderSkin");
}
IconItemRenderer
{
- paddingBottom: 12;
- paddingTop: 12;
- horizontalGap: 10;
- verticalGap: 9;
- iconDelay: 500;
- messageStyleName: "iconItemRendererMessageStyle";
+ paddingBottom: 12;
+ paddingTop: 12;
+ horizontalGap: 10;
+ verticalGap: 9;
+ iconDelay: 500;
+ messageStyleName: "iconItemRendererMessageStyle";
}
.iconItemRendererMessageStyle
{
- fontSize: 20;
- color: #333333;
+ fontSize: 20;
+ color: #333333;
}
Image
{
- skinClass: ClassReference("spark.skins.mobile.ImageSkin");
- enableLoadingState: false;
- showErrorSkin : false;
- smoothingQuality: "default";
+ skinClass: ClassReference("spark.skins.mobile.ImageSkin");
+ enableLoadingState: false;
+ showErrorSkin : false;
+ smoothingQuality: "default";
}
LabelItemRenderer
{
- paddingBottom: 24;
- paddingLeft: 15;
- paddingRight: 15;
- paddingTop: 24;
- verticalAlign: "middle";
+ paddingBottom: 24;
+ paddingLeft: 15;
+ paddingRight: 15;
+ paddingTop: 24;
+ verticalAlign: "middle";
}
List
{
- skinClass: ClassReference("spark.skins.mobile.ListSkin");
- borderColor: #000000;
- borderAlpha: 1;
- verticalScrollPolicy: on;
- borderVisible: false;
+ skinClass: ClassReference("spark.skins.mobile.ListSkin");
+ borderColor: #000000;
+ borderAlpha: 1;
+ verticalScrollPolicy: on;
+ borderVisible: false;
}
RadioButton
{
- skinClass: ClassReference("spark.skins.mobile.RadioButtonSkin");
+ skinClass: ClassReference("spark.skins.mobile.RadioButtonSkin");
}
Scroller
{
- touchDelay: 100;
+ touchDelay: 100;
}
SkinnableContainer
{
- backgroundColor: #FFFFFF;
- skinClass: ClassReference("spark.skins.mobile.SkinnableContainerSkin");
+ backgroundColor: #FFFFFF;
+ skinClass: ClassReference("spark.skins.mobile.SkinnableContainerSkin");
}
SkinnableTextBase:normalWithPrompt
{
- fontStyle: normal;
+ fontStyle: normal;
}
SkinnableTextBase:disabledWithPrompt
{
- fontStyle: normal;
+ fontStyle: normal;
}
SpinnerList
{
skinClass: ClassReference("spark.skins.mobile.SpinnerListSkin");
+ useAccentColor: false;
}
SpinnerListContainer
@@ -279,146 +287,146 @@ SpinnerListItemRenderer
SplitViewNavigator
{
skinClass: ClassReference("spark.skins.mobile.SplitViewNavigatorSkin");
- backgroundColor: #000000;
+ backgroundColor: #000000;
}
TabbedViewNavigatorApplication
{
- backgroundColor: #FFFFFF;
- skinClass: ClassReference("spark.skins.mobile.TabbedViewNavigatorApplicationSkin");
+ backgroundColor: #FFFFFF;
+ skinClass: ClassReference("spark.skins.mobile.TabbedViewNavigatorApplicationSkin");
}
TabbedViewNavigator
{
- skinClass: ClassReference("spark.skins.mobile.TabbedViewNavigatorSkin");
+ skinClass: ClassReference("spark.skins.mobile.TabbedViewNavigatorSkin");
}
TabbedViewNavigator #tabBar
{
- chromeColor: #484848;
- color: #FFFFFF;
- fontSize: 20;
- fontWeight: normal;
- iconPlacement: top;
- interactionMode: mouse;
- skinClass: ClassReference("spark.skins.mobile.TabbedViewNavigatorTabBarSkin");
- textShadowAlpha: .65;
- textShadowColor: #000000;
+ chromeColor: #484848;
+ color: #FFFFFF;
+ fontSize: 20;
+ fontWeight: normal;
+ iconPlacement: top;
+ interactionMode: mouse;
+ skinClass: ClassReference("spark.skins.mobile.TabbedViewNavigatorTabBarSkin");
+ textShadowAlpha: .65;
+ textShadowColor: #000000;
}
TextArea
{
- paddingBottom: 9;
- paddingLeft: 9;
- paddingRight: 9;
- paddingTop: 9;
- showPromptWhenFocused: true;
- skinClass: ClassReference("spark.skins.mobile.ScrollingStageTextAreaSkin");
+ paddingBottom: 9;
+ paddingLeft: 9;
+ paddingRight: 9;
+ paddingTop: 9;
+ showPromptWhenFocused: true;
+ skinClass: ClassReference("spark.skins.mobile.ScrollingStageTextAreaSkin");
}
TextArea VScrollBar
{
- skinClass: ClassReference("spark.skins.mobile.TextAreaVScrollBarSkin");
+ skinClass: ClassReference("spark.skins.mobile.TextAreaVScrollBarSkin");
}
TextArea HScrollBar
{
- skinClass: ClassReference("spark.skins.mobile.TextAreaHScrollBarSkin");
+ skinClass: ClassReference("spark.skins.mobile.TextAreaHScrollBarSkin");
}
TextInput
{
- paddingBottom: 9;
- paddingLeft: 9;
- paddingRight: 9;
- paddingTop: 9;
- showPromptWhenFocused: true;
- skinClass: ClassReference("spark.skins.mobile.ScrollingStageTextInputSkin");
+ paddingBottom: 9;
+ paddingLeft: 9;
+ paddingRight: 9;
+ paddingTop: 9;
+ showPromptWhenFocused: true;
+ skinClass: ClassReference("spark.skins.mobile.ScrollingStageTextInputSkin");
}
ToggleSwitch
{
- accentColor: #3F7FBA;
- color: #FFFFFF;
- fontSize: 27;
- skinClass: ClassReference("spark.skins.mobile.ToggleSwitchSkin");
- slideDuration: 125;
- textShadowAlpha: .65;
- textShadowColor: #000000;
+ accentColor: #3F7FBA;
+ color: #FFFFFF;
+ fontSize: 27;
+ skinClass: ClassReference("spark.skins.mobile.ToggleSwitchSkin");
+ slideDuration: 125;
+ textShadowAlpha: .65;
+ textShadowColor: #000000;
}
View
{
- backgroundColor: #FFFFFF;
- skinClass: ClassReference("spark.skins.mobile.SkinnableContainerSkin");
+ backgroundColor: #FFFFFF;
+ skinClass: ClassReference("spark.skins.mobile.SkinnableContainerSkin");
}
ViewMenu
{
- skinClass: ClassReference("spark.skins.mobile.ViewMenuSkin");
+ skinClass: ClassReference("spark.skins.mobile.ViewMenuSkin");
}
ViewMenuItem
{
- iconPlacement : "top";
- chromeColor : #FFFFFF;
- paddingBottom: 8;
- paddingLeft: 8;
- paddingRight: 8;
- paddingTop: 8;
- skinClass : ClassReference("spark.skins.mobile.ViewMenuItemSkin");
+ iconPlacement : "top";
+ chromeColor : #FFFFFF;
+ paddingBottom: 8;
+ paddingLeft: 8;
+ paddingRight: 8;
+ paddingTop: 8;
+ skinClass : ClassReference("spark.skins.mobile.ViewMenuItemSkin");
}
ViewNavigator
{
- skinClass: ClassReference("spark.skins.mobile.ViewNavigatorSkin");
+ skinClass: ClassReference("spark.skins.mobile.ViewNavigatorSkin");
}
ViewNavigatorApplication
{
- backgroundColor: #FFFFFF;
- skinClass: ClassReference("spark.skins.mobile.ViewNavigatorApplicationSkin");
+ backgroundColor: #FFFFFF;
+ skinClass: ClassReference("spark.skins.mobile.ViewNavigatorApplicationSkin");
}
VScrollBar
{
- skinClass: ClassReference("spark.skins.mobile.VScrollBarSkin");
+ skinClass: ClassReference("spark.skins.mobile.VScrollBarSkin");
}
global
{
- /* framework styles */
- modalTransparency: 0;
- modalTransparencyBlur: 0;
-
- /* Looks */
- backgroundAlpha : 1;
- backgroundImageFillMode : "scale";
- borderVisible : true;
- borderWeight : 1;
- contentBackgroundColor: #F0F0F0;
- downColor: #E0E0E0; /* set in here and not in framework's default.css because it only is really applicable for touch interactions*/
- selectionColor: #E0E0E0;
- alternatingItemColors: #FFFFFF;
- focusThickness: 3;
- symbolColor: #000000;
- fontLookup: "embeddedCFF";
- fontFamily: "_sans";
- fontSize: 24;
- color: #000000;
- textShadowColor: #FFFFFF;
- textShadowAlpha: .55;
-
- /* Behaviors */
- autoThumbVisibility: true;
- fixedThumbSize: false;
- fullScreenHideControlsDelay: 3000;
- interactionMode: "touch";
- liveDragging: true;
- rollOverOpenDelay: 200;
- slideDuration: 300;
- smoothScrolling: true;
- touchDelay: 0; /* default to 0 here, but Scroller sets it to 100 */
+ /* framework styles */
+ modalTransparency: 0;
+ modalTransparencyBlur: 0;
+
+ /* Looks */
+ backgroundAlpha : 1;
+ backgroundImageFillMode : "scale";
+ borderVisible : true;
+ borderWeight : 1;
+ contentBackgroundColor: #F0F0F0;
+ downColor: #E0E0E0; /* set in here and not in framework's default.css because it only is really applicable for touch interactions*/
+ selectionColor: #E0E0E0;
+ alternatingItemColors: #FFFFFF;
+ focusThickness: 3;
+ symbolColor: #000000;
+ fontLookup: "embeddedCFF";
+ fontFamily: "_sans";
+ fontSize: 24;
+ color: #000000;
+ textShadowColor: #FFFFFF;
+ textShadowAlpha: .55;
+
+ /* Behaviors */
+ autoThumbVisibility: true;
+ fixedThumbSize: false;
+ fullScreenHideControlsDelay: 3000;
+ interactionMode: "touch";
+ liveDragging: true;
+ rollOverOpenDelay: 200;
+ slideDuration: 300;
+ smoothScrolling: true;
+ touchDelay: 0; /* default to 0 here, but Scroller sets it to 100 */
}
@media (application-dpi: 120)
@@ -522,61 +530,61 @@ global
@media (application-dpi: 160)
{
- ActionBar
- {
- paddingBottom: 1;
- paddingLeft: 0;
- paddingRight: 0;
- paddingTop: 1;
- }
-
- ActionBar.beveled
- {
- paddingLeft: 5;
- paddingRight: 5;
- }
-
- ActionBar #titleDisplay
- {
- fontSize: 18;
- }
-
- ActionBar.beveled Group#navigationGroup Button
- {
- fontSize: 12;
- }
-
- ActionBar.beveled Group#actionGroup Button
- {
- fontSize: 12;
- }
-
- Callout
- {
- gap: 8;
- }
-
- IconItemRenderer
- {
- paddingBottom: 8;
- paddingTop: 8;
- horizontalGap: 8;
- verticalGap: 6;
- }
-
- .iconItemRendererMessageStyle
- {
- fontSize: 14;
- }
-
- LabelItemRenderer
- {
- paddingBottom: 16;
- paddingLeft: 10;
- paddingRight: 10;
- paddingTop: 16;
- }
-
+ ActionBar
+ {
+ paddingBottom: 1;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 1;
+ }
+
+ ActionBar.beveled
+ {
+ paddingLeft: 5;
+ paddingRight: 5;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 18;
+ }
+
+ ActionBar.beveled Group#navigationGroup Button
+ {
+ fontSize: 12;
+ }
+
+ ActionBar.beveled Group#actionGroup Button
+ {
+ fontSize: 12;
+ }
+
+ Callout
+ {
+ gap: 8;
+ }
+
+ IconItemRenderer
+ {
+ paddingBottom: 8;
+ paddingTop: 8;
+ horizontalGap: 8;
+ verticalGap: 6;
+ }
+
+ .iconItemRendererMessageStyle
+ {
+ fontSize: 14;
+ }
+
+ LabelItemRenderer
+ {
+ paddingBottom: 16;
+ paddingLeft: 10;
+ paddingRight: 10;
+ paddingTop: 16;
+ }
+
SpinnerListItemRenderer
{
paddingTop : 12;
@@ -585,96 +593,96 @@ global
paddingRight : 8;
}
- TextArea
- {
- paddingBottom: 6;
- paddingLeft: 6;
- paddingRight: 6;
- paddingTop: 6;
- }
-
- TextInput
- {
- paddingBottom: 6;
- paddingLeft: 6;
- paddingRight: 6;
- paddingTop: 6;
- }
-
- TabbedViewNavigator #tabBar
- {
- fontSize: 14;
- }
-
- ToggleSwitch
- {
- fontSize: 18;
- }
-
- global
- {
- fontSize: 16;
- focusThickness: 2;
- }
+ TextArea
+ {
+ paddingBottom: 6;
+ paddingLeft: 6;
+ paddingRight: 6;
+ paddingTop: 6;
+ }
+
+ TextInput
+ {
+ paddingBottom: 6;
+ paddingLeft: 6;
+ paddingRight: 6;
+ paddingTop: 6;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 14;
+ }
+
+ ToggleSwitch
+ {
+ fontSize: 18;
+ }
+
+ global
+ {
+ fontSize: 16;
+ focusThickness: 2;
+ }
}
@media (application-dpi: 320)
{
- ActionBar
- {
- paddingBottom: 2;
- paddingLeft: 0;
- paddingRight: 0;
- paddingTop: 2;
- }
-
- ActionBar.beveled
- {
- paddingLeft: 10;
- paddingRight: 10;
- }
-
- ActionBar #titleDisplay
- {
- fontSize: 36;
- }
-
- ActionBar.beveled Group#navigationGroup Button
- {
- fontSize: 24;
- }
-
- ActionBar.beveled Group#actionGroup Button
- {
- fontSize: 24;
- }
-
- Callout
- {
- gap: 16;
- }
-
- IconItemRenderer
- {
- paddingBottom: 16;
- paddingTop: 16;
- horizontalGap: 16;
- verticalGap: 12;
- }
-
- .iconItemRendererMessageStyle
- {
- fontSize: 26;
- }
-
- LabelItemRenderer
- {
- paddingBottom: 32;
- paddingLeft: 20;
- paddingRight: 20;
- paddingTop: 32;
- }
-
+ ActionBar
+ {
+ paddingBottom: 2;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 2;
+ }
+
+ ActionBar.beveled
+ {
+ paddingLeft: 10;
+ paddingRight: 10;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 36;
+ }
+
+ ActionBar.beveled Group#navigationGroup Button
+ {
+ fontSize: 24;
+ }
+
+ ActionBar.beveled Group#actionGroup Button
+ {
+ fontSize: 24;
+ }
+
+ Callout
+ {
+ gap: 16;
+ }
+
+ IconItemRenderer
+ {
+ paddingBottom: 16;
+ paddingTop: 16;
+ horizontalGap: 16;
+ verticalGap: 12;
+ }
+
+ .iconItemRendererMessageStyle
+ {
+ fontSize: 26;
+ }
+
+ LabelItemRenderer
+ {
+ paddingBottom: 32;
+ paddingLeft: 20;
+ paddingRight: 20;
+ paddingTop: 32;
+ }
+
SpinnerListItemRenderer
{
paddingTop : 24;
@@ -683,36 +691,36 @@ global
paddingRight : 24;
}
- TextArea
- {
- paddingBottom: 12;
- paddingLeft: 12;
- paddingRight: 12;
- paddingTop: 12;
- }
-
- TextInput
- {
- paddingBottom: 12;
- paddingLeft: 12;
- paddingRight: 12;
- paddingTop: 12;
- }
-
- TabbedViewNavigator #tabBar
- {
- fontSize: 28;
- }
-
- ToggleSwitch
- {
- fontSize: 36;
- }
-
- global
- {
- fontSize: 32;
- }
+ TextArea
+ {
+ paddingBottom: 12;
+ paddingLeft: 12;
+ paddingRight: 12;
+ paddingTop: 12;
+ }
+
+ TextInput
+ {
+ paddingBottom: 12;
+ paddingLeft: 12;
+ paddingRight: 12;
+ paddingTop: 12;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 28;
+ }
+
+ ToggleSwitch
+ {
+ fontSize: 36;
+ }
+
+ global
+ {
+ fontSize: 32;
+ }
}
@media (application-dpi: 480)
@@ -914,61 +922,910 @@ global
@media (application-dpi: 160) AND (os-platform:"IOS")
{
- TextArea
- {
- leading: 1.5;
- paddingRight: 1.5;
- }
+ TextArea
+ {
+ leading: 1.5;
+ paddingRight: 1.5;
+ }
}
@media (application-dpi: 320) AND (os-platform:"IOS")
{
- TextArea
- {
- leading: 4.5;
- paddingRight: 3;
- }
+ TextArea
+ {
+ leading: 4.5;
+ paddingRight: 3;
+ }
}
-/* ios 7 status bar
- requires new os-version selector (cf FLEX-FLEX-33949)
- */
-@media (application-dpi: 120) AND (os-platform:"IOS") AND (min-os-version: 7)
-{
- Application
- {
- osStatusBarHeight: 15;
- }
-}
-@media (application-dpi: 160) AND (os-platform:"IOS") AND (min-os-version: 7)
-{
- Application {
- osStatusBarHeight: 20;
- }
-}
+/* ios 7+ new theme */
-@media (application-dpi: 240) AND (os-platform:"IOS") AND (min-os-version: 7)
+@media (os-platform:"IOS") AND (min-os-version: 7)
{
- Application
- {
- osStatusBarHeight: 30;
- }
-}
-@media (application-dpi: 320) AND (os-platform:"IOS") AND (min-os-version: 7)
-{
- Application
- {
- osStatusBarHeight: 40;
- }
-}
+ global
+ {
+ fontFamily: RobotoRegular;
+ fontWeight: "normal";
+ fontSize: 24;
+ color: #000000;
+ highlightTextColor: #FFFFFF;
+ textShadowColor: #FFFFFF;
+ textShadowAlpha: 0;
+ }
+
+ ActionBar
+ {
+ defaultButtonAppearance: normal;
+ skinClass: ClassReference("spark.skins.ios7.ActionBarSkin");
+ textShadowAlpha: 0;
+ textShadowColor: #000000;
+ paddingBottom: 1;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 1;
+ }
+
+ ActionBar #titleDisplay
+ {
+ color: #007AFF;
+ fontSize: 24;
+ fontFamily: RobotoRegular;
+ fontWeight: normal;
+ }
+
+ ActionBar ButtonBase
+ {
+ color: #007AFF;
+ fontFamily: RobotoRegular;
+ fontWeight: normal;
+ }
+
+ ActionBar Group#actionGroup Button
+ {
+ skinClass: ClassReference("spark.skins.ios7.ButtonSkin");
+ }
+
+ BusyIndicator
+ {
+ skinClass: ClassReference("spark.skins.ios7.BusyIndicatorSkin");
+ rotationInterval: 30; /* Must be multiples of 30 */
+ }
+
+ Button
+ {
+ skinClass: ClassReference("spark.skins.ios7.ButtonSkin");
+ fontFamily: RobotoRegular;
+ fontWeight: normal;
+ }
+
+ Button.emphasized
+ {
+ skinClass: ClassReference("spark.skins.mobile.DefaultButtonSkin");
+ }
+
+ ButtonBar
+ {
+ skinClass: ClassReference("spark.skins.ios7.ButtonBarSkin");
+ color: #007AFF;
+ fontFamily: RobotoRegular;
+ fontWeight: normal;
+ }
+
+ Callout
+ {
+ skinClass: ClassReference("spark.skins.ios7.CalloutSkin");
+ backgroundColor: #F6F6F6;
+ contentBackgroundColor: #F6F6F6;
+ gap: 12;
+ borderThickness: 0;
+ frameThickness: 0;
+ contentBackgroundAppearance: flat;
+ }
+
+ Callout ViewNavigator
+ {
+ skinClass: ClassReference("spark.skins.ios7.CalloutViewNavigatorSkin");
+ contentBackgroundColor: #FFFFFF;
+ }
+
+ Callout ViewNavigator ActionBar
+ {
+ skinClass: ClassReference("spark.skins.ios7.CalloutActionBarSkin");
+ defaultButtonAppearance: normal;
+ textShadowAlpha: 0;
+ textShadowColor: #000000;
+ paddingBottom: 0;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 0;
+ contentBackgroundAppearance: flat;
+ }
+
+ Callout ViewNavigator ActionBar.beveled
+ {
+ paddingLeft: 0;
+ paddingRight: 0;
+ }
+
+ Callout ViewNavigator ActionBar.beveled Group#navigationGroup Button
+ {
+ skinClass: ClassReference("spark.skins.ios7.ButtonSkin");
+ }
+
+ Callout ViewNavigator ActionBar.beveled Group#navigationGroup Button.emphasized
+ {
+ skinClass: ClassReference("spark.skins.ios7.ButtonSkin");
+ }
+
+ Callout ViewNavigator ActionBar Group#navigationGroup Button
+ {
+ skinClass: ClassReference("spark.skins.ios7.ButtonSkin");
+ }
+
+ Callout ViewNavigator ActionBar Group#navigationGroup Button.emphasized
+ {
+ skinClass: ClassReference("spark.skins.ios7.ButtonSkin");
+ }
+
+ Callout#viewNavigatorPopUp
+ {
+ contentBackgroundAppearance: flat;
+ }
-@media (application-dpi: 480) AND (os-platform:"IOS") AND (min-os-version: 7)
-{
- Application
- {
- osStatusBarHeight: 60;
- }
-}
\ No newline at end of file
+ CheckBox
+ {
+ chromeColor: #FFFFFF;
+ skinClass: ClassReference("spark.skins.ios7.CheckBoxSkin");
+ }
+
+ HScrollBar
+ {
+ skinClass: ClassReference("spark.skins.ios7.HScrollBarSkin");
+ color: #E6E6E6;
+ }
+
+ HSlider
+ {
+ skinClass: ClassReference("spark.skins.ios7.HSliderSkin");
+ fontFamily: RobotoBold;
+ }
+
+ RadioButton
+ {
+ skinClass: ClassReference("spark.skins.ios7.RadioButtonSkin");
+ chromeColor: #FFFFFF;
+ }
+
+ SpinnerList
+ {
+ skinClass: ClassReference("spark.skins.ios7.SpinnerListSkin");
+ color: #999999;
+ accentColor: #333333;
+ useAccentColor: true;
+ }
+
+ SpinnerListContainer
+ {
+ skinClass: ClassReference("spark.skins.ios7.SpinnerListContainerSkin");
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 9;
+ paddingBottom : 9;
+ paddingLeft : 6;
+ paddingRight : 6;
+ }
+
+ SplitViewNavigator
+ {
+ backgroundColor: #FFFFFF;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontFamily: RobotoRegular;
+ chromeColor: #FFFFFF;
+ color: #007AFF;
+ highlightTextColor: #FFFFFF;
+ fontSize: 20;
+ fontWeight: normal;
+ iconPlacement: top;
+ interactionMode: mouse;
+ skinClass: ClassReference("spark.skins.ios7.TabbedViewNavigatorTabBarSkin");
+ textShadowAlpha: 0;
+ textShadowColor: #000000;
+ }
+
+ TextInput
+ {
+ skinClass: ClassReference("spark.skins.ios7.StageTextInputSkin");
+ contentBackgroundAlpha: 0;
+ focusColor: #cccccc;
+ borderColor: #cccccc;
+ contentBackgroundColor: #DEDEDD;
+ contentBackgroundBorder: "roundedrect";
+ fontFamily: RobotoRegular;
+ fontWeight: normal;
+ selectionHighlighting: "never";
+ focusEnabled:"false";
+ focusThickness: 0;
+ focusAlpha: 0;
+ }
+
+ TextArea
+ {
+ skinClass: ClassReference("spark.skins.ios7.StageTextAreaSkin");
+ contentBackgroundAlpha: 1;
+ contentBackgroundBorder: "rectangle";
+ contentBackgroundColor: #DEDEDD;
+ focusColor: #cccccc;
+ borderColor: #cccccc;
+ selectionHighlighting: "never";
+ focusEnabled:"false";
+ focusThickness: 0;
+ focusAlpha: 0;
+ }
+
+ ToggleSwitch
+ {
+ accentColor: #3F7FBA;
+ color: #FFFFFF;
+ skinClass: ClassReference("spark.skins.ios7.ToggleSwitchSkin");
+ slideDuration: 125;
+ textShadowAlpha: .65;
+ textShadowColor: #000000;
+ }
+
+ VScrollBar
+ {
+ skinClass: ClassReference("spark.skins.ios7.VScrollBarSkin");
+ color: #E6E6E6;
+ }
+
+ ViewMenu
+ {
+ skinClass: ClassReference("spark.skins.ios7.ViewMenuSkin");
+ }
+
+ ViewMenuItem
+ {
+ iconPlacement : "left";
+ chromeColor : #FFFFFF;
+ focusColor: #DEDEDD;
+ paddingBottom: 8;
+ paddingLeft: 8;
+ paddingRight: 8;
+ paddingTop: 8;
+ skinClass : ClassReference("spark.skins.ios7.ViewMenuItemSkin");
+ }
+
+ ViewNavigator
+ {
+ skinClass: ClassReference("spark.skins.mobile.ViewNavigatorSkin");
+ }
+
+}
+
+@media (os-platform:"IOS") AND (min-os-version: 7) AND (application-dpi: 120)
+{
+ global
+ {
+ fontSize: 12;
+ focusThickness: 2;
+ }
+
+ ActionBar.beveled
+ {
+ paddingLeft: 4;
+ paddingRight: 4;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 14;
+ }
+
+ Application
+ {
+ osStatusBarHeight: 15;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 9;
+ paddingBottom : 9;
+ paddingLeft : 3;
+ paddingRight : 3;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 11;
+ }
+}
+
+@media (os-platform:"IOS") AND (min-os-version: 7) AND (application-dpi: 160)
+{
+ global
+ {
+ fontSize: 16;
+ focusThickness: 2;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 1;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 1;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 18;
+ }
+
+ Application {
+ osStatusBarHeight: 20;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 12;
+ paddingBottom : 12;
+ paddingLeft : 4;
+ paddingRight : 4;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 14;
+ }
+}
+
+@media (os-platform:"IOS") AND (min-os-version: 7) AND (application-dpi: 240)
+{
+ Application
+ {
+ osStatusBarHeight: 30;
+ }
+}
+
+@media (os-platform:"IOS") AND (min-os-version: 7) AND (application-dpi: 320)
+{
+ global
+ {
+ fontSize: 32;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 2;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 2;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 36;
+ }
+
+ Application
+ {
+ osStatusBarHeight: 40;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 24;
+ paddingBottom : 24;
+ paddingLeft : 8;
+ paddingRight : 8;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 28;
+ }
+}
+
+@media (os-platform:"IOS") AND (min-os-version: 7) AND (application-dpi: 480)
+{
+ global
+ {
+ fontSize: 48;
+ focusThickness: 6;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 4;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 4;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 54;
+ }
+
+ Application
+ {
+ osStatusBarHeight: 60;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 36;
+ paddingBottom : 36;
+ paddingLeft : 12;
+ paddingRight : 12;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 42;
+ }
+}
+
+@media (os-platform:"IOS") AND (min-os-version: 7) AND (application-dpi: 640)
+{
+ global
+ {
+ fontSize: 64;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 4;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 4;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 72;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 48;
+ paddingBottom : 48;
+ paddingLeft : 16;
+ paddingRight : 16;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 56;
+ }
+}
+
+
+
+/*
+Android 4.x specific Mobile Flex skins and styles. Defaults sizes are based on
+application-dpi=240.
+*/
+
+/*Roboto Fonts*/
+@font-face {
+ src: url("spark/skins/android4/assets/fonts/Roboto-Regular.ttf");
+ fontFamily: RobotoRegular;
+ embed-as-cff: false;
+}
+
+@font-face {
+ src: url("spark/skins/android4/assets/fonts/Roboto-Bold.ttf");
+ fontFamily: RobotoBold;
+ fontWeight: bold;
+ embed-as-cff: false;
+}
+
+@media (os-platform: "android") AND (min-os-version: "4.1.2")
+{
+ global
+ {
+ primaryAccentColor: #33B5E5;
+ fontFamily: RobotoRegular;
+ fontWeight: "normal";
+ fontSize: 24;
+ color: #000000;
+ textShadowColor: #FFFFFF;
+ textShadowAlpha: 0;
+ }
+
+ ActionBar
+ {
+ chromeColor: #DEDEDD;
+ defaultButtonAppearance: normal;
+ skinClass: ClassReference("spark.skins.android4.ActionBarSkin");
+ textShadowAlpha: 0;
+ textShadowColor: #000000;
+ paddingBottom: 1;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 1;
+ }
+
+ ActionBar #titleDisplay
+ {
+ color: #333333;
+ fontSize: 24;
+ fontFamily: RobotoBold;
+ }
+
+ ActionBar ButtonBase
+ {
+ color: #333333;
+ fontFamily: RobotoBold;
+ fontWeight: bold;
+ }
+
+ ActionBar Group#actionGroup Button
+ {
+ skinClass: ClassReference("spark.skins.android4.TransparentActionButtonSkin");
+ }
+
+ BusyIndicator
+ {
+ skinClass: ClassReference("spark.skins.android4.BusyIndicatorSkin");
+ }
+
+ Button
+ {
+ fontFamily: RobotoBold;
+ fontWeight: "bold";
+ skinClass: ClassReference("spark.skins.android4.ButtonSkin");
+ }
+
+ Button.emphasized
+ {
+ skinClass: ClassReference("spark.skins.mobile.DefaultButtonSkin");
+ }
+
+ ButtonBar
+ {
+ skinClass: ClassReference("spark.skins.android4.ButtonBarSkin");
+ fontFamily: RobotoBold;
+ fontWeight: "bold";
+ }
+
+ Callout
+ {
+ backgroundColor: #33B5E5;
+ contentBackgroundColor: #FFFFFF;
+ gap: 12;
+ skinClass: ClassReference("spark.skins.android4.CalloutSkin");
+ borderThickness: 0;
+ borderColor: 0;
+ contentBackgroundAppearance: flat;
+ }
+
+ Callout ViewNavigator ActionBar
+ {
+ skinClass: ClassReference("spark.skins.mobile.CalloutActionBarSkin");
+ defaultButtonAppearance: none;
+ paddingLeft: 0;
+ paddingRight: 0;
+ }
+
+ Callout ViewNavigator ActionBar.beveled
+ {
+ paddingLeft: 0;
+ paddingRight: 0;
+ }
+
+ Callout ViewNavigator ActionBar.beveled Group#navigationGroup Button
+ {
+ skinClass: ClassReference("spark.skins.mobile.BeveledActionButtonSkin");
+ }
+
+ Callout ViewNavigator ActionBar.beveled Group#navigationGroup Button.emphasized
+ {
+ skinClass: ClassReference("spark.skins.mobile.DefaultBeveledActionButtonSkin");
+ }
+
+ Callout#viewNavigatorPopUp
+ {
+ contentBackgroundAppearance: none;
+ }
+
+ CheckBox
+ {
+ skinClass: ClassReference("spark.skins.android4.CheckBoxSkin");
+ chromeColor: #FFFFFF;
+ }
+
+ HScrollBar
+ {
+ skinClass: ClassReference("spark.skins.android4.HScrollBarSkin");
+ color: #333333;
+ }
+
+ HSlider
+ {
+ skinClass: ClassReference("spark.skins.android4.HSliderSkin");
+ fontFamily: RobotoBold;
+ }
+
+ RadioButton
+ {
+ skinClass: ClassReference("spark.skins.android4.RadioButtonSkin");
+ chromeColor: #FFFFFF;
+ }
+
+ SpinnerList
+ {
+ skinClass: ClassReference("spark.skins.android4.SpinnerListSkin");
+ }
+
+ SpinnerListContainer
+ {
+ skinClass: ClassReference("spark.skins.android4.SpinnerListContainerSkin");
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 18;
+ paddingBottom : 18;
+ paddingLeft : 6;
+ paddingRight : 6;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontFamily: RobotoRegular;
+ chromeColor: #484848;
+ color: #000000;
+ fontSize: 20;
+ fontWeight: normal;
+ iconPlacement: top;
+ interactionMode: mouse;
+ skinClass: ClassReference("spark.skins.android4.TabbedViewNavigatorTabBarSkin");
+ textShadowAlpha: 0;
+ textShadowColor: #000000;
+ }
+
+ TextInput
+ {
+ skinClass: ClassReference("spark.skins.android4.StageTextInputSkin");
+ contentBackgroundAlpha: 0;
+ focusColor: #33B5E5;
+ contentBackgroundColor: #DEDEDD;
+ contentBackgroundBorder: "flat";
+ fontFamily: RobotoRegular;
+ selectionHighlighting: "never";
+ focusEnabled:"false";
+ focusThickness: 0;
+ }
+
+ TextArea
+ {
+ skinClass: ClassReference("spark.skins.android4.StageTextAreaSkin");
+ contentBackgroundAlpha: 1;
+ contentBackgroundBorder: "rectangle";
+ contentBackgroundColor: #DEDEDD;
+ focusColor: #33B5E5;
+ fontFamily: RobotoRegular;
+ selectionHighlighting: "never";
+ focusEnabled:"false";
+ focusThickness: 0;
+ }
+
+ ToggleSwitch
+ {
+ accentColor: #3F7FBA;
+ color: #FFFFFF;
+ skinClass: ClassReference("spark.skins.android4.ToggleSwitchSkin");
+ slideDuration: 125;
+ textShadowAlpha: .65;
+ textShadowColor: #000000;
+ }
+
+ VScrollBar
+ {
+ skinClass: ClassReference("spark.skins.android4.VScrollBarSkin");
+ color: #333333;
+ }
+
+ ViewMenu
+ {
+ skinClass: ClassReference("spark.skins.android4.ViewMenuSkin");
+ }
+
+ ViewMenuItem
+ {
+ iconPlacement : "left";
+ chromeColor : #FFFFFF;
+ focusColor: #DEDEDD;
+ paddingBottom: 8;
+ paddingLeft: 8;
+ paddingRight: 8;
+ paddingTop: 8;
+ skinClass : ClassReference("spark.skins.android4.ViewMenuItemSkin");
+ }
+
+ ViewNavigator
+ {
+ skinClass: ClassReference("spark.skins.mobile.ViewNavigatorSkin");
+ }
+}
+@media (os-platform: "android") AND (min-os-version: "4.1.2") AND (application-dpi: 120)
+{
+ global
+ {
+ fontSize: 12;
+ focusThickness: 2;
+ }
+
+ ActionBar.beveled
+ {
+ paddingLeft: 4;
+ paddingRight: 4;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 14;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 9;
+ paddingBottom : 9;
+ paddingLeft : 3;
+ paddingRight : 3;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 11;
+ }
+}
+
+@media (os-platform: "android") AND (min-os-version: "4.1.2") AND (application-dpi: 160)
+{
+ global
+ {
+ fontSize: 16;
+ focusThickness: 2;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 1;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 1;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 18;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 12;
+ paddingBottom : 12;
+ paddingLeft : 4;
+ paddingRight : 4;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 14;
+ }
+}
+
+@media (os-platform: "android") AND (min-os-version: "4.1.2") AND (application-dpi: 320)
+{
+ global
+ {
+ fontSize: 32;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 2;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 2;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 36;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 24;
+ paddingBottom : 24;
+ paddingLeft : 8;
+ paddingRight : 8;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 28;
+ }
+}
+
+@media (os-platform: "android") AND (min-os-version: "4.1.2") AND (application-dpi: 480)
+{
+ global
+ {
+ fontSize: 48;
+ focusThickness: 6;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 4;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 4;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 54;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 36;
+ paddingBottom : 36;
+ paddingLeft : 12;
+ paddingRight : 12;
+ }
+
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 42;
+ }
+}
+
+@media (os-platform: "android") AND (min-os-version: "4.1.2") AND (application-dpi: 640)
+{
+ global
+ {
+ fontSize: 64;
+ }
+
+ ActionBar
+ {
+ paddingBottom: 4;
+ paddingLeft: 0;
+ paddingRight: 0;
+ paddingTop: 4;
+ }
+
+ ActionBar #titleDisplay
+ {
+ fontSize: 72;
+ }
+
+ SpinnerListItemRenderer
+ {
+ paddingTop : 48;
+ paddingBottom : 48;
+ paddingLeft : 16;
+ paddingRight : 16;
+ }
+
+ TabbedViewNavigator #tabBar
+ {
+ fontSize: 56;
+ }
+}
diff --git a/frameworks/projects/mobiletheme/src/MobileThemeClasses.as b/frameworks/projects/mobiletheme/src/MobileThemeClasses.as
index 1f890cbef8..70272df13a 100644
--- a/frameworks/projects/mobiletheme/src/MobileThemeClasses.as
+++ b/frameworks/projects/mobiletheme/src/MobileThemeClasses.as
@@ -19,60 +19,128 @@
package
{
-
-internal class MobileThemeClasses
-{
-
-/**
- * @private
- * This class is used to link additional classes into mobile.swc
- * beyond those that are found by dependecy analysis starting
- * from the classes specified in manifest.xml.
- */
-import spark.skins.mobile.ActionBarSkin; ActionBarSkin;
-import spark.skins.mobile.BeveledActionButtonSkin; BeveledActionButtonSkin;
-import spark.skins.mobile.BeveledBackButtonSkin; BeveledBackButtonSkin;
-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;
- import spark.skins.mobile.supportClasses.CalloutArrow; spark.skins.mobile.supportClasses.CalloutArrow;
- import spark.skins.mobile.CalloutActionBarSkin; spark.skins.mobile.CalloutActionBarSkin;
-import spark.skins.mobile.CalloutViewNavigatorSkin; spark.skins.mobile.CalloutViewNavigatorSkin;
-import spark.skins.mobile.CheckBoxSkin; spark.skins.mobile.CheckBoxSkin;
-import spark.skins.mobile.DefaultBeveledActionButtonSkin; spark.skins.mobile.DefaultBeveledActionButtonSkin;
-import spark.skins.mobile.DefaultBeveledBackButtonSkin; spark.skins.mobile.DefaultBeveledBackButtonSkin;
-import spark.skins.mobile.DefaultButtonSkin; spark.skins.mobile.DefaultButtonSkin;
-import spark.skins.mobile.DefaultTransparentActionButtonSkin; spark.skins.mobile.DefaultTransparentActionButtonSkin;
-import spark.skins.mobile.DefaultTransparentNavigationButtonSkin; spark.skins.mobile.DefaultTransparentNavigationButtonSkin;
-import spark.skins.mobile.DateSpinnerSkin; spark.skins.mobile.DateSpinnerSkin;
-import spark.skins.mobile.HScrollBarSkin; spark.skins.mobile.HScrollBarSkin;
-import spark.skins.mobile.HSliderSkin; spark.skins.mobile.HSliderSkin;
-import spark.skins.mobile.ImageSkin; spark.skins.mobile.ImageSkin;
-import spark.skins.mobile.ListSkin; spark.skins.mobile.ListSkin;
-import spark.skins.mobile.RadioButtonSkin; spark.skins.mobile.RadioButtonSkin;
-import spark.skins.mobile.SpinnerListContainerSkin; SpinnerListContainerSkin;
-import spark.skins.mobile.SpinnerListScrollerSkin; SpinnerListScrollerSkin;
-import spark.skins.mobile.SpinnerListSkin; SpinnerListSkin;
-import spark.skins.mobile.SkinnableContainerSkin; SkinnableContainerSkin;
-import spark.skins.mobile.SplitViewNavigatorSkin; SplitViewNavigatorSkin;
-import spark.skins.mobile.StageTextAreaSkin; StageTextAreaSkin;
-import spark.skins.mobile.StageTextInputSkin; StageTextInputSkin;
- import spark.skins.mobile.ScrollingStageTextInputSkin; ScrollingStageTextInputSkin;
-import spark.skins.mobile.ScrollingStageTextAreaSkin; ScrollingStageTextAreaSkin
-import spark.skins.mobile.TabbedViewNavigatorApplicationSkin; TabbedViewNavigatorApplicationSkin;
-import spark.skins.mobile.TabbedViewNavigatorSkin; TabbedViewNavigatorSkin;
-import spark.skins.mobile.TabbedViewNavigatorTabBarSkin; TabbedViewNavigatorTabBarSkin;
-import spark.skins.mobile.TextAreaSkin; TextAreaSkin;
-import spark.skins.mobile.TextAreaHScrollBarSkin; TextAreaHScrollBarSkin;
-import spark.skins.mobile.TextAreaVScrollBarSkin; TextAreaVScrollBarSkin;
-import spark.skins.mobile.TextInputSkin; TextInputSkin;
-import spark.skins.mobile.ToggleSwitchSkin; ToggleSwitchSkin;
-import spark.skins.mobile.TransparentActionButtonSkin; TransparentActionButtonSkin;
-import spark.skins.mobile.TransparentNavigationButtonSkin; TransparentNavigationButtonSkin;
-import spark.skins.mobile.ViewMenuItemSkin; ViewMenuItemSkin;
-import spark.skins.mobile.ViewMenuSkin; ViewMenuSkin;
-import spark.skins.mobile.ViewNavigatorApplicationSkin; ViewNavigatorApplicationSkin;
-import spark.skins.mobile.ViewNavigatorSkin; ViewNavigatorSkin;
-import spark.skins.mobile.VScrollBarSkin; spark.skins.mobile.VScrollBarSkin;
-}
+
+ internal class MobileThemeClasses
+ {
+
+ /**
+ * @private
+ * This class is used to link additional classes into mobile.swc
+ * beyond those that are found by dependecy analysis starting
+ * from the classes specified in manifest.xml.
+ */
+ 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;
+ import spark.skins.mobile.supportClasses.CalloutArrow; spark.skins.mobile.supportClasses.CalloutArrow;
+ import spark.skins.mobile.CalloutActionBarSkin; spark.skins.mobile.CalloutActionBarSkin;
+ import spark.skins.mobile.CalloutViewNavigatorSkin; spark.skins.mobile.CalloutViewNavigatorSkin;
+ import spark.skins.mobile.CheckBoxSkin; spark.skins.mobile.CheckBoxSkin;
+ import spark.skins.mobile.DefaultBeveledActionButtonSkin; spark.skins.mobile.DefaultBeveledActionButtonSkin;
+ import spark.skins.mobile.DefaultBeveledBackButtonSkin; spark.skins.mobile.DefaultBeveledBackButtonSkin;
+ import spark.skins.mobile.DefaultButtonSkin; spark.skins.mobile.DefaultButtonSkin;
+ import spark.skins.mobile.DefaultTransparentActionButtonSkin; spark.skins.mobile.DefaultTransparentActionButtonSkin;
+ import spark.skins.mobile.DefaultTransparentNavigationButtonSkin; spark.skins.mobile.DefaultTransparentNavigationButtonSkin;
+ import spark.skins.mobile.DateSpinnerSkin; spark.skins.mobile.DateSpinnerSkin;
+ import spark.skins.mobile.HScrollBarSkin; spark.skins.mobile.HScrollBarSkin;
+ import spark.skins.mobile.HSliderSkin; spark.skins.mobile.HSliderSkin;
+ import spark.skins.mobile.ImageSkin; spark.skins.mobile.ImageSkin;
+ import spark.skins.mobile.ListSkin; spark.skins.mobile.ListSkin;
+ import spark.skins.mobile.RadioButtonSkin; spark.skins.mobile.RadioButtonSkin;
+ import spark.skins.mobile.SpinnerListContainerSkin; spark.skins.mobile.SpinnerListContainerSkin;
+ import spark.skins.mobile.SpinnerListScrollerSkin; spark.skins.mobile.SpinnerListScrollerSkin;
+ import spark.skins.mobile.SpinnerListSkin; spark.skins.mobile.SpinnerListSkin;
+ import spark.skins.mobile.SkinnableContainerSkin; spark.skins.mobile.SkinnableContainerSkin;
+ import spark.skins.mobile.SplitViewNavigatorSkin; spark.skins.mobile.SplitViewNavigatorSkin;
+ import spark.skins.mobile.StageTextAreaSkin; spark.skins.mobile.StageTextAreaSkin;
+ import spark.skins.mobile.StageTextInputSkin; spark.skins.mobile.StageTextInputSkin;
+ import spark.skins.mobile.ScrollingStageTextInputSkin; spark.skins.mobile.ScrollingStageTextInputSkin;
+ import spark.skins.mobile.ScrollingStageTextAreaSkin; spark.skins.mobile.ScrollingStageTextAreaSkin
+ import spark.skins.mobile.TabbedViewNavigatorApplicationSkin; spark.skins.mobile.TabbedViewNavigatorApplicationSkin;
+ import spark.skins.mobile.TabbedViewNavigatorSkin; spark.skins.mobile.TabbedViewNavigatorSkin;
+ import spark.skins.mobile.TabbedViewNavigatorTabBarSkin; spark.skins.mobile.TabbedViewNavigatorTabBarSkin;
+ import spark.skins.mobile.TextAreaSkin; spark.skins.mobile.TextAreaSkin;
+ import spark.skins.mobile.TextAreaHScrollBarSkin; spark.skins.mobile.TextAreaHScrollBarSkin;
+ import spark.skins.mobile.TextAreaVScrollBarSkin; spark.skins.mobile.TextAreaVScrollBarSkin;
+ import spark.skins.mobile.TextInputSkin; spark.skins.mobile.TextInputSkin;
+ import spark.skins.mobile.ToggleSwitchSkin; spark.skins.mobile.ToggleSwitchSkin;
+ import spark.skins.mobile.TransparentActionButtonSkin; spark.skins.mobile.TransparentActionButtonSkin;
+ import spark.skins.mobile.TransparentNavigationButtonSkin; spark.skins.mobile.TransparentNavigationButtonSkin;
+ import spark.skins.mobile.ViewMenuItemSkin; spark.skins.mobile.ViewMenuItemSkin;
+ import spark.skins.mobile.ViewMenuSkin; spark.skins.mobile.ViewMenuSkin;
+ import spark.skins.mobile.ViewNavigatorApplicationSkin; spark.skins.mobile.ViewNavigatorApplicationSkin;
+ import spark.skins.mobile.ViewNavigatorSkin; spark.skins.mobile.ViewNavigatorSkin;
+ import spark.skins.mobile.VScrollBarSkin; spark.skins.mobile.VScrollBarSkin;
+
+ //Android skins
+ import spark.skins.android4.ActionBarSkin; spark.skins.android4.ActionBarSkin;
+ import spark.skins.android4.BusyIndicatorSkin; spark.skins.android4.BusyIndicatorSkin;
+ import spark.skins.android4.ButtonBarFirstButtonSkin; spark.skins.android4.ButtonBarFirstButtonSkin;
+ import spark.skins.android4.ButtonBarMiddleButtonSkin; spark.skins.android4.ButtonBarMiddleButtonSkin;
+ import spark.skins.android4.ButtonBarSkin; spark.skins.android4.ButtonBarSkin;
+ import spark.skins.android4.ButtonSkin; spark.skins.android4.ButtonSkin;
+ import spark.skins.android4.CalloutSkin; spark.skins.android4.CalloutSkin;
+ import spark.skins.android4.CheckBoxSkin; spark.skins.android4.CheckBoxSkin;
+ import spark.skins.android4.HScrollBarSkin; spark.skins.android4.HScrollBarSkin;
+ import spark.skins.android4.HScrollBarThumbSkin; spark.skins.android4.HScrollBarThumbSkin;
+ import spark.skins.android4.HSliderSkin; spark.skins.android4.HSliderSkin;
+ import spark.skins.android4.HSliderThumbSkin; spark.skins.android4.HSliderThumbSkin;
+ import spark.skins.android4.HSliderTrackSkin; spark.skins.android4.HSliderTrackSkin;
+ import spark.skins.android4.RadioButtonSkin; spark.skins.android4.RadioButtonSkin;
+ import spark.skins.android4.SpinnerListContainerSkin; spark.skins.android4.SpinnerListContainerSkin;
+ import spark.skins.android4.SpinnerListScrollerSkin; spark.skins.android4.SpinnerListScrollerSkin;
+ import spark.skins.android4.SpinnerListSkin; spark.skins.android4.SpinnerListSkin;
+ import spark.skins.android4.StageTextAreaSkin; spark.skins.android4.StageTextAreaSkin;
+ import spark.skins.android4.StageTextInputSkin; spark.skins.android4.StageTextInputSkin;
+ import spark.skins.android4.TabbedViewNavigatorTabBarSkin; spark.skins.android4.TabbedViewNavigatorTabBarSkin;
+ import spark.skins.android4.TextAreaSkin; spark.skins.android4.TextAreaSkin;
+ import spark.skins.android4.TextInputSkin; spark.skins.android4.TextInputSkin;
+ import spark.skins.android4.ToggleSwitchSkin; spark.skins.android4.ToggleSwitchSkin;
+ import spark.skins.android4.TransparentActionButtonSkin; spark.skins.android4.TransparentActionButtonSkin;
+ import spark.skins.android4.TransparentNavigationButtonSkin; spark.skins.android4.TransparentNavigationButtonSkin;
+ import spark.skins.android4.ViewMenuItemSkin; spark.skins.android4.ViewMenuItemSkin;
+ import spark.skins.android4.ViewMenuSkin; spark.skins.android4.ViewMenuSkin;
+ import spark.skins.android4.VScrollBarSkin; spark.skins.android4.VScrollBarSkin;
+ import spark.skins.android4.VScrollBarThumbSkin; spark.skins.android4.VScrollBarThumbSkin;
+ import spark.skins.android4.supportClasses.CalloutArrow; spark.skins.android4.supportClasses.CalloutArrow;
+
+ //iOS7+ skins
+ import spark.skins.ios7.ActionBarSkin; spark.skins.ios7.ActionBarSkin;
+ import spark.skins.ios7.BusyIndicatorSkin; spark.skins.ios7.BusyIndicatorSkin;
+ import spark.skins.ios7.ButtonBarFirstButtonSkin; spark.skins.ios7.ButtonBarFirstButtonSkin;
+ import spark.skins.ios7.ButtonBarMiddleButtonSkin; spark.skins.ios7.ButtonBarMiddleButtonSkin;
+ import spark.skins.ios7.ButtonBarSkin; spark.skins.ios7.ButtonBarSkin;
+ import spark.skins.ios7.ButtonSkin; spark.skins.ios7.ButtonSkin;
+ import spark.skins.ios7.CalloutSkin; spark.skins.ios7.CalloutSkin;
+ import spark.skins.ios7.CalloutActionBarSkin; spark.skins.ios7.CalloutActionBarSkin;
+ import spark.skins.ios7.CalloutViewNavigatorSkin; spark.skins.ios7.CalloutViewNavigatorSkin;
+ import spark.skins.ios7.CheckBoxSkin; spark.skins.ios7.CheckBoxSkin;
+ import spark.skins.ios7.HScrollBarSkin; spark.skins.ios7.HScrollBarSkin;
+ import spark.skins.ios7.HScrollBarThumbSkin; spark.skins.ios7.HScrollBarThumbSkin;
+ import spark.skins.ios7.HSliderSkin; spark.skins.ios7.HSliderSkin;
+ import spark.skins.ios7.HSliderThumbSkin; spark.skins.ios7.HSliderThumbSkin;
+ import spark.skins.ios7.HSliderTrackSkin; spark.skins.ios7.HSliderTrackSkin;
+ import spark.skins.ios7.RadioButtonSkin; spark.skins.ios7.RadioButtonSkin;
+ import spark.skins.ios7.SpinnerListContainerSkin; spark.skins.ios7.SpinnerListContainerSkin;
+ import spark.skins.ios7.SpinnerListScrollerSkin; spark.skins.ios7.SpinnerListScrollerSkin;
+ import spark.skins.ios7.SpinnerListSkin; spark.skins.ios7.SpinnerListSkin;
+ import spark.skins.ios7.StageTextAreaSkin; spark.skins.ios7.StageTextAreaSkin;
+ import spark.skins.ios7.StageTextInputSkin; spark.skins.ios7.StageTextInputSkin;
+ import spark.skins.ios7.TabbedViewNavigatorTabBarSkin; spark.skins.ios7.TabbedViewNavigatorTabBarSkin;
+ import spark.skins.ios7.TextAreaSkin; spark.skins.ios7.TextAreaSkin;
+ import spark.skins.ios7.TextInputSkin; spark.skins.ios7.TextInputSkin;
+ import spark.skins.ios7.ToggleSwitchSkin; spark.skins.ios7.ToggleSwitchSkin;
+ import spark.skins.ios7.TransparentActionButtonSkin; spark.skins.ios7.TransparentActionButtonSkin;
+ import spark.skins.ios7.TransparentNavigationButtonSkin; spark.skins.ios7.TransparentNavigationButtonSkin;
+ import spark.skins.ios7.ViewMenuItemSkin; spark.skins.ios7.ViewMenuItemSkin;
+ import spark.skins.ios7.ViewMenuSkin; spark.skins.ios7.ViewMenuSkin;
+ import spark.skins.ios7.VScrollBarSkin; spark.skins.ios7.VScrollBarSkin;
+ import spark.skins.ios7.VScrollBarThumbSkin; spark.skins.ios7.VScrollBarThumbSkin;
+ import spark.skins.ios7.supportClasses.CalloutArrow; spark.skins.ios7.supportClasses.CalloutArrow;
+
+ }
}
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ActionBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/ActionBarSkin.as
new file mode 100644
index 0000000000..8ffbe4d2a1
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ActionBarSkin.as
@@ -0,0 +1,727 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.GradientType;
+import flash.events.Event;
+import flash.text.TextFormatAlign;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+import mx.utils.ColorUtil;
+
+import spark.components.ActionBar;
+import spark.components.Group;
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.SpriteVisualElement;
+import spark.layouts.HorizontalAlign;
+import spark.layouts.HorizontalLayout;
+import spark.layouts.VerticalAlign;
+import spark.skins.android4.assets.ActionBarBackground;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for the Spark ActionBar component in mobile
+ * applications.
+ *
+ * @see spark.components.ActionBar
+ * @see spark.skins.mobile.TransparentNavigationButtonSkin
+ * @see spark.skins.mobile.BeveledBackButtonSkin
+ * @see spark.skins.mobile.TransparentActionButtonSkin
+ * @see spark.skins.mobile.BeveledActionButtonSkin
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ActionBarSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ mx_internal static const ACTIONBAR_CHROME_COLOR_RATIOS:Array = [0, 80];
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ActionBarSkin()
+ {
+ super();
+
+ borderClass = spark.skins.android4.assets.ActionBarBackground;
+
+ switch (applicationDPI)
+ {
+
+ case DPIClassification.DPI_640:
+ {
+ borderSize = 2;
+ layoutContentGroupHeight = 172;
+ layoutTitleGroupHorizontalPadding = 52;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ borderSize = 2;
+ layoutContentGroupHeight = 130;
+ layoutTitleGroupHorizontalPadding = 40;
+
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ borderSize = 2;
+ layoutContentGroupHeight = 86;
+ layoutTitleGroupHorizontalPadding = 26;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ borderSize = 1;
+ layoutContentGroupHeight = 65;
+ layoutTitleGroupHorizontalPadding = 20;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ borderSize = 1;
+ layoutContentGroupHeight = 32;
+ layoutTitleGroupHorizontalPadding = 10;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ borderSize = 1;
+ layoutContentGroupHeight = 43;
+ layoutTitleGroupHorizontalPadding = 13;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Graphics variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * FXG Class reference for the ActionBar background border graphic.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var borderClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ private var borderSize:uint;
+
+ /**
+ * Default height for navigationGroup, titleGroup and actionGroup.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var layoutContentGroupHeight:uint;
+
+ /**
+ * Default horizontal padding for the titleGroup and titleDisplay.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var layoutTitleGroupHorizontalPadding:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:ActionBar;
+
+ /**
+ * @private
+ */
+ private var _navigationVisible:Boolean = false;
+
+ /**
+ * @private
+ */
+ private var _titleContentVisible:Boolean = false;
+
+ /**
+ * @private
+ */
+ private var _actionVisible:Boolean = false;
+
+ /**
+ * @private
+ */
+ private var border:SpriteVisualElement;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.components.ActionBar#navigationGroup
+ */
+ public var navigationGroup:Group;
+
+ /**
+ * @copy spark.components.ActionBar#titleGroup
+ */
+ public var titleGroup:Group;
+
+ /**
+ * @copy spark.components.ActionBar#actionGroup
+ */
+ public var actionGroup:Group;
+
+ /**
+ * @copy spark.components.ActionBar#titleDisplay
+ *
+ * @private
+ * Wraps a StyleableTextField in a UIComponent to be compatible with
+ * ViewTransition effects.
+ */
+ public var titleDisplay:TitleDisplayComponent;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ if (borderClass)
+ {
+ border = new borderClass();
+ addChild(border);
+ }
+
+ navigationGroup = new Group();
+ var hLayout:HorizontalLayout = new HorizontalLayout();
+ hLayout.horizontalAlign = HorizontalAlign.LEFT;
+ hLayout.verticalAlign = VerticalAlign.MIDDLE;
+ hLayout.gap = 0;
+ hLayout.paddingLeft = hLayout.paddingTop = hLayout.paddingRight =
+ hLayout.paddingBottom = 0;
+ navigationGroup.layout = hLayout;
+ navigationGroup.id = "navigationGroup";
+
+ titleGroup = new Group();
+ hLayout = new HorizontalLayout();
+ hLayout.horizontalAlign = HorizontalAlign.LEFT;
+ hLayout.verticalAlign = VerticalAlign.MIDDLE;
+ hLayout.gap = 0;
+ hLayout.paddingLeft = hLayout.paddingRight = layoutTitleGroupHorizontalPadding;
+ hLayout.paddingTop = hLayout.paddingBottom = 0;
+ titleGroup.layout = hLayout;
+ titleGroup.id = "titleGroup";
+
+ actionGroup = new Group();
+ hLayout = new HorizontalLayout();
+ hLayout.horizontalAlign = HorizontalAlign.RIGHT;
+ hLayout.verticalAlign = VerticalAlign.MIDDLE;
+ hLayout.gap = 0;
+ hLayout.paddingLeft = hLayout.paddingTop = hLayout.paddingRight =
+ hLayout.paddingBottom = 0;
+ actionGroup.layout = hLayout;
+ actionGroup.id = "actionGroup";
+
+ titleDisplay = new TitleDisplayComponent();
+ titleDisplay.id = "titleDisplay";
+
+ // initialize titleAlign style (center is managed explicitly in layoutContents)
+ var titleAlign:String = getStyle("titleAlign");
+ titleAlign = (titleAlign == "center") ? TextFormatAlign.LEFT : titleAlign;
+ titleDisplay.setStyle("textAlign", titleAlign);
+
+ addChild(navigationGroup);
+ addChild(titleGroup);
+ addChild(actionGroup);
+ addChild(titleDisplay);
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ var titleWidth:Number = 0;
+ var titleHeight:Number = 0;
+
+ if (_titleContentVisible)
+ {
+ titleWidth = titleGroup.getPreferredBoundsWidth();
+ titleHeight = titleGroup.getPreferredBoundsHeight();
+ }
+ else
+ {
+ // use titleLayout for paddingLeft and paddingRight
+ var layoutObject:Object = hostComponent.titleLayout;
+ titleWidth = ((layoutObject.paddingLeft) ? Number(layoutObject.paddingLeft) : 0)
+ + ((layoutObject.paddingRight) ? Number(layoutObject.paddingRight) : 0)
+ + titleDisplay.getPreferredBoundsWidth();
+
+ titleHeight = titleDisplay.getPreferredBoundsHeight();
+ }
+
+ measuredWidth =
+ getStyle("paddingLeft")
+ + navigationGroup.getPreferredBoundsWidth()
+ + titleWidth
+ + actionGroup.getPreferredBoundsWidth()
+ + getStyle("paddingRight");
+
+ // measuredHeight is contentGroupHeight, 2x border on top and bottom
+ measuredHeight =
+ getStyle("paddingTop")
+ + Math.max(layoutContentGroupHeight,
+ navigationGroup.getPreferredBoundsHeight(),
+ actionGroup.getPreferredBoundsHeight(),
+ titleHeight)
+ + getStyle("paddingBottom");
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ _titleContentVisible = currentState.indexOf("titleContent") >= 0;
+ _navigationVisible = currentState.indexOf("Navigation") >= 0;
+ _actionVisible = currentState.indexOf("Action") >= 0;
+
+ invalidateSize();
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ if (titleDisplay)
+ {
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || (styleProp == "titleAlign"))
+ {
+ var titleAlign:String = getStyle("titleAlign");
+
+ if (titleAlign == "center")
+ {
+ // If the title align is set to center, the alignment is set to LEFT
+ // so that the skin can manually center the component in layoutContents
+ titleDisplay.setStyle("textAlign", TextFormatAlign.LEFT);
+ }
+ else
+ {
+ titleDisplay.setStyle("textAlign", titleAlign);
+ }
+ }
+ }
+
+ super.styleChanged(styleProp);
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ var navigationGroupWidth:Number = 0;
+
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var titleCompX:Number = paddingLeft;
+ var titleCompWidth:Number = 0;
+
+ var actionGroupX:Number = unscaledWidth;
+ var actionGroupWidth:Number = 0;
+
+ // remove top and bottom padding from content group height
+ var contentGroupsHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+
+ if (border)
+ {
+ // FXG uses scale-9, drop shadow is drawn outside the bounds
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ }
+
+ // position groups, overlap of navigation and action groups is allowed
+ // when overlap occurs, titleDisplay/titleGroup is not visible
+ if (_navigationVisible)
+ {
+ navigationGroupWidth = navigationGroup.getPreferredBoundsWidth();
+ titleCompX += navigationGroupWidth;
+
+ setElementSize(navigationGroup, navigationGroupWidth, contentGroupsHeight);
+ setElementPosition(navigationGroup, paddingLeft, paddingTop);
+ }
+
+ if (_actionVisible)
+ {
+ // actionGroup x position can be negative
+ actionGroupWidth = actionGroup.getPreferredBoundsWidth();
+ actionGroupX = unscaledWidth - actionGroupWidth - paddingRight;
+
+ setElementSize(actionGroup, actionGroupWidth, contentGroupsHeight);
+ setElementPosition(actionGroup, actionGroupX, paddingTop);
+ }
+
+ // titleGroup or titleDisplay is given remaining width after navigation
+ // and action groups preferred widths
+ titleCompWidth = unscaledWidth - navigationGroupWidth - actionGroupWidth
+ - paddingLeft - paddingRight;
+
+ if (titleCompWidth <= 0)
+ {
+ titleDisplay.visible = false;
+ titleGroup.visible = false;
+ }
+ else if (_titleContentVisible)
+ {
+ titleDisplay.visible = false;
+ titleGroup.visible = true;
+
+ // use titleGroup for titleContent
+ setElementSize(titleGroup, titleCompWidth, contentGroupsHeight);
+ setElementPosition(titleGroup, titleCompX, paddingTop);
+ }
+ else
+ {
+ // use titleDisplay for title text label
+ titleGroup.visible = false;
+
+ // use titleLayout for paddingLeft and paddingRight
+ var layoutObject:Object = hostComponent.titleLayout;
+ var titlePaddingLeft:Number = (layoutObject.paddingLeft) ? Number(layoutObject.paddingLeft) : 0;
+ var titlePaddingRight:Number = (layoutObject.paddingRight) ? Number(layoutObject.paddingRight) : 0;
+
+ // align titleDisplay to the absolute center
+ var titleAlign:String = getStyle("titleAlign");
+
+ // check for available width after padding
+ if ((titleCompWidth - titlePaddingLeft - titlePaddingRight) <= 0)
+ {
+ titleCompX = 0;
+ titleCompWidth = 0;
+ }
+ else if (titleAlign == "center")
+ {
+ // use LEFT instead of CENTER
+ titleCompWidth = titleDisplay.getExplicitOrMeasuredWidth();
+
+ // use x position of titleDisplay to implement CENTER
+ titleCompX = Math.round((unscaledWidth - titleCompWidth) / 2);
+
+ var navigationOverlap:Number = navigationGroupWidth + titlePaddingLeft - titleCompX;
+ var actionOverlap:Number = (titleCompX + titleCompWidth + titlePaddingRight) - actionGroupX;
+
+ // shrink and/or move titleDisplay width if there is any
+ // overlap after centering
+ if ((navigationOverlap > 0) && (actionOverlap > 0))
+ {
+ // remaining width
+ titleCompX = navigationGroupWidth + titlePaddingLeft;
+ titleCompWidth = unscaledWidth - navigationGroupWidth - actionGroupWidth - titlePaddingLeft - titlePaddingRight;
+ }
+ else if ((navigationOverlap > 0) || (actionOverlap > 0))
+ {
+ if (navigationOverlap > 0)
+ {
+ // nudge to the right
+ titleCompX += navigationOverlap;
+ }
+ else if (actionOverlap > 0)
+ {
+ // nudge to the left
+ titleCompX -= actionOverlap;
+
+ // force left padding
+ if (titleCompX < (navigationGroupWidth + titlePaddingLeft))
+ titleCompX = navigationGroupWidth + titlePaddingLeft;
+ }
+
+ // recompute action overlap and force right padding
+ actionOverlap = (titleCompX + titleCompWidth + titlePaddingRight) - actionGroupX;
+
+ if (actionOverlap > 0)
+ titleCompWidth -= actionOverlap;
+ }
+ }
+ else
+ {
+ // implement padding by adjusting width and position
+ titleCompX += titlePaddingLeft;
+ titleCompWidth = titleCompWidth - titlePaddingLeft - titlePaddingRight;
+ }
+
+ // check for negative width
+ titleCompWidth = (titleCompWidth < 0) ? 0 : titleCompWidth;
+
+ setElementSize(titleDisplay, titleCompWidth, contentGroupsHeight);
+ setElementPosition(titleDisplay, titleCompX, paddingTop);
+
+ titleDisplay.visible = true;
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var chromeColor:uint = getStyle("chromeColor");
+ var backgroundAlphaValue:Number = getStyle("backgroundAlpha");
+ var colors:Array = [];
+
+ // apply alpha to chromeColor fill only
+ var backgroundAlphas:Array = [backgroundAlphaValue, backgroundAlphaValue];
+
+ // exclude top and bottom 1px borders
+ colorMatrix.createGradientBox(unscaledWidth, unscaledHeight - (borderSize * 2), Math.PI / 2, 0, 0);
+
+ colors[0] = ColorUtil.adjustBrightness2(chromeColor, 20);
+ colors[1] = chromeColor;
+
+ graphics.beginGradientFill(GradientType.LINEAR, colors, backgroundAlphas, ACTIONBAR_CHROME_COLOR_RATIOS, colorMatrix);
+ graphics.drawRect(0, borderSize, unscaledWidth, unscaledHeight - (borderSize * 2));
+ graphics.endFill();
+ }
+
+}
+}
+import flash.events.Event;
+
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.IDisplayText;
+
+use namespace mx_internal;
+
+/**
+ * @private
+ * Component that holds StyleableTextFields to produce a drop shadow effect.
+ * Combines label and shadow into a single component to allow transitions to
+ * target them both.
+ */
+class TitleDisplayComponent extends UIComponent implements IDisplayText
+{
+ private var titleDisplay:StyleableTextField;
+ private var titleDisplayShadow:StyleableTextField;
+ private var title:String;
+ private var titleChanged:Boolean;
+
+ public function TitleDisplayComponent()
+ {
+ super();
+ title = "";
+ }
+
+ override public function get baselinePosition():Number
+ {
+ return titleDisplay.baselinePosition;
+ }
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ titleDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ titleDisplay.styleName = this;
+ titleDisplay.editable = false;
+ titleDisplay.selectable = false;
+ titleDisplay.multiline = false;
+ titleDisplay.wordWrap = false;
+ titleDisplay.addEventListener(FlexEvent.VALUE_COMMIT,
+ titleDisplay_valueCommitHandler);
+
+ titleDisplayShadow =
+ StyleableTextField(createInFontContext(StyleableTextField));
+ titleDisplayShadow.styleName = this;
+ titleDisplayShadow.colorName = "textShadowColor";
+ titleDisplayShadow.editable = false;
+ titleDisplayShadow.selectable = false;
+ titleDisplayShadow.multiline = false;
+ titleDisplayShadow.wordWrap = false;
+
+ addChild(titleDisplayShadow);
+ addChild(titleDisplay);
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitProperties():void
+ {
+ super.commitProperties();
+
+ if (titleChanged)
+ {
+ titleDisplay.text = title;
+
+ invalidateSize();
+ invalidateDisplayList();
+
+ titleChanged = false;
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ // reset text if it was truncated before.
+ if (titleDisplay.isTruncated)
+ titleDisplay.text = title;
+
+ measuredWidth = titleDisplay.getPreferredBoundsWidth();
+
+ // tightTextHeight
+ measuredHeight = titleDisplay.getPreferredBoundsHeight();
+ }
+
+ /**
+ * @private
+ */
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+ // reset text if it was truncated before.
+ if (titleDisplay.isTruncated)
+ titleDisplay.text = title;
+ titleDisplay.commitStyles();
+
+ // use preferred height, setLayoutBoundsSize will accommodate for tight
+ // text adjustment
+ var tightHeight:Number = titleDisplay.getPreferredBoundsHeight();
+ var tightY:Number = (unscaledHeight - tightHeight) / 2;
+
+ titleDisplay.setLayoutBoundsSize(unscaledWidth, tightHeight);
+ titleDisplay.setLayoutBoundsPosition(0, (unscaledHeight - tightHeight) / 2);
+
+ // now truncate the text
+ titleDisplay.truncateToFit();
+
+ titleDisplayShadow.commitStyles();
+ titleDisplayShadow.setLayoutBoundsSize(unscaledWidth, tightHeight);
+ titleDisplayShadow.setLayoutBoundsPosition(0, tightY + 1);
+
+ titleDisplayShadow.alpha = getStyle("textShadowAlpha");
+
+ // if labelDisplay is truncated, then push it down here as well.
+ // otherwise, it would have gotten pushed in the labelDisplay_valueCommitHandler()
+ if (titleDisplay.isTruncated)
+ titleDisplayShadow.text = titleDisplay.text;
+ }
+
+ /**
+ * @private
+ */
+ private function titleDisplay_valueCommitHandler(event:Event):void
+ {
+ titleDisplayShadow.text = titleDisplay.text;
+ }
+
+ public function get text():String
+ {
+ return title;
+ }
+
+ public function set text(value:String):void
+ {
+ title = value;
+ titleChanged = true;
+
+ invalidateProperties();
+ }
+
+ public function get isTruncated():Boolean
+ {
+ return titleDisplay.isTruncated;
+ }
+}
\ No newline at end of file
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 0000000000..964b8cff21
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/BusyIndicatorSkin.as
@@ -0,0 +1,210 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.BusyIndicator;
+
+ 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;
+ private var symbolColor:uint;
+ private var symbolColorChanged:Boolean = false;
+
+ 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.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
+ {
+ 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();
+ }
+ }
+
+ override public function styleChanged(styleProp:String):void
+ {
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || styleProp == "symbolColor")
+ {
+ symbolColor = getStyle("symbolColor");
+ symbolColorChanged = true;
+ invalidateDisplayList();
+ }
+ 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(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
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarFirstButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarFirstButtonSkin.as
new file mode 100644
index 0000000000..4b8cbba095
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarFirstButtonSkin.as
@@ -0,0 +1,93 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.skins.android4.assets.ButtonBarFirstButton_selectedDown;
+ import spark.skins.android4.assets.ButtonBarFirstButton_selectedUp;
+ import spark.skins.mobile.supportClasses.ButtonBarButtonSkinBase;
+
+ /**
+ * Android 4.x specific Button skin for the first Button in a ButtonBar.
+ *
+ * @see spark.components.ButtonBar#firstButton
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class ButtonBarFirstButtonSkin extends ButtonBarButtonSkinBase
+ {
+
+ /**
+ * Class to use for the border in the selected and down state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var selectedDownBorderSkin:Class;
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ButtonBarFirstButtonSkin()
+ {
+ super();
+
+ upBorderSkin = spark.skins.android4.assets.ButtonBarFirstButton_up;
+ downBorderSkin = spark.skins.android4.assets.ButtonBarFirstButton_down;
+ selectedBorderSkin = spark.skins.android4.assets.ButtonBarFirstButton_selectedUp;
+ selectedDownBorderSkin = spark.skins.android4.assets.ButtonBarFirstButton_selectedDown;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ //Dont draw background
+ }
+
+ override protected function getBorderClassForCurrentState():Class
+ {
+ var isSelected:Boolean = currentState.indexOf("Selected") >= 0;
+ var isDown:Boolean = currentState.indexOf("down") >= 0;
+
+ if (isSelected && !isDown )
+ return selectedBorderSkin;
+ else if (isSelected && isDown)
+ return selectedDownBorderSkin;
+ else if (!isSelected && !isDown)
+ return upBorderSkin;
+ else
+ return downBorderSkin;
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarMiddleButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarMiddleButtonSkin.as
new file mode 100644
index 0000000000..c6206d0f42
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarMiddleButtonSkin.as
@@ -0,0 +1,95 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.skins.android4.assets.ButtonBarMiddleButton_selectedDown;
+ import spark.skins.android4.assets.ButtonBarMiddleButton_selectedUp;
+ import spark.skins.android4.assets.ButtonBarMiddleButton_up;
+ import spark.skins.mobile.supportClasses.ButtonBarButtonSkinBase;
+
+ /**
+ * Android 4.x specific Button skin for middle Buttons in a ButtonBar.
+ *
+ * @see spark.components.ButtonBar#middleButton
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class ButtonBarMiddleButtonSkin extends ButtonBarButtonSkinBase
+ {
+
+ /**
+ * Class to use for the border in the selected and down state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var selectedDownBorderSkin:Class;
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ButtonBarMiddleButtonSkin()
+ {
+ super();
+
+ upBorderSkin = spark.skins.android4.assets.ButtonBarMiddleButton_up;
+ downBorderSkin = spark.skins.android4.assets.ButtonBarMiddleButton_down;
+ selectedBorderSkin = spark.skins.android4.assets.ButtonBarMiddleButton_selectedUp;
+ selectedDownBorderSkin = spark.skins.android4.assets.ButtonBarMiddleButton_selectedDown;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ //Dont draw background
+ }
+
+ override protected function getBorderClassForCurrentState():Class
+ {
+ var isSelected:Boolean = currentState.indexOf("Selected") >= 0;
+ var isDown:Boolean = currentState.indexOf("down") >= 0;
+
+ if (isSelected && !isDown )
+ return selectedBorderSkin;
+ else if (isSelected && isDown)
+ return selectedDownBorderSkin;
+ else if (!isSelected && !isDown)
+ return upBorderSkin;
+ else
+ return downBorderSkin;
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarSkin.as
new file mode 100644
index 0000000000..4b194fdd74
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonBarSkin.as
@@ -0,0 +1,166 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.components.ButtonBar;
+import spark.components.ButtonBarButton;
+import spark.components.DataGroup;
+import spark.components.supportClasses.ButtonBarHorizontalLayout;
+import spark.skins.android4.ButtonBarFirstButtonSkin;
+import spark.skins.mobile.ButtonBarLastButtonSkin;
+import spark.skins.mobile.supportClasses.ButtonBarButtonClassFactory;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+/**
+ * The Android 4.x specific skin class for the Spark ButtonBar component.
+ *
+ * @see spark.components.ButtonBar
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ButtonBarSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function ButtonBarSkin()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:ButtonBar;
+
+ /**
+ * @copy spark.components.ButtonBar#firstButton
+ */
+ public var firstButton:ButtonBarButtonClassFactory;
+
+ /**
+ * @copy spark.components.ButtonBar#lastButton
+ */
+ public var lastButton:ButtonBarButtonClassFactory;
+
+ /**
+ * @copy spark.components.ButtonBar#middleButton
+ */
+ public var middleButton:ButtonBarButtonClassFactory;
+
+ /**
+ * @copy spark.components.SkinnableDataContainer#dataGroup
+ */
+ public var dataGroup:DataGroup;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Set up the class factories for the buttons
+ if (!firstButton)
+ {
+ firstButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ firstButton.skinClass = spark.skins.android4.ButtonBarFirstButtonSkin;
+ }
+
+ if (!lastButton)
+ {
+ lastButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ lastButton.skinClass = spark.skins.android4.ButtonBarFirstButtonSkin;
+ }
+
+ if (!middleButton)
+ {
+ middleButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ middleButton.skinClass = spark.skins.android4.ButtonBarMiddleButtonSkin;
+ }
+
+ // create the data group to house the buttons
+ if (!dataGroup)
+ {
+ dataGroup = new DataGroup();
+ var hLayout:ButtonBarHorizontalLayout = new ButtonBarHorizontalLayout();
+ hLayout.gap = 0;
+ dataGroup.layout = hLayout;
+ addChild(dataGroup);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ alpha = (currentState == "disabled") ? 0.5 : 1;
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = dataGroup.measuredWidth;
+ measuredHeight = dataGroup.measuredHeight;
+
+ measuredMinWidth = dataGroup.measuredMinWidth;
+ measuredMinHeight = dataGroup.measuredMinHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementPosition(dataGroup, 0, 0);
+ setElementSize(dataGroup, unscaledWidth, unscaledHeight);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonSkin.as
new file mode 100644
index 0000000000..43fb108c61
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ButtonSkin.as
@@ -0,0 +1,397 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+
+import spark.components.supportClasses.StyleableTextField;
+import spark.skins.android4.assets.Button_down;
+import spark.skins.android4.assets.Button_up;
+import spark.skins.mobile.supportClasses.ButtonSkinBase;
+
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for Button controls in mobile applications. The skin supports
+ * iconClass and labelPlacement. It uses FXG classes to
+ * implement the vector drawing.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ButtonSkin extends ButtonSkinBase
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * An array of color distribution ratios.
+ * This is used in the chrome color fill.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ mx_internal static const CHROME_COLOR_RATIOS:Array = [0, 127.5];
+
+ /**
+ * An array of alpha values for the corresponding colors in the colors array.
+ * This is used in the chrome color fill.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ mx_internal static const CHROME_COLOR_ALPHAS:Array = [1, 1];
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ButtonSkin()
+ {
+ super();
+ upBorderSkin = spark.skins.android4.assets.Button_up;
+ downBorderSkin = spark.skins.android4.assets.Button_down;
+ layoutCornerEllipseSize = 0;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ layoutGap = 20;
+ layoutPaddingLeft = 40;
+ layoutPaddingRight = 40;
+ layoutPaddingTop = 40;
+ layoutPaddingBottom = 40;
+ layoutBorderSize = 2;
+ measuredDefaultWidth = 128;
+ measuredDefaultHeight = 172;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ layoutGap = 14;
+ layoutPaddingLeft = 30;
+ layoutPaddingRight = 30;
+ layoutPaddingTop = 30;
+ layoutPaddingBottom = 30;
+ layoutBorderSize = 2;
+ measuredDefaultWidth = 96;
+ measuredDefaultHeight = 130;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ layoutGap = 10;
+ layoutPaddingLeft = 20;
+ layoutPaddingRight = 20;
+ layoutPaddingTop = 20;
+ layoutPaddingBottom = 20;
+ layoutBorderSize = 2;
+ measuredDefaultWidth = 64;
+ measuredDefaultHeight = 86;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+
+ layoutGap = 7;
+ layoutPaddingLeft = 15;
+ layoutPaddingRight = 15;
+ layoutPaddingTop = 15;
+ layoutPaddingBottom = 15;
+ layoutBorderSize = 1;
+ measuredDefaultWidth = 48;
+ measuredDefaultHeight = 65;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+
+ layoutGap = 4;
+ layoutPaddingLeft = 8;
+ layoutPaddingRight = 8;
+ layoutPaddingTop = 8;
+ layoutPaddingBottom = 8;
+ layoutBorderSize = 1;
+ measuredDefaultWidth = 24;
+ measuredDefaultHeight = 33;
+
+ break;
+ }
+ default:
+ {
+
+ layoutGap = 5;
+ layoutPaddingLeft = 10;
+ layoutPaddingRight = 10;
+ layoutPaddingTop = 10;
+ layoutPaddingBottom = 10;
+ layoutBorderSize = 1;
+ measuredDefaultWidth = 32;
+ measuredDefaultHeight = 43;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the corner radius.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var layoutCornerEllipseSize:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ private var _border:DisplayObject;
+
+ private var changeFXGSkin:Boolean = false;
+
+ private var borderClass:Class;
+
+ mx_internal var fillColorStyleName:String = "chromeColor";
+
+ /**
+ * Defines the shadow for the Button control's label.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var labelDisplayShadow:StyleableTextField;
+
+ /**
+ * Read-only button border graphic. Use getBorderClassForCurrentState()
+ * to specify a graphic per-state.
+ *
+ * @see #getBorderClassForCurrentState()
+ */
+ protected function get border():DisplayObject
+ {
+ return _border;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Class to use for the border in the up state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ * @default Button_up
+ */
+ protected var upBorderSkin:Class;
+
+ /**
+ * Class to use for the border in the down state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ * @default Button_down
+ */
+ protected var downBorderSkin:Class;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!labelDisplayShadow && labelDisplay)
+ {
+ labelDisplayShadow = StyleableTextField(createInFontContext(StyleableTextField));
+ labelDisplayShadow.styleName = this;
+ labelDisplayShadow.colorName = "textShadowColor";
+ labelDisplayShadow.useTightTextBounds = false;
+
+ // add shadow before display
+ addChildAt(labelDisplayShadow, getChildIndex(labelDisplay));
+ }
+
+ setStyle("textAlign", "center");
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ borderClass = getBorderClassForCurrentState();
+
+ if (!(_border is borderClass))
+ changeFXGSkin = true;
+
+ // update borderClass and background
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // size the FXG background
+ if (changeFXGSkin)
+ {
+ changeFXGSkin = false;
+
+ if (_border)
+ {
+ removeChild(_border);
+ _border = null;
+ }
+
+ if (borderClass)
+ {
+ _border = new borderClass();
+ addChildAt(_border, 0);
+ }
+ }
+
+ layoutBorder(unscaledWidth, unscaledHeight);
+
+ // update label shadow
+ labelDisplayShadow.alpha = getStyle("textShadowAlpha");
+ labelDisplayShadow.commitStyles();
+
+ // don't use tightText positioning on shadow
+ setElementPosition(labelDisplayShadow, labelDisplay.x, labelDisplay.y + 1);
+ setElementSize(labelDisplayShadow, labelDisplay.width, labelDisplay.height);
+
+ // if labelDisplay is truncated, then push it down here as well.
+ // otherwise, it would have gotten pushed in the labelDisplay_valueCommitHandler()
+ if (labelDisplay.isTruncated)
+ labelDisplayShadow.text = labelDisplay.text;
+ }
+
+ /**
+ * Position the background of the skin. Override this function to re-position the background.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ mx_internal function layoutBorder(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+
+ /**
+ * Returns the borderClass to use based on the currentState.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected function getBorderClassForCurrentState():Class
+ {
+ if (currentState == "down")
+ return downBorderSkin;
+ else
+ return upBorderSkin;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event Handlers
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function labelDisplay_valueCommitHandler(event:FlexEvent):void
+ {
+ super.labelDisplay_valueCommitHandler(event);
+ labelDisplayShadow.text = labelDisplay.text;
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/CalloutSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/CalloutSkin.as
new file mode 100644
index 0000000000..95fefef02c
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/CalloutSkin.as
@@ -0,0 +1,825 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.BlendMode;
+import flash.display.GradientType;
+import flash.display.Graphics;
+import flash.display.Sprite;
+import flash.events.Event;
+
+import mx.core.DPIClassification;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.events.EffectEvent;
+import mx.events.FlexEvent;
+import mx.utils.ColorUtil;
+
+import spark.components.ArrowDirection;
+import spark.components.Callout;
+import spark.components.ContentBackgroundAppearance;
+import spark.components.Group;
+import spark.core.SpriteVisualElement;
+import spark.effects.Fade;
+import spark.primitives.RectangularDropShadow;
+import spark.skins.android4.assets.CalloutContentBackground;
+import spark.skins.android4.supportClasses.CalloutArrow;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for the Spark Callout component in mobile
+ * applications.
+ *
+ *
The contentGroup lies above a backgroundColor fill
+ * which frames the contentGroup. The position and size of the frame
+ * adjust based on the host component arrowDirection, leaving
+ * space for the arrow to appear on the outside edge of the
+ * frame.
+ *
+ *
The arrow skin part is not positioned by the skin. Instead,
+ * the Callout component positions the arrow relative to the owner in
+ * updateSkinDisplayList(). This method assumes that Callout skin
+ * and the arrow use the same coordinate space.
+ *
+ * @see spark.components.Callout
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+public class CalloutSkin extends MobileSkin
+{
+ mx_internal static const BACKGROUND_GRADIENT_BRIGHTNESS_TOP:int = 15;
+
+ mx_internal static const BACKGROUND_GRADIENT_BRIGHTNESS_BOTTOM:int = -15;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public function CalloutSkin()
+ {
+ super();
+
+ dropShadowAlpha = 0.7;
+ contentBackgroundInsetClass = spark.skins.android4.assets.CalloutContentBackground;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ backgroundCornerRadius = 24;
+ backgroundGradientHeight = 440;
+ frameThickness = 12;
+ arrowWidth = 160;
+ arrowHeight = 80;
+ contentCornerRadius = 40;
+ dropShadowBlurX = 64;
+ dropShadowBlurY = 64;
+ dropShadowDistance = 12;
+ highlightWeight = 4;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ backgroundCornerRadius = 16;
+ backgroundGradientHeight = 330;
+ frameThickness = 8;
+ arrowWidth = 120;
+ arrowHeight = 60;
+ contentCornerRadius = 28;
+ dropShadowBlurX = 48;
+ dropShadowBlurY = 48;
+ dropShadowDistance = 8;
+ highlightWeight = 2;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ backgroundCornerRadius = 12;
+ backgroundGradientHeight = 220;
+ frameThickness = 6;
+ arrowWidth = 80;
+ arrowHeight = 40;
+ contentCornerRadius = 20;
+ dropShadowBlurX = 32;
+ dropShadowBlurY = 32;
+ dropShadowDistance = 6;
+ highlightWeight = 2;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ backgroundCornerRadius = 8;
+ backgroundGradientHeight = 165;
+ frameThickness = 4;
+ arrowWidth = 60;
+ arrowHeight = 30;
+ contentCornerRadius = 14;
+ dropShadowBlurX = 24;
+ dropShadowBlurY = 24;
+ dropShadowDistance = 4;
+ highlightWeight = 1;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ backgroundCornerRadius = 4;
+ backgroundGradientHeight = 83;
+ frameThickness = 2;
+ arrowWidth = 30;
+ arrowHeight = 15;
+ contentCornerRadius = 7;
+ dropShadowBlurX = 12;
+ dropShadowBlurY = 12;
+ dropShadowDistance = 2;
+ highlightWeight = 0.5;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ backgroundCornerRadius = 6;
+ backgroundGradientHeight = 110;
+ frameThickness = 3;
+ arrowWidth = 40;
+ arrowHeight = 20;
+ contentCornerRadius = 10;
+ dropShadowBlurX = 16;
+ dropShadowBlurY = 16;
+ dropShadowDistance = 3;
+ highlightWeight = 1;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Callout;
+
+ /**
+ * Enables a RectangularDropShadow behind the backgroundColor frame.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var dropShadowVisible:Boolean = true;
+
+ /**
+ * Enables a vertical linear gradient in the backgroundColor frame. This
+ * gradient fill is drawn across both the arrow and the frame. By default,
+ * the gradient brightens the background color by 15% and darkens it by 60%.
+ *
+ * @default true
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var useBackgroundGradient:Boolean = true;
+
+ /**
+ * Corner radius used for the contentBackgroundColor fill.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var contentCornerRadius:uint;
+
+ /**
+ * A class reference to an FXG class that is layered underneath the
+ * contentGroup. The instance of this class is sized to match the
+ * contentGroup.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var contentBackgroundInsetClass:Class;
+
+ /**
+ * Corner radius of the backgroundColor "frame".
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var backgroundCornerRadius:Number;
+
+ /**
+ * The thickness of the backgroundColor "frame" that surrounds the
+ * contentGroup.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var frameThickness:Number;
+
+ /**
+ * Color of the border stroke around the backgroundColor "frame".
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderColor:Number = -1; // not set
+
+ /**
+ * Thickness of the border stroke around the backgroundColor
+ * "frame".
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderThickness:Number = -1 ; // marker that borderThickness was not set directly
+
+ /**
+ * Width of the arrow in vertical directions. This property also controls
+ * the height of the arrow in horizontal directions.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var arrowWidth:Number;
+
+ /**
+ * Height of the arrow in vertical directions. This property also controls
+ * the width of the arrow in horizontal directions.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var arrowHeight:Number;
+
+ /**
+ * @private
+ * Instance of the contentBackgroundClass
+ */
+ mx_internal var contentBackgroundGraphic:SpriteVisualElement;
+
+ /**
+ * @private
+ * Tracks changes to the skin state to support the fade out tranisition
+ * when closed;
+ */
+ mx_internal var isOpen:Boolean;
+
+ private var backgroundGradientHeight:Number;
+
+ private var contentMask:Sprite;
+
+ private var backgroundFill:SpriteVisualElement;
+
+ private var dropShadow:RectangularDropShadow;
+
+ private var dropShadowBlurX:Number;
+
+ private var dropShadowBlurY:Number;
+
+ private var dropShadowDistance:Number;
+
+ private var dropShadowAlpha:Number;
+
+ private var fade:Fade;
+
+ private var highlightWeight:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.components.SkinnableContainer#contentGroup
+ */
+ public var contentGroup:Group;
+
+ /**
+ * @copy spark.components.Callout#arrow
+ */
+ public var arrow:UIComponent;
+
+ /* helper private accessors */
+
+ /* returns borderThickness from style if member is -1, or borderThickness. Returns 0 if NaN */
+ mx_internal function get actualBorderThickness():Number
+ {
+ var border: Number = borderThickness != -1 ? borderThickness : getStyle('borderThickness');
+ return isNaN(border)? 0: border;
+ }
+
+ mx_internal function get actualBorderColor():uint
+ {
+ return borderColor != -1 ? borderColor: getStyle('borderColor');
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (dropShadowVisible)
+ {
+ dropShadow = new RectangularDropShadow();
+ dropShadow.angle = 90;
+ dropShadow.distance = dropShadowDistance;
+ dropShadow.blurX = dropShadowBlurX;
+ dropShadow.blurY = dropShadowBlurY;
+ dropShadow.tlRadius = dropShadow.trRadius = dropShadow.blRadius =
+ dropShadow.brRadius = backgroundCornerRadius ;
+ dropShadow.mouseEnabled = false;
+ dropShadow.alpha = dropShadowAlpha;
+ addChild(dropShadow);
+ }
+
+ // background fill placed above the drop shadow
+ backgroundFill = new SpriteVisualElement();
+ addChild(backgroundFill);
+
+ // arrow
+ if (!arrow)
+ {
+ arrow = new CalloutArrow();
+ arrow.id = "arrow";
+ arrow.styleName = this;
+ addChild(arrow);
+ }
+
+ // contentGroup
+ if (!contentGroup)
+ {
+ contentGroup = new Group();
+ contentGroup.id = "contentGroup";
+ addChild(contentGroup);
+ }
+
+
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitProperties():void
+ {
+ super.commitProperties();
+
+ // add or remove the contentBackgroundGraphic
+ var contentBackgroundAppearance:String = getStyle("contentBackgroundAppearance");
+
+ if (contentBackgroundAppearance == ContentBackgroundAppearance.INSET)
+ {
+ // create the contentBackgroundGraphic
+ if (!contentBackgroundGraphic && contentBackgroundInsetClass)
+ {
+ contentBackgroundGraphic = new contentBackgroundInsetClass() as SpriteVisualElement;
+
+ // with the current skin structure, contentBackgroundGraphic is
+ // always the last child
+ addChild(contentBackgroundGraphic);
+ }
+ }
+ else if (contentBackgroundGraphic)
+ {
+ // if already created, remove the graphic for "flat" and "none"
+ removeChild(contentBackgroundGraphic);
+ contentBackgroundGraphic = null;
+ }
+
+ // always invalidate to accomodate arrow direction changes
+ invalidateSize();
+ invalidateDisplayList();
+ }
+
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var borderWeight:Number =actualBorderThickness;
+ var frameAdjustment:Number = (frameThickness + borderWeight) * 2;
+
+ var arrowMeasuredWidth:Number;
+ var arrowMeasuredHeight:Number;
+
+ // pad the arrow so that the edges are within the background corner radius
+ if (isArrowHorizontal)
+ {
+ arrowMeasuredWidth = arrowHeight;
+ arrowMeasuredHeight = arrowWidth + (backgroundCornerRadius * 2);
+ }
+ else if (isArrowVertical)
+ {
+ arrowMeasuredWidth = arrowWidth + (backgroundCornerRadius * 2);
+ arrowMeasuredHeight = arrowHeight;
+ }
+
+ // count the contentGroup size and frame size
+ measuredMinWidth = contentGroup.measuredMinWidth + frameAdjustment;
+ measuredMinHeight = contentGroup.measuredMinHeight + frameAdjustment;
+
+ measuredWidth = contentGroup.getPreferredBoundsWidth() + frameAdjustment;
+ measuredHeight = contentGroup.getPreferredBoundsHeight() + frameAdjustment;
+
+ // add the arrow size based on the arrowDirection
+ if (isArrowHorizontal)
+ {
+ measuredMinWidth += arrowMeasuredWidth;
+ measuredMinHeight = Math.max(measuredMinHeight, arrowMeasuredHeight);
+
+ measuredWidth += arrowMeasuredWidth;
+ measuredHeight = Math.max(measuredHeight, arrowMeasuredHeight);
+ }
+ else if (isArrowVertical)
+ {
+ measuredMinWidth += Math.max(measuredMinWidth, arrowMeasuredWidth);
+ measuredMinHeight += arrowMeasuredHeight;
+
+ measuredWidth = Math.max(measuredWidth, arrowMeasuredWidth);
+ measuredHeight += arrowMeasuredHeight;
+ }
+ }
+
+ /**
+ * @private
+ * SkinnaablePopUpContainer skins must dispatch a
+ * FlexEvent.STATE_CHANGE_COMPLETE event for the component to properly
+ * update the skin state.
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ var isNormal:Boolean = (currentState == "normal");
+ var isDisabled:Boolean = (currentState == "disabled")
+
+ // play a fade out if the callout was previously open
+ if (!(isNormal || isDisabled) && isOpen)
+ {
+ if (!fade)
+ {
+ fade = new Fade();
+ fade.target = this;
+ fade.duration = 200;
+ fade.alphaTo = 0;
+ }
+
+ // BlendMode.LAYER while fading out
+ blendMode = BlendMode.LAYER;
+
+ // play a short fade effect
+ fade.addEventListener(EffectEvent.EFFECT_END, stateChangeComplete);
+ fade.play();
+
+ isOpen = false;
+ }
+ else
+ {
+ isOpen = isNormal || isDisabled;
+
+ // handle re-opening the Callout while fading out
+ if (fade && fade.isPlaying)
+ {
+ // Do not dispatch a state change complete.
+ // SkinnablePopUpContainer handles state interruptions.
+ fade.removeEventListener(EffectEvent.EFFECT_END, stateChangeComplete);
+ fade.stop();
+ }
+
+ if (isDisabled)
+ {
+ // BlendMode.LAYER to allow CalloutArrow BlendMode.ERASE
+ blendMode = BlendMode.LAYER;
+
+ alpha = 0.5;
+ }
+ else
+ {
+ // BlendMode.NORMAL for non-animated state transitions
+ blendMode = BlendMode.NORMAL;
+
+ if (isNormal)
+ alpha = 1;
+ else
+ alpha = 0;
+ }
+
+ stateChangeComplete();
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var frameEllipseSize:Number = backgroundCornerRadius * 2;
+
+ // account for borderThickness center stroke alignment
+ var borderWeight:Number =actualBorderThickness;
+ var showBorder:Boolean = borderWeight > 0 ;
+
+
+ // contentBackgroundGraphic already accounts for the arrow position
+ // use it's positioning instead of recalculating based on unscaledWidth
+ // and unscaledHeight
+ var frameX:Number = Math.floor(contentGroup.getLayoutBoundsX() - frameThickness) - (borderWeight / 2);
+ var frameY:Number = Math.floor(contentGroup.getLayoutBoundsY() - frameThickness) - (borderWeight / 2);
+ var frameWidth:Number = contentGroup.getLayoutBoundsWidth() + (frameThickness * 2) + borderWeight;
+ var frameHeight:Number = contentGroup.getLayoutBoundsHeight() + (frameThickness * 2) + borderWeight;
+
+ var backgroundColor:Number = getStyle("primaryAccentColor");
+ var backgroundAlpha:Number = getStyle("backgroundAlpha");
+
+ var bgFill:Graphics = backgroundFill.graphics;
+ bgFill.clear();
+
+ if (showBorder)
+ bgFill.lineStyle(borderWeight, actualBorderColor, 1, true);
+
+ if (useBackgroundGradient)
+ {
+ // top color is brighter if arrowDirection == ArrowDirection.UP
+ var backgroundColorTop:Number = ColorUtil.adjustBrightness2(backgroundColor,
+ BACKGROUND_GRADIENT_BRIGHTNESS_TOP);
+ var backgroundColorBottom:Number = ColorUtil.adjustBrightness2(backgroundColor,
+ BACKGROUND_GRADIENT_BRIGHTNESS_BOTTOM);
+
+ // max gradient height = backgroundGradientHeight
+ colorMatrix.createGradientBox(unscaledWidth, backgroundGradientHeight,
+ Math.PI / 2, 0, 0);
+
+ bgFill.beginGradientFill(GradientType.LINEAR,
+ [backgroundColorTop, backgroundColorBottom],
+ [backgroundAlpha, backgroundAlpha],
+ [0, 255],
+ colorMatrix);
+ }
+ else
+ {
+ bgFill.beginFill(backgroundColor, backgroundAlpha);
+ }
+
+ bgFill.drawRoundRect(frameX, frameY, frameWidth,
+ frameHeight, frameEllipseSize, frameEllipseSize);
+ bgFill.endFill();
+
+ // draw content background styles
+ var contentBackgroundAppearance:String = getStyle("contentBackgroundAppearance");
+
+ if (contentBackgroundAppearance != ContentBackgroundAppearance.NONE)
+ {
+ var contentEllipseSize:Number = contentCornerRadius * 2;
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ var contentWidth:Number = contentGroup.getLayoutBoundsWidth();
+ var contentHeight:Number = contentGroup.getLayoutBoundsHeight();
+
+ // all appearance values except for "none" use a mask
+ if (!contentMask)
+ contentMask = new SpriteVisualElement();
+
+ contentGroup.mask = contentMask;
+
+ // draw contentMask in contentGroup coordinate space
+ var maskGraphics:Graphics = contentMask.graphics;
+ maskGraphics.clear();
+ maskGraphics.beginFill(0, 1);
+ maskGraphics.drawRoundRect(0, 0, contentWidth, contentHeight,
+ contentEllipseSize, contentEllipseSize);
+ maskGraphics.endFill();
+
+ // reset line style to none
+ if (showBorder)
+ bgFill.lineStyle(NaN);
+
+ // draw the contentBackgroundColor
+ bgFill.beginFill(getStyle("contentBackgroundColor"),
+ contentBackgroundAlpha);
+ bgFill.drawRoundRect(contentGroup.getLayoutBoundsX(),
+ contentGroup.getLayoutBoundsY(),
+ contentWidth, contentHeight, contentEllipseSize, contentEllipseSize);
+ bgFill.endFill();
+
+ if (contentBackgroundGraphic)
+ contentBackgroundGraphic.alpha = contentBackgroundAlpha;
+ }
+ else // if (contentBackgroundAppearance == CalloutContentBackgroundAppearance.NONE))
+ {
+ // remove the mask
+ if (contentMask)
+ {
+ contentGroup.mask = null;
+ contentMask = null;
+ }
+ }
+
+ // draw highlight in the callout when the arrow is hidden
+ if (useBackgroundGradient && !isArrowHorizontal && !isArrowVertical)
+ {
+ // highlight width spans the callout width minus the corner radius
+ var highlightWidth:Number = frameWidth - frameEllipseSize;
+ var highlightX:Number = frameX + backgroundCornerRadius;
+ var highlightOffset:Number = (highlightWeight * 1.5);
+
+ // straight line across the top
+ bgFill.lineStyle(highlightWeight, 0xFFFFFF, 0.2 * backgroundAlpha);
+ bgFill.moveTo(highlightX, highlightOffset);
+ bgFill.lineTo(highlightX + highlightWidth, highlightOffset);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // pad the arrow so that the edges are within the background corner radius
+ if (isArrowHorizontal)
+ {
+ arrow.width = arrowHeight;
+ arrow.height = arrowWidth + (backgroundCornerRadius * 2);
+ }
+ else if (isArrowVertical)
+ {
+ arrow.width = arrowWidth + (backgroundCornerRadius * 2);
+ arrow.height = arrowHeight;
+ }
+
+ setElementSize(backgroundFill, unscaledWidth, unscaledHeight);
+ setElementPosition(backgroundFill, 0, 0);
+
+ var frameX:Number = 0;
+ var frameY:Number = 0;
+ var frameWidth:Number = unscaledWidth;
+ var frameHeight:Number = unscaledHeight;
+
+ switch (hostComponent.arrowDirection)
+ {
+ case ArrowDirection.UP:
+ frameY = arrow.height;
+ frameHeight -= arrow.height;
+ break;
+ case ArrowDirection.DOWN:
+ frameHeight -= arrow.height;
+ break;
+ case ArrowDirection.LEFT:
+ frameX = arrow.width;
+ frameWidth -= arrow.width;
+ break;
+ case ArrowDirection.RIGHT:
+ frameWidth -= arrow.width;
+ break;
+ default:
+ // no arrow, content takes all available space
+ break;
+ }
+
+ if (dropShadow)
+ {
+ setElementSize(dropShadow, frameWidth, frameHeight);
+ setElementPosition(dropShadow, frameX, frameY);
+ }
+
+ // Show frameThickness by inset of contentGroup
+ var borderWeight:Number = actualBorderThickness;
+ var contentBackgroundAdjustment:Number = frameThickness + borderWeight;
+
+ var contentBackgroundX:Number = frameX + contentBackgroundAdjustment;
+ var contentBackgroundY:Number = frameY + contentBackgroundAdjustment;
+
+ contentBackgroundAdjustment = contentBackgroundAdjustment * 2;
+ var contentBackgroundWidth:Number = frameWidth - contentBackgroundAdjustment;
+ var contentBackgroundHeight:Number = frameHeight - contentBackgroundAdjustment;
+
+ if (contentBackgroundGraphic)
+ {
+ setElementSize(contentBackgroundGraphic, contentBackgroundWidth, contentBackgroundHeight);
+ setElementPosition(contentBackgroundGraphic, contentBackgroundX, contentBackgroundY);
+ }
+
+ setElementSize(contentGroup, contentBackgroundWidth, contentBackgroundHeight);
+ setElementPosition(contentGroup, contentBackgroundX, contentBackgroundY);
+
+ // mask position is in the contentGroup coordinate space
+ if (contentMask)
+ setElementSize(contentMask, contentBackgroundWidth, contentBackgroundHeight);
+ }
+
+ override public function styleChanged(styleProp:String):void
+ {
+ super.styleChanged(styleProp);
+
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || (styleProp == "contentBackgroundAppearance"))
+ invalidateProperties();
+
+ if (allStyles || (styleProp == "backgroundAlpha"))
+ {
+ var backgroundAlpha:Number = getStyle("backgroundAlpha");
+
+ // Use BlendMode.LAYER to allow CalloutArrow to erase the dropShadow
+ // when the Callout background is transparent
+ blendMode = (backgroundAlpha < 1) ? BlendMode.LAYER : BlendMode.NORMAL;
+ }
+ }
+
+ /**
+ * @private
+ */
+ mx_internal function get isArrowHorizontal():Boolean
+ {
+ return (hostComponent.arrowDirection == ArrowDirection.LEFT
+ || hostComponent.arrowDirection == ArrowDirection.RIGHT);
+ }
+
+ /**
+ * @private
+ */
+ mx_internal function get isArrowVertical():Boolean
+ {
+ return (hostComponent.arrowDirection == ArrowDirection.UP
+ || hostComponent.arrowDirection == ArrowDirection.DOWN);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event handlers
+ //
+ //--------------------------------------------------------------------------
+
+ private function stateChangeComplete(event:Event=null):void
+ {
+ if (fade && event)
+ fade.removeEventListener(EffectEvent.EFFECT_END, stateChangeComplete);
+
+ // SkinnablePopUpContainer relies on state changes for open and close
+ dispatchEvent(new FlexEvent(FlexEvent.STATE_CHANGE_COMPLETE));
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/CheckBoxSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/CheckBoxSkin.as
new file mode 100644
index 0000000000..f091205bc4
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/CheckBoxSkin.as
@@ -0,0 +1,268 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+ import spark.skins.android4.assets.CheckBox_up;
+ import spark.skins.mobile.supportClasses.SelectableButtonSkinBase;
+
+ /**
+ * ActionScript-based skin for CheckBox components in mobile applications.
+ *
+ * @see spark.components.CheckBox
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class CheckBoxSkin extends SelectableButtonSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ private static const exclusions:Array = ["labelDisplay", "labelDisplayShadow"];
+
+ //--------------------------------------------------------------------------
+ //
+ // Member variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var symbolOffsetX:Number;
+ protected var symbolOffsetY:Number;
+ protected var iconWidth:Number;
+ protected var iconHeight:Number;
+ protected var symbolWidth:Number;
+ protected var symbolHeight:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function CheckBoxSkin()
+ {
+ super();
+
+ layoutPaddingLeft = 0;
+ layoutPaddingRight = 0;
+ layoutPaddingTop = 0;
+ layoutPaddingBottom = 0;
+
+ upIconClass = spark.skins.android4.assets.CheckBox_up;
+ upSelectedIconClass = spark.skins.android4.assets.CheckBox_upSelected;
+ downIconClass = spark.skins.android4.assets.CheckBox_down;
+ downSelectedIconClass = spark.skins.android4.assets.CheckBox_downSelected;
+ upSymbolIconClass = null;
+ upSymbolIconSelectedClass = spark.skins.android4.assets.CheckBox_upSymbolSelected;
+ downSymbolIconSelectedClass = spark.skins.android4.assets.CheckBox_downSymbolSelected;
+ downSymbolIconClass = null;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ layoutGap = 16;
+ minWidth = 128;
+ minHeight = 128;
+ layoutBorderSize = 6;
+ iconWidth = 128;
+ iconHeight = 128;
+ symbolWidth = 64;
+ symbolHeight = 64;
+ symbolOffsetX = 32;
+ symbolOffsetY = 32;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ layoutGap = 12;
+ minWidth = 96;
+ minHeight = 96;
+ layoutBorderSize = 4;
+ iconWidth = 96;
+ iconHeight = 96;
+ symbolWidth = 48;
+ symbolHeight = 48;
+ symbolOffsetX = 24;
+ symbolOffsetY = 24;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ layoutGap = 8;
+ minWidth = 64;
+ minHeight = 64;
+ layoutBorderSize = 3;
+ iconWidth = 64;
+ iconHeight = 64;
+ symbolWidth = 32;
+ symbolHeight = 32;
+ symbolOffsetX = 16;
+ symbolOffsetY = 16;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+
+ layoutGap = 6;
+ minWidth = 48;
+ minHeight = 48;
+ layoutBorderSize = 2;
+ iconWidth = 48;
+ iconHeight = 48;
+ symbolWidth = 24;
+ symbolHeight = 24;
+ symbolOffsetX = 12;
+ symbolOffsetY = 12;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+
+ layoutGap = 3;
+ minWidth = 24;
+ minHeight = 24;
+ layoutBorderSize = 1;
+ iconWidth = 24;
+ iconHeight = 24;
+ symbolWidth = 12;
+ symbolHeight = 12;
+ symbolOffsetX = 6;
+ symbolOffsetY = 6;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+
+ layoutGap = 4;
+ minWidth = 32;
+ minHeight = 32;
+ layoutBorderSize = 2;
+ iconWidth = 32;
+ iconHeight = 32;
+ symbolWidth = 16;
+ symbolHeight = 16;
+ symbolOffsetX = 8;
+ symbolOffsetY = 8;
+
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * CheckBox chromeColor is drawn to match the FXG rectangle
+ * shape and position.
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // super draws a transparent hit zone
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ // get the size and position of iconDisplay
+ var currentIcon:DisplayObject = getIconDisplay();
+ var widthAdjustment:Number = layoutBorderSize * 2;
+
+ graphics.beginFill(getStyle("chromeColor"));
+ graphics.drawRoundRect(currentIcon.x + layoutBorderSize,
+ currentIcon.y + layoutBorderSize,
+ currentIcon.width - widthAdjustment,
+ currentIcon.height - widthAdjustment, layoutBorderSize, layoutBorderSize);
+ graphics.endFill();
+ }
+
+ /**
+ * List of IDs of items that should be excluded when rendering the focus ring.
+ * Only items of type DisplayObject or GraphicElement should be excluded. Items
+ * of other types are ignored.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ override protected function get focusSkinExclusions():Array
+ {
+ return exclusions;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+ if(symbolIcon != null)
+ {
+ symbolIcon.width = symbolWidth;
+ symbolIcon.height = symbolHeight;
+ }
+ var iconDisplay:DisplayObject = getIconDisplay();
+ if(iconDisplay != null)
+ {
+ iconDisplay.width = iconWidth;
+ iconDisplay.height = iconHeight;
+ }
+ }
+
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+ // position the symbols to align with the background "icon"
+ if (symbolIcon)
+ {
+ var currentIcon:DisplayObject = getIconDisplay();
+ setElementPosition(symbolIcon, symbolOffsetX, symbolOffsetY);
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/HScrollBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/HScrollBarSkin.as
new file mode 100644
index 0000000000..1e712793fd
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/HScrollBarSkin.as
@@ -0,0 +1,205 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.Button;
+import spark.components.HScrollBar;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for HScrollBar components in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class HScrollBarSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function HScrollBarSkin()
+ {
+ super();
+
+ minWidth = 20;
+ thumbSkinClass = HScrollBarThumbSkin;
+ var paddingBottom:int;
+ var paddingHorizontal:int;
+
+ // Depending on density set our measured height
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ minHeight = 24;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_640DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ minHeight = 18;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_480DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ minHeight = 12;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_320DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ minHeight = 9;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_240DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ minHeight = 5;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_120DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_120DPI;
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ minHeight = 6;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_DEFAULTDPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_DEFAULTDPI;
+ break;
+ }
+ }
+
+ // The minimum width is set such that, at it's smallest size, the thumb appears
+ // as wide as it is high.
+ minThumbWidth = (minHeight - paddingBottom) + (paddingHorizontal * 2);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:HScrollBar;
+
+ /**
+ * Minimum width for the thumb
+ */
+ protected var minThumbWidth:Number;
+
+ /**
+ * Skin to use for the thumb Button skin part
+ */
+ protected var thumbSkinClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * HScrollbar track skin part.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var track:Button;
+
+ /**
+ * HScrollbar thumb skin part.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var thumb:Button;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Create our skin parts if necessary: track and thumb.
+ if (!track)
+ {
+ // We don't want a visible track so we set the skin to MobileSkin
+ track = new Button();
+ track.setStyle("skinClass", spark.skins.mobile.supportClasses.MobileSkin);
+ track.width = minWidth;
+ track.height = minHeight;
+ addChild(track);
+ }
+
+ if (!thumb)
+ {
+ thumb = new Button();
+ thumb.minWidth = minThumbWidth;
+ thumb.setStyle("skinClass", thumbSkinClass);
+ thumb.width = minHeight;
+ thumb.height = minHeight;
+ addChild(thumb);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(track, unscaledWidth, unscaledHeight);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/HScrollBarThumbSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/HScrollBarThumbSkin.as
new file mode 100644
index 0000000000..a96e4e4863
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/HScrollBarThumbSkin.as
@@ -0,0 +1,177 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.Button;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for the HScrollBar thumb skin part in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class HScrollBarThumbSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ // These constants are also accessed from HScrollBarSkin
+ mx_internal static const PADDING_BOTTOM_640DPI:int = 10;
+ mx_internal static const PADDING_HORIZONTAL_640DPI:int = 8;
+ mx_internal static const PADDING_BOTTOM_480DPI:int = 8;
+ mx_internal static const PADDING_HORIZONTAL_480DPI:int = 6;
+ mx_internal static const PADDING_BOTTOM_320DPI:int = 5;
+ mx_internal static const PADDING_HORIZONTAL_320DPI:int = 4;
+ mx_internal static const PADDING_BOTTOM_240DPI:int = 4;
+ mx_internal static const PADDING_HORIZONTAL_240DPI:int = 3;
+ mx_internal static const PADDING_BOTTOM_120DPI:int = 2;
+ mx_internal static const PADDING_HORIZONTAL_120DPI:int = 2;
+ mx_internal static const PADDING_BOTTOM_DEFAULTDPI:int = 3;
+ mx_internal static const PADDING_HORIZONTAL_DEFAULTDPI:int = 2;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function HScrollBarThumbSkin()
+ {
+ super();
+
+ // Depending on density set padding
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ paddingBottom = PADDING_BOTTOM_640DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ paddingBottom = PADDING_BOTTOM_480DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ paddingBottom = PADDING_BOTTOM_320DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ paddingBottom = PADDING_BOTTOM_240DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ paddingBottom = PADDING_BOTTOM_120DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_120DPI;
+ break;
+ }
+ default:
+ {
+ paddingBottom = PADDING_BOTTOM_DEFAULTDPI;
+ paddingHorizontal = PADDING_HORIZONTAL_DEFAULTDPI;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Padding from bottom.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingBottom:int;
+
+ /**
+ * Horizontal padding from left and right.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingHorizontal:int;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var thumbHeight:Number = unscaledHeight - paddingBottom;
+
+ graphics.beginFill(getStyle("color"), 1);
+ graphics.drawRect(paddingHorizontal + .5, 0.5, unscaledWidth - 2 * paddingHorizontal, thumbHeight);
+
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as
new file mode 100644
index 0000000000..c9f696bd26
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderSkin.as
@@ -0,0 +1,300 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.BlendMode;
+ import flash.display.DisplayObject;
+ import flash.events.Event;
+
+ import mx.core.ClassFactory;
+ import mx.core.IFactory;
+ import mx.events.FlexEvent;
+
+ import spark.components.Button;
+ import spark.components.HSlider;
+ import spark.skins.android4.assets.HSliderTrack_filled;
+ import spark.skins.mobile.supportClasses.HSliderDataTip;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ /**
+ * Android 4.x specific ActionScript-based skin for HSlider controls in mobile applications.
+ *
+ *
The base Flex implementation creates an HSlider with fixed height
+ * and variable width with a fixed-size thumb. As the height of the
+ * HSlider component increases, the vertical dimensions of the visible HSlider remain
+ * the same, and the HSlider stays vertically centered.
+ *
+ *
The thumb and track implementations can be customized by subclassing
+ * this skin class and overriding the thumbSkinClass, trackSkinClass,
+ * and/or dataTipClass variables as necessary.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class HSliderSkin extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function HSliderSkin()
+ {
+ super();
+
+ thumbSkinClass = spark.skins.android4.HSliderThumbSkin;
+ trackSkinClass = spark.skins.android4.HSliderTrackSkin;
+ filledTrackSkinClass = spark.skins.android4.assets.HSliderTrack_filled;
+ dataTipClass = spark.skins.mobile.supportClasses.HSliderDataTip;
+
+ blendMode = BlendMode.LAYER;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ private var _hostComponent:HSlider;
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public function get hostComponent():HSlider
+ {
+ return _hostComponent;
+ }
+
+ public function set hostComponent(value:HSlider):void
+ {
+ if (_hostComponent)
+ {
+ _hostComponent.removeEventListener(Event.CHANGE, thumbPositionChanged_handler);
+ _hostComponent.removeEventListener(FlexEvent.VALUE_COMMIT, thumbPositionChanged_handler);
+ }
+ _hostComponent = value;
+ if (_hostComponent)
+ {
+ _hostComponent.addEventListener(Event.CHANGE, thumbPositionChanged_handler);
+ _hostComponent.addEventListener(FlexEvent.VALUE_COMMIT, thumbPositionChanged_handler);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * HSlider track skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var track:Button;
+
+ /**
+ * HSlider track skin part that
+ * depicts area that is filled
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var filledTrack:DisplayObject;
+
+ /**
+ * HSlider thumb skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var thumb:Button;
+
+ /**
+ * HSlider dataTip class factory
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var dataTip:IFactory;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Specifies the skin class that will be used for the HSlider thumb.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbSkinClass:Class;
+
+ /**
+ * Specifies the skin class that will be used for the HSlider track.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackSkinClass:Class;
+ /**
+ * Specifies the skin class that will be used for the HSlider track's
+ * filled area.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var filledTrackSkinClass:Class;
+
+ /**
+ * Specifies the class that will be used for the HSlider datatip.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var dataTipClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ if (currentState == "disabled")
+ alpha = 0.5;
+ else if (currentState == "normal")
+ alpha = 1;
+ }
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Create our skin parts: track and thumb
+ track = new Button();
+ track.setStyle("skinClass", trackSkinClass);
+ addChild(track);
+
+ filledTrack = new filledTrackSkinClass();
+ addChild(filledTrack);
+
+ thumb = new Button();
+ thumb.setStyle("skinClass", thumbSkinClass);
+ addChild(thumb);
+
+ // Set up the class factory for the dataTip
+ dataTip = new ClassFactory();
+ ClassFactory(dataTip).generator = dataTipClass;
+ }
+
+ /**
+ * @private
+ * The HSliderSkin width will be no less than the width of the thumb skin.
+ * The HSliderSkin height will be no less than the greater of the heights of
+ * the thumb and track skins.
+ */
+ override protected function measure():void
+ {
+ measuredWidth = track.getPreferredBoundsWidth();
+ measuredHeight = Math.max(track.getPreferredBoundsHeight(), thumb.getPreferredBoundsHeight());
+
+ measuredMinHeight = Math.max(track.getPreferredBoundsHeight(), thumb.getPreferredBoundsHeight());
+ measuredMinWidth = thumb.getPreferredBoundsWidth();
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // minimum height is no smaller than the larger of the thumb or track
+ var calculatedSkinHeight:int = Math.max(Math.max(thumb.getPreferredBoundsHeight(), track.getPreferredBoundsHeight()),
+ unscaledHeight);
+
+ // minimum width is no smaller than the thumb
+ var calculatedSkinWidth:int = Math.max(thumb.getPreferredBoundsWidth(),
+ unscaledWidth);
+
+ // once we know the skin height, center the thumb and track
+ thumb.y = Math.max(Math.round((calculatedSkinHeight - thumb.getPreferredBoundsHeight()) / 2), 0);
+ var calculatedTrackY:int = Math.max(Math.round((calculatedSkinHeight - track.getPreferredBoundsHeight()) / 2), 0);
+
+ // size and position
+ setElementSize(thumb, thumb.getPreferredBoundsWidth(), thumb.getPreferredBoundsHeight()); // thumb does NOT scale
+ setElementSize(track, calculatedSkinWidth, track.getPreferredBoundsHeight()); // note track is NOT scaled vertically
+ setElementPosition(track, 0, calculatedTrackY);
+
+ //Set size and position of filled area based on thumb's current location
+ var filledTrackWidth:Number = thumb.getLayoutBoundsX();
+ setElementSize(filledTrack, filledTrackWidth, track.getPreferredBoundsHeight()); // note track is NOT scaled vertically
+ setElementPosition(filledTrack, track.x + HSliderTrackSkin(track.skin).visibleTrackOffset , calculatedTrackY);
+ }
+
+ private function thumbPositionChanged_handler(event:Event):void
+ {
+ //Just trigger a redraw so that the filled area of the track updates itself
+ invalidateDisplayList();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderThumbSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderThumbSkin.as
new file mode 100644
index 0000000000..517ff930fb
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderThumbSkin.as
@@ -0,0 +1,333 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+import spark.components.Button;
+import spark.skins.android4.assets.HSliderThumb_normal;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+/**
+ * Android 4.x specific ActionScript-based skin for the HSlider thumb skin part in mobile applications.
+ *
+ *
Note that this particular implementation defines a hit zone which is larger than
+ * the visible thumb for better usability on mobile screens.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class HSliderThumbSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function HSliderThumbSkin()
+ {
+ super();
+
+ thumbNormalClass = spark.skins.android4.assets.HSliderThumb_normal;
+ thumbPressedClass = spark.skins.android4.assets.HSliderThumb_pressed;
+
+ // set the dimensions to use based on the screen density
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ thumbImageWidth = 116;
+ thumbImageHeight = 116;
+
+ hitZoneOffset = 20;
+ hitZoneSideLength = 160;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ // Note provisional may need changes
+ thumbImageWidth = 88;
+ thumbImageHeight = 88;
+
+ hitZoneOffset = 20;
+ hitZoneSideLength = 130;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ thumbImageWidth = 58;
+ thumbImageHeight = 58;
+
+ hitZoneOffset = 10;
+ hitZoneSideLength = 80;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ thumbImageWidth = 44;
+ thumbImageHeight = 44;
+
+ hitZoneOffset = 10;
+ hitZoneSideLength = 65;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ thumbImageWidth = 22;
+ thumbImageHeight = 22;
+
+ hitZoneOffset = 5;
+ hitZoneSideLength = 33;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ thumbImageWidth = 29;
+ thumbImageHeight = 29;
+
+ hitZoneOffset = 5;
+ hitZoneSideLength = 40;
+
+ break;
+ }
+
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ // FXG thumb classes
+ /**
+ * Specifies the FXG class to use when the thumb is in the normal state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbNormalClass:Class;
+
+ /**
+ * Specifies the FXG class to use when the thumb is in the pressed state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbPressedClass:Class;
+
+ /**
+ * Specifies the DisplayObject to use when the thumb is in the normal state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbSkin_normal:DisplayObject;
+
+ /**
+ * Specifies the DisplayObject to use when the thumb is in the pressed state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbSkin_pressed:DisplayObject;
+
+ /**
+ * Specifies the current DisplayObject that should be shown
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var currentThumbSkin:DisplayObject;
+
+ /**
+ * Width of the overall thumb image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbImageWidth:int;
+
+ /**
+ * Height of the overall thumb image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbImageHeight:int;
+
+ /**
+ * Length of the sizes of the hitzone (assumed to be square)
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var hitZoneSideLength:int;
+
+ /**
+ * Distance between the left edge of the hitzone and the left edge
+ * of the thumb
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var hitZoneOffset:int;
+
+ /**
+ * @private
+ * Remember which state is currently being displayed
+ */
+ private var displayedState:String;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ if (currentState == "up")
+ {
+ // show the normal button
+ if (!thumbSkin_normal)
+ {
+ thumbSkin_normal = new thumbNormalClass();
+ addChild(thumbSkin_normal);
+ }
+ else
+ {
+ thumbSkin_normal.visible = true;
+ }
+ currentThumbSkin = thumbSkin_normal;
+
+ // hide the pressed button
+ if (thumbSkin_pressed)
+ thumbSkin_pressed.visible = false;
+ }
+ else if (currentState == "down")
+ {
+ // show the pressed button
+ if (!thumbSkin_pressed)
+ {
+ thumbSkin_pressed = new thumbPressedClass();
+ addChild(thumbSkin_pressed);
+ }
+ else
+ {
+ thumbSkin_pressed.visible = true;
+ }
+ currentThumbSkin = thumbSkin_pressed;
+
+ // hide the normal button
+ if (thumbSkin_normal)
+ thumbSkin_normal.visible = false;
+ }
+
+ displayedState = currentState;
+
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = thumbImageWidth;
+ measuredHeight = thumbImageHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(currentThumbSkin, unscaledWidth, unscaledHeight);
+ setElementPosition(currentThumbSkin, 0, 0)
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // put in a larger hit zone than the thumb
+ graphics.beginFill(0xffffff, 0);
+ graphics.drawRect(-hitZoneOffset, -hitZoneOffset, hitZoneSideLength, hitZoneSideLength);
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderTrackSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderTrackSkin.as
new file mode 100644
index 0000000000..57dc8f391c
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/HSliderTrackSkin.as
@@ -0,0 +1,227 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+ import spark.components.Button;
+ import spark.skins.android4.assets.HSliderTrack;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ /**
+ * ActionScript-based skin for the HSlider track skin part in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class HSliderTrackSkin extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function HSliderTrackSkin()
+ {
+ super();
+
+ trackClass = spark.skins.android4.assets.HSliderTrack;
+
+ // set the right dimensions to use based on the screen density
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ trackWidth = 1200;
+ trackHeight = 8;
+
+ visibleTrackOffset = 48;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ trackWidth = 900;
+ trackHeight = 6;
+
+ visibleTrackOffset = 38;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ trackWidth = 600;
+ trackHeight = 4;
+
+ visibleTrackOffset = 24;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ trackWidth = 450;
+ trackHeight = 3;
+
+ visibleTrackOffset = 18;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ trackWidth = 225;
+ trackHeight = 2;
+
+ visibleTrackOffset = 9;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ trackWidth = 300;
+ trackHeight = 2;
+
+ visibleTrackOffset = 12;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Specifies the FXG class to use for the track image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackClass:Class;
+
+ /**
+ * Specifies the DisplayObject for the track image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackSkin:DisplayObject;
+
+ /**
+ * Specifies the track image width
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackWidth:int;
+
+ /**
+ * Specifies the track image height
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackHeight:int;
+
+ /**
+ * Specifies the offset from the left and right edge to where
+ * the visible track begins. This should match the offset in the FXG assets.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var visibleTrackOffset:int;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ trackSkin = new trackClass();
+ addChild(trackSkin);
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = trackWidth;
+ measuredHeight = trackHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ var unscaledTrackWidth:int = unscaledWidth - (2 * visibleTrackOffset);
+ setElementSize(trackSkin, unscaledTrackWidth, unscaledHeight);
+ setElementPosition(trackSkin, visibleTrackOffset, 0);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/RadioButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/RadioButtonSkin.as
new file mode 100644
index 0000000000..fd74645065
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/RadioButtonSkin.as
@@ -0,0 +1,253 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+import spark.skins.android4.assets.RadioButton_up;
+import spark.skins.mobile.supportClasses.SelectableButtonSkinBase;
+
+/**
+ * ActionScript-based skin for RadioButton controls in mobile applications.
+ *
+ * @see spark.components.RadioButton
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class RadioButtonSkin extends SelectableButtonSkinBase
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ static private const exclusions:Array = ["labelDisplay", "labelDisplayShadow"];
+
+ //--------------------------------------------------------------------------
+ //
+ // Member variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var symbolOffsetX:Number;
+ protected var symbolOffsetY:Number;
+ protected var iconWidth:Number;
+ protected var iconHeight:Number;
+ protected var symbolWidth:Number;
+ protected var symbolHeight:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function RadioButtonSkin()
+ {
+ super();
+
+ layoutPaddingLeft = 0;
+ layoutPaddingRight = 0;
+ layoutPaddingTop = 0;
+ layoutPaddingBottom = 0;
+
+ upIconClass = spark.skins.android4.assets.RadioButton_up;
+ upSelectedIconClass = spark.skins.android4.assets.RadioButton_up;
+ downIconClass = spark.skins.android4.assets.RadioButton_down;
+ downSelectedIconClass = spark.skins.android4.assets.RadioButton_down;
+ upSymbolIconClass = null;
+ downSymbolIconClass = null;
+ upSymbolIconSelectedClass = spark.skins.android4.assets.RadioButton_upSymbolSelected;
+ downSymbolIconSelectedClass = spark.skins.android4.assets.RadioButton_downSymbolSelected;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ layoutGap = 16;
+ minWidth = 128;
+ minHeight = 128;
+ iconWidth = 128;
+ iconHeight = 128;
+ symbolWidth = 44;
+ symbolHeight = 44;
+ symbolOffsetX = 44;
+ symbolOffsetY = 44;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ layoutGap = 12;
+ minWidth = 96;
+ minHeight = 96;
+ iconWidth = 96;
+ iconHeight = 96;
+ symbolWidth = 33;
+ symbolHeight = 33;
+ symbolOffsetX = 33;
+ symbolOffsetY = 33;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ layoutGap = 8;
+ minWidth = 64;
+ minHeight = 64;
+ iconWidth = 64;
+ iconHeight = 64;
+ symbolWidth = 22;
+ symbolHeight = 22;
+ symbolOffsetX = 22;
+ symbolOffsetY = 22;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+
+ layoutGap = 6;
+ minWidth = 48;
+ minHeight = 48;
+ iconWidth = 48;
+ iconHeight = 48;
+ symbolWidth = 16.5;
+ symbolHeight = 16.5;
+ symbolOffsetX = 16.5;
+ symbolOffsetY = 16.5;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+
+ layoutGap = 3;
+ minWidth = 24;
+ minHeight = 24;
+ iconWidth = 24;
+ iconHeight = 24;
+ symbolWidth = 8.25;
+ symbolHeight = 8.25;
+ symbolOffsetX = 8.25;
+ symbolOffsetY = 8.25;
+
+ break;
+ }
+ default:
+ {
+
+ layoutGap = 4;
+ minWidth = 32;
+ minHeight = 32;
+ iconWidth = 32;
+ iconHeight = 32;
+ symbolWidth = 11;
+ symbolHeight = 11;
+ symbolOffsetX = 11;
+ symbolOffsetY = 11;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * RadioButton chromeColor is drawn to match the FXG ellipse
+ * shape and position.
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // super draws a transparent hit zone
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ // get the size and position of iconDisplay
+ var currentIcon:DisplayObject = getIconDisplay();
+
+ graphics.beginFill(getStyle("chromeColor"));
+ graphics.drawEllipse(currentIcon.x + 1, currentIcon.y + 1, currentIcon.width - 2, currentIcon.height - 2);
+ graphics.endFill();
+ }
+
+ /**
+ * @private
+ */
+ override protected function get focusSkinExclusions():Array
+ {
+ return exclusions;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+ if(symbolIcon != null)
+ {
+ symbolIcon.width = symbolWidth;
+ symbolIcon.height = symbolHeight;
+ }
+ var iconDisplay:DisplayObject = getIconDisplay();
+ if(iconDisplay != null)
+ {
+ iconDisplay.width = iconWidth;
+ iconDisplay.height = iconHeight;
+ }
+ }
+
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+ // position the symbols to align with the background "icon"
+ if (symbolIcon)
+ {
+ var currentIcon:DisplayObject = getIconDisplay();
+ setElementPosition(symbolIcon, symbolOffsetX, symbolOffsetY);
+ }
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListContainerSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListContainerSkin.as
new file mode 100644
index 0000000000..e076a6b347
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListContainerSkin.as
@@ -0,0 +1,326 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.Graphics;
+ import flash.display.InteractiveObject;
+ import flash.display.Sprite;
+
+ import mx.core.DPIClassification;
+ import mx.core.mx_internal;
+
+ import spark.components.Group;
+ import spark.components.SpinnerListContainer;
+ import spark.layouts.HorizontalLayout;
+ import spark.skins.android4.assets.SpinnerListContainerBackground;
+ import spark.skins.android4.assets.SpinnerListContainerSelectionIndicator;
+ import spark.skins.android4.assets.SpinnerListContainerShadow;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ use namespace mx_internal;
+ /**
+ * ActionScript-based skin for the SpinnerListContainer in mobile applications.
+ *
+ * @see spark.components.SpinnerListContainer
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public class SpinnerListContainerSkin extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ *
+ */
+ public function SpinnerListContainerSkin()
+ {
+ super();
+
+ borderClass = spark.skins.android4.assets.SpinnerListContainerBackground;
+ selectionIndicatorClass = spark.skins.android4.assets.SpinnerListContainerSelectionIndicator;
+ shadowClass = spark.skins.android4.assets.SpinnerListContainerShadow;
+ cornerRadius = 0;
+ borderThickness = 0;
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ selectionIndicatorHeight = 182;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ selectionIndicatorHeight = 144;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ selectionIndicatorHeight = 96;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ selectionIndicatorHeight = 72;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ selectionIndicatorHeight = 36;
+ break;
+ }
+ default: // default DPI_160
+ {
+ selectionIndicatorHeight = 48;
+
+ break;
+ }
+ }
+
+ minWidth = 30;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Pixel thickness of the border.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderThickness:Number;
+
+ /**
+ * Radius of the border corners.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var cornerRadius:Number;
+
+ /**
+ * Height of the selection indicator.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicatorHeight:Number;
+
+ /**
+ * Class for the border part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderClass:Class;
+
+ /**
+ * Class for the selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicatorClass:Class;
+
+ /**
+ * Class for the shadow skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var shadowClass:Class;
+
+ /**
+ * Border skin part which includes the background.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var border:InteractiveObject;
+
+ /**
+ * Selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicator:InteractiveObject;
+
+ /**
+ * Shadow skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var shadow:InteractiveObject;
+
+ /**
+ * Mask for the content group.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var contentGroupMask:Sprite;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * An optional skin part that defines the Group where the content
+ * children are pushed into and laid out.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var contentGroup:Group;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var hostComponent:SpinnerListContainer;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Methods
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!border)
+ {
+ // Border and background
+ border = new borderClass();
+ border.mouseEnabled = false;
+ addChild(border);
+ }
+
+ if (!contentGroup)
+ {
+ // Contains the child elements
+ contentGroup = new Group();
+ var hLayout:HorizontalLayout = new HorizontalLayout();
+ hLayout.gap = 0;
+ hLayout.verticalAlign = "middle";
+ contentGroup.layout = hLayout;
+ contentGroup.id = "contentGroup";
+ addChild(contentGroup);
+ }
+
+ if (!shadow)
+ {
+ // Shadowing sits on top of the content
+ shadow = new shadowClass();
+ shadow.mouseEnabled = false;
+ addChild(shadow);
+ }
+
+
+ if (!contentGroupMask)
+ {
+ // Create a mask for the content
+ contentGroupMask = new Sprite();
+ addChild(contentGroupMask);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var contentW:Number = contentGroup.getPreferredBoundsWidth();
+ var contentH:Number = contentGroup.getPreferredBoundsHeight();
+
+ measuredWidth = measuredMinWidth = contentW + borderThickness * 2;
+ measuredHeight = contentH + borderThickness * 2;
+
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(contentGroup, unscaledWidth - borderThickness * 2, unscaledHeight - borderThickness * 2);
+ setElementPosition(contentGroup, borderThickness, borderThickness);
+
+ // Inset by the borderThickness horizontally because the selectionIndicator starts at 0
+ setElementSize(border, unscaledWidth - borderThickness * 2, unscaledHeight);
+ setElementPosition(border, borderThickness, 0);
+
+ setElementSize(shadow, unscaledWidth - borderThickness * 4, measuredHeight - borderThickness * 2);
+ setElementPosition(shadow, borderThickness * 2, unscaledHeight/2 - measuredHeight/2);
+
+ // The SpinnerLists contain a left and right border. We don't want to show the leftmost
+ // SpinnerLists's left border nor the rightmost one's right border.
+ // We inset the mask on the left and right sides to accomplish this.
+ var g:Graphics = contentGroupMask.graphics;
+ g.clear();
+ g.beginFill(0x00FF00);
+ g.drawRoundRect(borderThickness * 2, borderThickness, unscaledWidth - borderThickness * 4, unscaledHeight - borderThickness * 2, cornerRadius, cornerRadius);
+ g.endFill();
+
+ contentGroup.mask = contentGroupMask;
+ }
+ }
+}
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListScrollerSkin.mxml b/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListScrollerSkin.mxml
new file mode 100644
index 0000000000..270818e903
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListScrollerSkin.mxml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListSkin.as
new file mode 100644
index 0000000000..b86553fd91
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/SpinnerListSkin.as
@@ -0,0 +1,294 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.InteractiveObject;
+
+ import mx.core.ClassFactory;
+ import mx.core.DPIClassification;
+ import mx.core.mx_internal;
+
+ import spark.components.DataGroup;
+ import spark.components.Scroller;
+ import spark.components.SpinnerList;
+ import spark.components.SpinnerListItemRenderer;
+ import spark.layouts.VerticalSpinnerLayout;
+ import spark.skins.android4.assets.SpinnerListContainerSelectionIndicator;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+
+ use namespace mx_internal;
+ /**
+ * ActionScript-based skin for the SpinnerList in mobile applications.
+ *
+ * @see spark.components.SpinnerList
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public class SpinnerListSkin extends MobileSkin
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public function SpinnerListSkin()
+ {
+ super();
+
+ selectionIndicatorClass = spark.skins.android4.assets.SpinnerListContainerSelectionIndicator;
+ borderThickness = 1;
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ selectionIndicatorHeight = 182;
+ minWidth = 64;
+ borderThickness = 3;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ selectionIndicatorHeight = 144;
+ minWidth = 48;
+ borderThickness = 2;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ selectionIndicatorHeight = 96;
+ minWidth = 32;
+ borderThickness = 2;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ selectionIndicatorHeight = 72;
+ minWidth = 24;
+ borderThickness = 1;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ selectionIndicatorHeight = 36;
+ minWidth = 12;
+ borderThickness = 0;
+ break;
+ }
+ default:
+ {
+ selectionIndicatorHeight = 48;
+ minWidth = 16;
+ borderThickness = 1;
+ }
+ }
+
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Scroller skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var scroller:Scroller;
+
+ /**
+ * DataGroup skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var dataGroup:DataGroup;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var hostComponent:SpinnerList;
+
+ /**
+ * Pixel size of the border.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderThickness:int;
+
+ /**
+ * Class for the selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicatorClass:Class;
+
+ /**
+ * Selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicator:InteractiveObject;
+
+ /**
+ * Height of the selection indicator.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicatorHeight:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+ }
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!dataGroup)
+ {
+ // Create data group layout
+ var layout:VerticalSpinnerLayout = new VerticalSpinnerLayout();
+ layout.requestedRowCount = 5;
+
+ // Create data group
+ dataGroup = new DataGroup();
+ dataGroup.id = "dataGroup";
+ dataGroup.layout = layout;
+
+ dataGroup.itemRenderer = new ClassFactory(spark.components.SpinnerListItemRenderer);
+ }
+
+ if (!scroller)
+ {
+ // Create scroller
+ scroller = new Scroller();
+ scroller.id = "scroller";
+ scroller.hasFocusableChildren = false;
+ scroller.ensureElementIsVisibleForSoftKeyboard = false;
+
+ // Only support vertical scrolling
+ scroller.setStyle("verticalScrollPolicy","on");
+ scroller.setStyle("horizontalScrollPolicy", "off");
+ scroller.setStyle("skinClass", spark.skins.android4.SpinnerListScrollerSkin);
+
+ addChild(scroller);
+ }
+
+ if (!selectionIndicator)
+ {
+ // Selection indicator is on top
+ selectionIndicator = new selectionIndicatorClass();
+ selectionIndicator.mouseEnabled = false;
+ addChild(selectionIndicator);
+ }
+
+ // Associate scroller with data group
+ if (!scroller.viewport)
+ scroller.viewport = dataGroup;
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = scroller.getPreferredBoundsWidth() + borderThickness * 2;
+ measuredHeight = scroller.getPreferredBoundsHeight();
+ //add in for selection indicator
+ measuredMinHeight = selectionIndicatorHeight + borderThickness * 4;
+ minHeight = measuredMinHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // Scroller
+ setElementSize(scroller, unscaledWidth - borderThickness * 2, unscaledHeight);
+ setElementPosition(scroller, borderThickness, 0);
+ //selection indicator
+ unscaledHeight = Math.max(unscaledHeight, selectionIndicatorHeight + borderThickness * 4);
+
+ setElementSize(selectionIndicator, unscaledWidth, selectionIndicatorHeight);
+ setElementPosition(selectionIndicator, 0, Math.floor((unscaledHeight - selectionIndicatorHeight) / 2));
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ // Reinitialize the typical element so it picks up the latest styles
+ // Font styles might impact the size of the SpinnerList
+ if (styleProp != "color" && styleProp != "accentColor")
+ {
+ if (dataGroup)
+ dataGroup.invalidateTypicalItemRenderer();
+ }
+
+ super.styleChanged(styleProp);
+ }
+
+ }
+}
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/StageTextAreaSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/StageTextAreaSkin.as
new file mode 100644
index 0000000000..d48377d3f3
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/StageTextAreaSkin.as
@@ -0,0 +1,190 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+ import mx.core.mx_internal;
+
+ import spark.components.TextArea;
+ import spark.components.supportClasses.IStyleableEditableText;
+ import spark.components.supportClasses.ScrollableStageText;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.android4.supportClasses.StageTextSkinBase;
+
+ use namespace mx_internal;
+
+ /**
+ * ActionScript-based skin for TextArea controls in mobile applications that uses a
+ * StyleableStageText class for the text display.
+ *
+ * @see spark.components.TextArea
+ * @see spark.components.supportClasses.StyleableStageText
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public class StageTextAreaSkin extends StageTextSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Class variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * The underlying native text control on iOS has internal margins of its
+ * own. In order to remain faithful to the paddingTop and paddingBottom
+ * style values that developers may specify, those internal margins need to
+ * be compensated for. This variable contains size of that compensation in
+ * pixels.
+ */
+ mx_internal static var iOSVerticalPaddingAdjustment:Number = 5;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function StageTextAreaSkin()
+ {
+ super();
+ multiline = true;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultHeight = 212;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ measuredDefaultHeight = 140;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultHeight = 106;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultHeight = 70;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultHeight = 35;
+ break;
+ }
+ default:
+ {
+ measuredDefaultHeight = 48;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextArea; // SkinnableComponent will populate
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+ measureTextComponent(hostComponent);
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number,
+ unscaledHeight:Number):void
+ {
+ // base class handles border position & size
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size the text
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = Math.max(0, unscaledWidth - paddingLeft - paddingRight);
+ var unscaledTextHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+
+ if (textDisplay)
+ {
+ var verticalPosAdjustment:Number = 0;
+ var heightAdjustment:Number = 0;
+
+ /* if (Platform.isIOS)
+ {
+ verticalPosAdjustment = Math.min(iOSVerticalPaddingAdjustment, paddingTop);
+ heightAdjustment = verticalPosAdjustment + Math.min(iOSVerticalPaddingAdjustment, paddingBottom);
+ }*/
+
+ textDisplay.commitStyles();
+ setElementSize(textDisplay, unscaledTextWidth, unscaledTextHeight + heightAdjustment);
+ setElementPosition(textDisplay, paddingLeft, paddingTop - verticalPosAdjustment);
+ }
+
+ if (promptDisplay)
+ {
+ if (promptDisplay is StyleableTextField)
+ StyleableTextField(promptDisplay).commitStyles();
+
+ setElementSize(promptDisplay, unscaledTextWidth, unscaledTextHeight);
+ setElementPosition(promptDisplay, paddingLeft, paddingTop);
+ }
+ }
+
+ override protected function createTextDisplay():IStyleableEditableText
+ {
+ return new ScrollableStageText(multiline);
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/StageTextInputSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/StageTextInputSkin.as
new file mode 100644
index 0000000000..7f92647f1d
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/StageTextInputSkin.as
@@ -0,0 +1,134 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.components.TextInput;
+ import spark.components.supportClasses.IStyleableEditableText;
+ import spark.components.supportClasses.ScrollableStageText;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.android4.supportClasses.StageTextSkinBase;
+
+ /**
+ * ActionScript-based skin for TextInput controls in mobile applications that uses a
+ * StyleableStageText class for the text input.
+ *
+ * @see spark.components.TextInput
+ * @see spark.components.supportClasses.StyleableStageText
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public class StageTextInputSkin extends StageTextSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function StageTextInputSkin()
+ {
+ super();
+ multiline = false;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextInput; // SkinnableComponent will populate
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+ measureTextComponent(hostComponent);
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number,
+ unscaledHeight:Number):void
+ {
+ // base class handles border position & size
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size the text
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = Math.max(0, unscaledWidth - paddingLeft - paddingRight);
+ var unscaledTextHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+
+ // default vertical positioning is centered
+ var textHeight:Number = getElementPreferredHeight(textDisplay);
+ var textY:Number = Math.round(0.5 * (unscaledTextHeight - textHeight)) + paddingTop;
+
+ if (textDisplay)
+ {
+ textDisplay.commitStyles();
+ setElementSize(textDisplay, unscaledTextWidth, unscaledTextHeight);
+ setElementPosition(textDisplay, paddingLeft, textY);
+ }
+
+ if (promptDisplay)
+ {
+ if (promptDisplay is StyleableTextField)
+ StyleableTextField(promptDisplay).commitStyles();
+
+ var promptHeight:Number = getElementPreferredHeight(promptDisplay);
+ var promptY:Number = Math.round(0.5 * (unscaledTextHeight - promptHeight)) + paddingTop;
+
+ setElementSize(promptDisplay, unscaledTextWidth, promptHeight);
+ setElementPosition(promptDisplay, paddingLeft, promptY);
+ }
+ }
+
+ override protected function createTextDisplay():IStyleableEditableText
+ {
+ return new ScrollableStageText(multiline);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/TabbedViewNavigatorTabBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/TabbedViewNavigatorTabBarSkin.as
new file mode 100644
index 0000000000..eea5948eea
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/TabbedViewNavigatorTabBarSkin.as
@@ -0,0 +1,122 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.components.ButtonBarButton;
+import spark.components.DataGroup;
+import spark.skins.mobile.supportClasses.ButtonBarButtonClassFactory;
+import spark.skins.mobile.supportClasses.TabbedViewNavigatorTabBarHorizontalLayout;
+
+/**
+ * The Android 4.x specific skin class for the Spark TabbedViewNavigator tabBar skin part.
+ * It uses the ButtonBarFirstButtonSkin and ButtonBarMiddleButtonSkin as skins for first
+ * middle buttons
+ *
+ * @see spark.components.TabbedViewNavigator#tabBar
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TabbedViewNavigatorTabBarSkin extends ButtonBarSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function TabbedViewNavigatorTabBarSkin()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ if (!firstButton)
+ {
+ firstButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ firstButton.skinClass = spark.skins.android4.ButtonBarFirstButtonSkin;
+ }
+
+ if (!lastButton)
+ {
+ lastButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ lastButton.skinClass = spark.skins.android4.ButtonBarFirstButtonSkin;
+ }
+
+ if (!middleButton)
+ {
+ middleButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ middleButton.skinClass = spark.skins.android4.ButtonBarMiddleButtonSkin;
+ }
+
+ if (!dataGroup)
+ {
+ // TabbedViewNavigatorButtonBarHorizontalLayout for even percent layout
+ var tabLayout:TabbedViewNavigatorTabBarHorizontalLayout =
+ new TabbedViewNavigatorTabBarHorizontalLayout();
+ tabLayout.useVirtualLayout = false;
+
+ dataGroup = new DataGroup();
+ dataGroup.layout = tabLayout;
+ addChild(dataGroup);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ // backgroundAlpha style is not supported by ButtonBar
+ // TabbedViewNavigatorSkin sets a hard-coded value to support
+ // overlayControls
+ var backgroundAlphaValue:* = getStyle("backgroundAlpha");
+ var backgroundAlpha:Number = (backgroundAlphaValue === undefined)
+ ? 1 : getStyle("backgroundAlpha");
+
+ graphics.beginFill(getStyle("chromeColor"), backgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/TextAreaSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/TextAreaSkin.as
new file mode 100644
index 0000000000..0c231a6f2d
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/TextAreaSkin.as
@@ -0,0 +1,892 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.events.Event;
+import flash.events.FocusEvent;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.events.SoftKeyboardEvent;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.system.Capabilities;
+import flash.text.TextLineMetrics;
+import flash.ui.Keyboard;
+
+import mx.core.DPIClassification;
+import mx.core.EventPriority;
+import mx.core.FlexGlobals;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+import mx.utils.Platform;
+
+import spark.components.Group;
+import spark.components.Scroller;
+import spark.components.TextArea;
+import spark.components.supportClasses.StyleableTextField;
+import spark.events.CaretBoundsChangeEvent;
+import spark.skins.android4.supportClasses.TextSkinBase;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for TextArea components in mobile applications.
+ *
+ * @see spark.components.TextArea
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TextAreaSkin extends TextSkinBase
+{
+ /**
+ * @private
+ * Right-margin of iOS native text control when editing on a retina display
+ * based on fontSize 32.
+ */
+ mx_internal static var IOS_RIGHT_MARGIN_320:Number = 19;
+
+ /**
+ * @private
+ * Right-margin of iOS native text control when editing on a retina display
+ * based on fontSize 16 scaling from applicationDPI 160.
+ */
+ mx_internal static var IOS_RIGHT_MARGIN_160_SCALED_TO_320:Number = 9.4;
+
+ /**
+ * @private
+ * Right-margin of iOS native text control when editing on a standard display
+ * based on fontSize 16 and runtimeDPI 160.
+ */
+ mx_internal static var IOS_RIGHT_MARGIN_160:Number = 20.6;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function TextAreaSkin()
+ {
+ super();
+
+ addEventListener(Event.RESIZE, resizeHandler);
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultWidth = 1024;
+ measuredDefaultHeight = 212;
+ layoutBorderSize = 4;
+ flatheight = 9;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ measuredDefaultWidth = 880;
+ measuredDefaultHeight = 140;
+ layoutBorderSize = 3;
+ flatheight = 7;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultWidth = 612;
+ measuredDefaultHeight = 106;
+ layoutBorderSize = 2;
+ flatheight = 6;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultWidth = 440;
+ measuredDefaultHeight = 70;
+ layoutBorderSize = 2;
+ flatheight = 5;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultWidth = 220;
+ measuredDefaultHeight = 35;
+ layoutBorderSize = 1;
+ flatheight = 2;
+ break;
+ }
+ default:
+ {
+ measuredDefaultWidth = 306;
+ measuredDefaultHeight = 53;
+ layoutBorderSize = 1;
+ flatheight = 3;
+ break;
+ }
+ }
+ addEventListener(FocusEvent.FOCUS_IN, focusChangeHandler);
+ addEventListener(FocusEvent.FOCUS_OUT, focusChangeHandler);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Scroller skin part.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var scroller:Scroller;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextArea;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var isFocused:Boolean = false;
+
+ protected var flatheight:uint;
+
+ /**
+ * @private
+ * The width of the component on the previous layout manager
+ * pass. This gets set in updateDisplayList() and used in measure() on
+ * the next layout pass. This is so our "guessed width" in measure()
+ * will be as accurate as possible since textDisplay is multiline and
+ * the textDisplay height is dependent on the width.
+ *
+ * In the constructor this is actually set based on the DPI.
+ */
+ mx_internal var oldUnscaledWidth:Number;
+
+ private var textDisplayGroup:Group;
+ private var _isIOS:Boolean;
+ private var invalidateCaretPosition:Boolean = true;
+ private var oldCaretBounds:Rectangle = new Rectangle(-1, -1, -1, -1);
+ private var lastTextHeight:Number;
+ private var lastTextWidth:Number;
+
+ private var isTextDisplayTall:Boolean = true;
+ private var growTextDisplay:Boolean = false;
+ private var shrinkTextDisplay:Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ if (!textDisplay)
+ {
+ // wrap StyleableTextField in UIComponent
+ textDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ textDisplay.styleName = this;
+ textDisplay.multiline = true;
+ textDisplay.editable = true;
+ textDisplay.lineBreak = getStyle("lineBreak");
+ textDisplay.useTightTextBounds = false;
+ textDisplay.scrollToRangeDelegate = scrollToRange;
+
+ // on iOS, resize the TextField and let the native control handle scrolling
+ _isIOS = Platform.isIOS;
+
+ if (_isIOS)
+ {
+ // hard-coded rightMargin for iOS native text control
+ // this value is independent of the paddingRight style
+ var rightMargin:Number = 0;
+ var isRetina:Boolean = false;
+ var isScaling160to320:Boolean = false;
+
+ // check for scaling
+ if ("runtimeDPI" in FlexGlobals.topLevelApplication)
+ {
+ var runtimeDPI:Number = FlexGlobals.topLevelApplication.runtimeDPI as Number;
+ isRetina = (runtimeDPI == DPIClassification.DPI_320);
+ isScaling160to320 = isRetina
+ && (applicationDPI == DPIClassification.DPI_160);
+ }
+
+ if (isRetina && !isScaling160to320)
+ rightMargin = IOS_RIGHT_MARGIN_320;
+ else if (isRetina && isScaling160to320)
+ rightMargin = IOS_RIGHT_MARGIN_160_SCALED_TO_320;
+ else
+ rightMargin = IOS_RIGHT_MARGIN_160;
+
+ textDisplay.rightMargin = rightMargin;
+ }
+ else
+ {
+ textDisplay.addEventListener(KeyboardEvent.KEY_DOWN, textDisplay_keyHandler);
+ }
+
+ textDisplay.addEventListener(Event.CHANGE, textDisplay_changeHandler);
+ textDisplay.addEventListener(FlexEvent.VALUE_COMMIT, textDisplay_changeHandler);
+ textDisplay.addEventListener(Event.SCROLL, textDisplay_scrollHandler);
+ // Use a lower priority so that the StyleableTextField event handler is called first.
+ // That handler cancels the event and we need to check for that case
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, textDisplay_softKeyboardActivatingHandler, false, EventPriority.DEFAULT_HANDLER);
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, textDisplay_softKeyboardActivateHandler);
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, textDisplay_softKeyboardDeactivateHandler);
+
+ textDisplay.left = getStyle("paddingLeft");
+ textDisplay.top = getStyle("paddingTop");
+ textDisplay.right = getStyle("paddingRight");
+ textDisplay.bottom = getStyle("paddingBottom");
+
+ // wrap StyleableTextComponent in Group for viewport
+ textDisplayGroup = new Group();
+ textDisplayGroup.clipAndEnableScrolling = true;
+ textDisplayGroup.addElement(textDisplay);
+ }
+
+ if (!scroller)
+ {
+ scroller = new Scroller();
+ scroller.minViewportInset = 0;
+ scroller.measuredSizeIncludesScrollBars = false;
+ scroller.ensureElementIsVisibleForSoftKeyboard = false;
+
+ addChild(scroller);
+ }
+
+ if (!scroller.viewport)
+ scroller.viewport = textDisplayGroup;
+
+ super.createChildren();
+ }
+
+ /**
+ * @private
+ * TextArea prompt supports wrapping and multiline
+ */
+ override protected function createPromptDisplay():StyleableTextField
+ {
+ var prompt:StyleableTextField = super.createPromptDisplay();
+ prompt.editable = true;
+ prompt.wordWrap = true;
+
+ return prompt;
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+
+ // TextDisplay always defaults to 440 pixels wide (the value is DPI dependent),
+ // and tall enough to show all text.
+ //
+ // You can set an explicit width and the height will adjust accordingly. The opposite
+ // is not true: setting an explicit height will not adjust the width accordingly.
+
+ measuredWidth = measuredDefaultWidth;
+
+ // now we need to measure textDisplay's height. Unfortunately, this is tricky and
+ // is dependent on textDisplay's width. Let's use the heuristic that our width
+ // is the same as our last width.
+ // We don't use layoutMeasuredWidth, because that value is just a constant and doesn't
+ // take into account the fact that the TextArea could have an explicitWidth or could
+ // be constrained by some value. However, we still default oldTextDisplayWidth to
+ // be layoutMeasuredWidth the first time through.
+ var textDisplayEstimatedWidth:Number = oldUnscaledWidth - paddingLeft - paddingRight;
+
+ // now we need to measure textDisplay's height. Unfortunately, this is tricky and
+ // is dependent on textDisplay's width.
+ // Use the old textDisplay width as an estimte for the new one.
+ // If we are wrong, we'll find out in updateDisplayList()
+ textDisplay.commitStyles();
+
+ // Clear min sizes first.
+ textDisplay.minWidth = textDisplay.minHeight = NaN;
+
+ // If lineBreak == explicit, always use NaN for estimated width
+ if (getStyle("lineBreak") == "explicit")
+ textDisplayEstimatedWidth = NaN;
+
+ setElementSize(textDisplay, textDisplayEstimatedWidth, NaN);
+
+ measuredHeight = getElementPreferredHeight(textDisplay) + paddingTop + paddingBottom;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size border
+ if (border)
+ {
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+
+ setElementSize(scroller, unscaledWidth, unscaledHeight);
+ setElementPosition(scroller, 0, 0);
+
+ // position & size the text
+ var explicitLineBreak:Boolean = getStyle("lineBreak") == "explicit";
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = unscaledWidth - paddingLeft - paddingRight;
+ var unscaledTextHeight:Number = unscaledHeight - paddingTop - paddingBottom;
+ var textHeight:Number;
+ var textWidth:Number = explicitLineBreak ? textDisplay.measuredTextSize.x : unscaledTextWidth;
+
+ var lineIndex:int;
+ var topCharIndex:int;
+ var charBounds:Rectangle;
+
+ // grab old measured textDisplay height before resizing it
+ var oldPreferredTextHeight:Number = getElementPreferredHeight(textDisplay);
+
+ // set width first to measure height correctly
+ textDisplay.commitStyles();
+ textDisplay.setLayoutBoundsSize(textWidth, NaN);
+
+ // In iOS, when we go into editing mode, the runtime overlays a native
+ // text control over the textDisplay. In order to prevent the text
+ // from overflowing the component and to get scrolling support, the
+ // native text control must be the same size as the TextArea
+ if (_isIOS)
+ {
+ if (shrinkTextDisplay)
+ {
+ // Switching to edit mode. Convert from viewport scrolling to
+ // TextField scrolling
+ var vsp:Number = textDisplayGroup.verticalScrollPosition;
+
+ var lineMetrics:TextLineMetrics = textDisplay.getLineMetrics(0);
+ var lineHeight:Number = lineMetrics.ascent + lineMetrics.descent;
+
+ // TODO Figure out how to get the x offset. Right now is hard coded to 2
+ // At least half the line should be showing before we scroll to that line
+ // This makes the conversion from pixel to line based scrolling a little less jumpy
+ lineIndex = textDisplay.getLineIndexAtPoint(2, vsp + lineHeight / 2) + 1;
+ textDisplayGroup.verticalScrollPosition = 0;
+ isTextDisplayTall = false;
+ //trace("TAS.layoutContents shrinkText vsp",vsp,"lineIndex",lineIndex);
+ }
+
+ else if (growTextDisplay)
+ {
+ // Leaving edit mode. Convert from TextField scrolling to
+ // viewport scrolling
+ var scrollV:Number = textDisplay.scrollV;
+
+ // TODO (jszeto) investigate using lineMetrics.lineHeight * scrollV instead of getCharBoundaries
+ topCharIndex = textDisplay.getLineOffset(scrollV - 1);
+ charBounds = textDisplay.getCharBoundaries(topCharIndex);
+ // If the charBounds is null, just set vsp to 0
+ if (charBounds == null)
+ charBounds = new Rectangle(0, 0, 0, 0);
+ textDisplay.scrollV = 1;
+ isTextDisplayTall = true;
+ //trace("TAS.layoutContents growText scrollV",scrollV,"topCharIndex",topCharIndex,"charBounds",charBounds);
+ }
+ }
+
+ // TextField height should match its content or the TextArea bounds at minimum
+ // iOS special case to prevent Flex Scroller scrolling when editable
+ if (isTextDisplayTall)
+ textHeight = Math.max(textDisplay.measuredTextSize.y, unscaledTextHeight);
+ else
+ textHeight = unscaledTextHeight;
+
+ // FIXME (jasonsj): iOS native scroll bar appears even when explictHeight
+ // is not specified. Focus-in is jumpy.
+
+ if (promptDisplay)
+ {
+ promptDisplay.commitStyles();
+ setElementSize(promptDisplay, unscaledTextWidth, textHeight);
+ setElementPosition(promptDisplay, paddingLeft, paddingTop);
+
+ // no need to update textDisplay if promptDisplay is present
+ return;
+ }
+
+ // keep track of oldUnscaledWidth so we have a good guess as to the width
+ // of the textDisplay on the next measure() pass
+ oldUnscaledWidth = unscaledWidth;
+
+ // set the width of textDisplay to textWidth.
+ // set the height to oldTextHeight. If the height's actually wrong,
+ // we'll invalidateSize() and go through this layout pass again anyways
+ setElementSize(textDisplay, textWidth, textHeight);
+
+ // Set minWidth/Height on the text so the textDisplayGroup sizes accordingly
+ textDisplay.minWidth = textWidth;
+ textDisplay.minHeight = textHeight;
+ textDisplayGroup.invalidateDisplayList();
+
+ // grab new measured textDisplay height after the textDisplay has taken its final width
+ var newPreferredTextHeight:Number = getElementPreferredHeight(textDisplay);
+
+ // if the resize caused the textDisplay's height to change (because of
+ // text reflow), then we need to remeasure ourselves with our new width
+ if (oldPreferredTextHeight != newPreferredTextHeight)
+ invalidateSize();
+
+ if (_isIOS)
+ {
+ if (shrinkTextDisplay)
+ {
+ scroller.validateNow();
+ textDisplay.scrollV = lineIndex;
+ }
+ else if (growTextDisplay)
+ {
+ scroller.validateNow();
+ textDisplayGroup.verticalScrollPosition = charBounds.y;
+ }
+
+ shrinkTextDisplay = false;
+ growTextDisplay = false;
+ }
+
+ //trace("TAS.layoutContents tH",textHeight,"tW",textWidth,"invalidateCaret",invalidateCaretPosition);
+
+ // checking if text fits in TextArea
+ // does not apply to iOS due to native text editing and scrolling
+ // invalidateCaretPosition will never be true for iOS
+ if (invalidateCaretPosition && isTextDisplayTall)
+ {
+ // if the caret is outside the viewport, update the Group verticalScrollPosition
+ var charIndex:int = textDisplay.selectionBeginIndex;
+ var caretBounds:Rectangle = textDisplay.getCharBoundaries(charIndex);
+ lineIndex = textDisplay.getLineIndexOfChar(charIndex);
+
+ // getCharBoundaries() returns null for new lines
+ if (!caretBounds)
+ {
+ // temporarily insert a character at the caretIndex
+ textDisplay.replaceText(charIndex, charIndex, "W");
+ caretBounds = textDisplay.getCharBoundaries(charIndex);
+ lineIndex = textDisplay.getLineIndexOfChar(charIndex);
+ textDisplay.replaceText(charIndex, charIndex + 1, "");
+ }
+
+ if (caretBounds)
+ {
+ // Scroll the internal Scroller to ensure the caret is visible
+ if (textHeight > unscaledTextHeight)
+ {
+
+ if (charIndex == textDisplay.text.length)
+ {
+ // Make sure textDisplayGroup is validated, otherwise the
+ // verticalScrollPosition may be out of bounds, which will
+ // cause a bounce effect.
+ textDisplayGroup.validateNow();
+ textDisplayGroup.verticalScrollPosition = textHeight;
+ }
+ else
+ {
+ // caretTopPositon and caretBottomPosition are TextField-relative positions
+ // the TextField is inset by padding styles of the TextArea (via the VGroup)
+
+ // adjust top position to 0 when on the first line
+ // caretTopPosition will be negative when off stage
+ var caretTopPosition:Number = ((caretBounds.y) < 0 || (lineIndex == 0))
+ ? 0 : caretBounds.y;
+
+ // caretBottomPosition is the y coordinate of the bottom bounds of the caret
+ var caretBottomPosition:Number = caretBounds.y + caretBounds.height;
+
+ // note that verticalScrollPosition min/max do not account for padding
+ var vspTop:Number = textDisplayGroup.verticalScrollPosition;
+
+ // vspBottom should be the max visible Y in the TextField
+ // coordinate space.
+ // remove paddingBottom for some clearance between caret and border
+ var vspBottom:Number = vspTop + unscaledHeight - paddingTop - paddingBottom;
+
+ // is the caret in or below the padding and viewport?
+ if (caretBottomPosition > vspBottom)
+ {
+ // adjust caretBottomPosition to max scroll position when on the last line
+ if (lineIndex + 1 == textDisplay.numLines)
+ {
+ // use textHeight+paddings instead of textDisplayGroup.contentHeight
+ // Group has not been resized by this point
+ textDisplayGroup.verticalScrollPosition = (textHeight + paddingTop + paddingBottom) - textDisplayGroup.height;
+ }
+ else
+ {
+ // bottom edge of the caret moves just inside the bottom edge of the scroller
+ // add delta between caret and vspBottom
+ textDisplayGroup.verticalScrollPosition = vspTop + (caretBottomPosition - vspBottom);
+ }
+ }
+ // is the caret above the viewport?
+ else if (caretTopPosition < vspTop)
+ {
+ // top edge of the caret moves inside the top edge of the scroller
+ textDisplayGroup.verticalScrollPosition = caretTopPosition;
+ }
+ }
+
+ scroller.validateNow();
+ }
+
+ // Convert to local coordinates
+ // Dispatch an event for an ancestor Scroller
+ // It will scroll the TextArea so the caret is in view
+ convertBoundsToLocal(caretBounds);
+ if (oldCaretBounds == null || caretBounds.bottom != oldCaretBounds.bottom || caretBounds.top != oldCaretBounds.top)
+ {
+ //trace("TAS.layoutContents send caret CHANGE");
+ dispatchEvent(new CaretBoundsChangeEvent(CaretBoundsChangeEvent.CARET_BOUNDS_CHANGE,true,true,oldCaretBounds,caretBounds));
+ }
+
+ oldCaretBounds = caretBounds;
+ }
+
+ invalidateCaretPosition = false;
+ }
+
+ // Make sure final scroll position is valid
+ if (isTextDisplayTall)
+ snapTextScrollPosition();
+ }
+
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var contentBackgroundColor:uint = getStyle("contentBackgroundColor");
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ //change border color and thickness when in focus
+ var borderColor:uint = isFocused ? getStyle("focusColor") : getStyle("borderColor");
+ var selectWidth:uint = isFocused ? layoutBorderSize + 1 : layoutBorderSize;
+ if (isNaN(contentBackgroundAlpha))
+ {
+ contentBackgroundAlpha = 1;
+ }
+ if (getStyle("contentBackgroundBorder") == "flat")
+ {
+ var halfGap:int = flatheight * 2;
+ //background
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth, unscaledHeight - flatheight);
+ graphics.endFill();
+ //begin flat border
+ graphics.beginFill(borderColor, 1);
+ //left half border
+ graphics.drawRect(0, unscaledHeight - halfGap, selectWidth, flatheight );
+ //bottom border
+ graphics.drawRect(0, unscaledHeight - flatheight, unscaledWidth, selectWidth);
+ //right border
+ graphics.drawRect(unscaledWidth - selectWidth, unscaledHeight - halfGap, selectWidth, flatheight);
+ graphics.endFill();
+ }
+ else if (getStyle("contentBackgroundBorder") == "rectangle")
+ {
+ var borderWidth:uint = layoutBorderSize * 2;
+ //rectangle border and background
+ graphics.lineStyle(selectWidth, borderColor, 1);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ }
+
+ /**
+ * @private
+ * Make sure the scroll positions are valid, and adjust if needed.
+ */
+ private function snapTextScrollPosition():void
+ {
+ var maxHsp:Number = textDisplayGroup.contentWidth > textDisplayGroup.width ?
+ textDisplayGroup.contentWidth-textDisplayGroup.width : 0;
+ textDisplayGroup.horizontalScrollPosition =
+ Math.min(Math.max(0,textDisplayGroup.horizontalScrollPosition),maxHsp);
+
+ var maxVsp:Number = textDisplayGroup.contentHeight > textDisplayGroup.height ?
+ textDisplayGroup.contentHeight-textDisplayGroup.height : 0;
+
+ textDisplayGroup.verticalScrollPosition =
+ Math.min(Math.max(0,textDisplayGroup.verticalScrollPosition),maxVsp);
+ }
+
+ /**
+ * @private
+ * Get the bounds of the caret
+ */
+ private function getCaretBounds():Rectangle
+ {
+ var charIndex:int = textDisplay.selectionBeginIndex;
+ var caretBounds:Rectangle = textDisplay.getCharBoundaries(charIndex);
+
+ if (!caretBounds)
+ {
+ textDisplay.replaceText(charIndex, charIndex, "W");
+ caretBounds = textDisplay.getCharBoundaries(charIndex);
+ textDisplay.replaceText(charIndex, charIndex + 1, "");
+ }
+
+ return caretBounds;
+ }
+
+ /**
+ * @private
+ * Convert bounds from textDisplay to local coordinates
+ */
+ private function convertBoundsToLocal(bounds:Rectangle):void
+ {
+ if (bounds)
+ {
+ var position:Point = new Point(bounds.x, bounds.y);
+ position = textDisplay.localToGlobal(position);
+ position = globalToLocal(position);
+ bounds.x = position.x;
+ bounds.y = position.y;
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function scrollToRange(anchorPosition:int, activePosition:int):void
+ {
+ var pos:int = Math.min(anchorPosition, activePosition);
+ var bounds:Rectangle = textDisplay.getCharBoundaries(pos);
+ var vsp:int = textDisplayGroup.verticalScrollPosition;
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ if (bounds && (bounds.top < vsp - paddingTop ||
+ bounds.bottom > vsp + unscaledHeight - paddingTop - paddingBottom))
+ {
+ textDisplayGroup.verticalScrollPosition = bounds.top + paddingTop;
+ snapTextScrollPosition();
+ }
+ }
+
+ /**
+ * @private
+ * Handle size and caret position changes that occur when text content
+ * changes.
+ */
+ private function textDisplay_changeHandler(event:Event):void
+ {
+ var tH:Number = textDisplay.textHeight;
+ var tW:Number = textDisplay.textWidth;
+ var explicitLineBreak:Boolean = getStyle("lineBreak") == "explicit";
+
+ // Size and caret position have changed if the text height is different or
+ // the text width is different and we aren't word wrapping
+ if (tH != lastTextHeight || ( explicitLineBreak && tW != lastTextWidth))
+ {
+ invalidateSize();
+ invalidateDisplayList();
+ invalidateCaretPosition = true;
+ }
+
+ lastTextHeight = tH;
+ lastTextWidth = tW;
+ }
+
+ /**
+ * @private
+ * Cancels any native scroll that the Flash Player attempts to do
+ */
+ private function textDisplay_scrollHandler(event:Event):void
+ {
+ // if iOS, let the OS handle scrolling
+ if (_isIOS)
+ return;
+
+ // If not IOS, we will handle scrolling, so don't let the native
+ // flash textfield scroll at all.
+ if (textDisplay.scrollV > 1)
+ textDisplay.scrollV = 1;
+ if (textDisplay.scrollH > 0)
+ textDisplay.scrollH = 0;
+ }
+
+ /**
+ * @private
+ * Adjust viewport when using key navigation
+ */
+ private function textDisplay_keyHandler(event:KeyboardEvent):void
+ {
+ // update scroll position when caret changes
+ if ((event.keyCode == Keyboard.UP
+ || event.keyCode == Keyboard.DOWN
+ || event.keyCode == Keyboard.LEFT
+ || event.keyCode == Keyboard.RIGHT))
+ {
+ invalidateDisplayList();
+ invalidateCaretPosition = true;
+ }
+
+ // Change event is not always sent when delete key is pressed, so
+ // invalidate the size here
+ if (event.keyCode == Keyboard.BACKSPACE)
+ {
+ invalidateSize();
+ }
+ }
+
+ /**
+ * @private
+ * When entering edit mode on iOS, we need to shrink the textDisplay to
+ * the size of the TextArea
+ */
+ private function textDisplay_softKeyboardActivatingHandler(event:SoftKeyboardEvent):void
+ {
+ if (event.isDefaultPrevented())
+ return;
+
+ if (_isIOS && isTextDisplayTall)
+ {
+ //trace("TAS.SK ACTIVATING targ",event.target);
+ shrinkTextDisplay = true;
+ invalidateDisplayList();
+ validateNow();
+ }
+ }
+
+ /**
+ * @private
+ * Send a caret change event to an ancestor Scroller
+ */
+ private function textDisplay_softKeyboardActivateHandler(event:SoftKeyboardEvent):void
+ {
+ var keyboardRect:Rectangle = stage.softKeyboardRect;
+
+ if (keyboardRect.width > 0 && keyboardRect.height > 0)
+ {
+ var newCaretBounds:Rectangle = getCaretBounds();
+ convertBoundsToLocal(newCaretBounds);
+
+ if (oldCaretBounds != newCaretBounds)
+ {
+ //trace("TAS.SK ACTIVATE",keyboardRect,"dispatch caret CHANGE","newCaretBounds",newCaretBounds);
+ dispatchEvent(new CaretBoundsChangeEvent(CaretBoundsChangeEvent.CARET_BOUNDS_CHANGE,true,true,oldCaretBounds,newCaretBounds));
+ oldCaretBounds = newCaretBounds;
+ }
+ }
+ }
+
+ /**
+ * @private
+ * On iOS, when leaving edit mode, we need to restore the textDisplay to the
+ * height of the text.
+ */
+ private function textDisplay_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
+ {
+ if (_isIOS && !isTextDisplayTall)
+ {
+ growTextDisplay = true;
+ invalidateDisplayList();
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function resizeHandler(event:Event):void
+ {
+ // Resizing needs to tickle the TextArea's internal auto-scroll logic
+ invalidateCaretPosition = true;
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ super.styleChanged(styleProp);
+
+ // propogate styleChanged explicitly to textDisplay
+ if (textDisplay)
+ textDisplay.styleChanged(styleProp);
+
+ // Check for padding style changes
+ if (!styleProp || styleProp == "styleName" || styleProp.indexOf("padding") >= 0)
+ {
+ if (textDisplay)
+ {
+ textDisplay.left = getStyle("paddingLeft");
+ textDisplay.top = getStyle("paddingTop");
+ textDisplay.right = getStyle("paddingRight");
+ textDisplay.bottom = getStyle("paddingBottom");
+ }
+ }
+ }
+
+ private function focusChangeHandler(event:FocusEvent):void
+ {
+ isFocused = event.type == FocusEvent.FOCUS_IN;
+ invalidateDisplayList();
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/TextInputSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/TextInputSkin.as
new file mode 100644
index 0000000000..7488e1f7c7
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/TextInputSkin.as
@@ -0,0 +1,375 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.events.Event;
+ import flash.events.FocusEvent;
+ import flash.events.SoftKeyboardEvent;
+
+ import mx.core.DPIClassification;
+ import mx.core.EventPriority;
+ import mx.core.mx_internal;
+ import mx.events.FlexEvent;
+ import mx.utils.Platform;
+
+ import spark.components.TextInput;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.android4.supportClasses.TextSkinBase;
+
+ use namespace mx_internal;
+
+ /**
+ * ActionScript-based skin for TextInput controls in mobile applications.
+ *
+ * @see spark.components.TextInput
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class TextInputSkin extends TextSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function TextInputSkin()
+ {
+ super();
+
+ // on iOS, make adjustments for native text rendering
+ _isIOS = Platform.isIOS;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultWidth = 1200;
+ measuredDefaultHeight = 132;
+ layoutBorderSize = 4;
+ flatheight = 9;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ measuredDefaultWidth = 880;
+ measuredDefaultHeight = 100;
+ layoutBorderSize = 3;
+ flatheight = 7;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultWidth = 600;
+ measuredDefaultHeight = 66;
+ layoutBorderSize = 2;
+ flatheight = 6;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultWidth = 440;
+ measuredDefaultHeight = 50;
+ layoutBorderSize = 2;
+ flatheight = 5;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultWidth = 220;
+ measuredDefaultHeight = 25;
+ layoutBorderSize = 1;
+ flatheight = 2;
+ break;
+ }
+ default:
+ {
+ measuredDefaultWidth = 300;
+ measuredDefaultHeight = 33;
+ layoutBorderSize = 1;
+ flatheight = 3;
+ break;
+ }
+ }
+ addEventListener(FocusEvent.FOCUS_IN, focusChangeHandler);
+ addEventListener(FocusEvent.FOCUS_OUT, focusChangeHandler);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var isFocused:Boolean = false;
+
+ protected var flatheight:uint;
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextInput; // SkinnableComponent will populate
+
+ /**
+ * @private
+ */
+ private var _isIOS:Boolean;
+
+ /**
+ * @private
+ */
+ private var _isEditing:Boolean;
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ textDisplay.addEventListener("editableChanged", editableChangedHandler);
+ textDisplay.addEventListener(FlexEvent.VALUE_COMMIT, valueCommitHandler);
+
+ // remove hit area improvements on iOS when editing
+ if (_isIOS)
+ {
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, textDisplay_softKeyboardActivatingHandler, false, EventPriority.DEFAULT_HANDLER);
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, textDisplay_softKeyboardDeactivateHandler);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+ var textHeight:Number = getStyle("fontSize") as Number;
+
+ if (textDisplay)
+ {
+ // temporarily change text for measurement
+ var oldText:String = textDisplay.text;
+
+ // commit styles so we can get a valid textHeight
+ textDisplay.text = "Wj";
+ textDisplay.commitStyles();
+
+ textHeight = textDisplay.measuredTextSize.y;
+ textDisplay.text = oldText;
+ }
+
+ // width is based on maxChars (if set)
+ if (hostComponent && hostComponent.maxChars)
+ {
+ // Grab the fontSize and subtract 2 as the pixel value for each character.
+ // This is just an approximation, but it appears to be a reasonable one
+ // for most input and most font.
+ var characterWidth:int = Math.max(1, (getStyle("fontSize") - 2));
+ measuredWidth = (characterWidth * hostComponent.maxChars) +
+ paddingLeft + paddingRight + StyleableTextField.TEXT_WIDTH_PADDING;
+ }
+
+ measuredHeight = paddingTop + textHeight + paddingBottom;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size border
+ if (border)
+ {
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+
+ // position & size the text
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = unscaledWidth - paddingLeft - paddingRight;
+ var unscaledTextHeight:Number = unscaledHeight - paddingTop - paddingBottom;
+
+ // default vertical positioning is centered
+ var textHeight:Number = getElementPreferredHeight(textDisplay);
+ var textY:Number = Math.round(0.5 * (unscaledTextHeight - textHeight)) + paddingTop;
+
+ // On iOS the TextField top and bottom edges are bounded by the padding.
+ // On all other platforms, the height of the textDisplay is
+ // textHeight + paddingBottom to increase hitArea on bottom.
+ // Note: We don't move the Y position upwards because TextField
+ // has way to set vertical positioning.
+ // Note: iOS is a special case due to the clear button provided by the
+ // native text control used while editing.
+ var adjustedTextHeight:Number = (_isIOS && _isEditing) ? textHeight : textHeight + paddingBottom;
+
+ if (textDisplay)
+ {
+ // We're going to do a few tricks to try to increase the size of our hitArea to make it
+ // easier for users to select text or put the caret in a certain spot. To do that,
+ // rather than set textDisplay.x=paddingLeft, we are going to set
+ // textDisplay.leftMargin = paddingLeft. In addition, we're going to size the height
+ // of the textDisplay larger than just the size of the text inside to increase the hitArea
+ // on the bottom. We'll also assign textDisplay.rightMargin = paddingRight to increase the
+ // the hitArea on the right. Unfortunately, there's no way to increase the hitArea on the top
+ // just yet, but these three tricks definitely help out with regards to user experience.
+ // See http://bugs.adobe.com/jira/browse/SDK-29406 and http://bugs.adobe.com/jira/browse/SDK-29405
+
+ // set leftMargin, rightMargin to increase the hitArea. Need to set it before calling commitStyles().
+ var marginChanged:Boolean = ((textDisplay.leftMargin != paddingLeft) ||
+ (textDisplay.rightMargin != paddingRight));
+
+ textDisplay.leftMargin = paddingLeft;
+ textDisplay.rightMargin = paddingRight;
+
+ // need to force a styleChanged() after setting leftMargin, rightMargin if they
+ // changed values. Then we can validate the styles through commitStyles()
+ if (marginChanged)
+ textDisplay.styleChanged(null);
+ textDisplay.commitStyles();
+
+ setElementSize(textDisplay, unscaledWidth, adjustedTextHeight);
+
+ // set x=0 since we're using textDisplay.leftMargin = paddingLeft
+ setElementPosition(textDisplay, 0, textY);
+ }
+
+ if (promptDisplay)
+ {
+ promptDisplay.commitStyles();
+ setElementSize(promptDisplay, unscaledTextWidth, adjustedTextHeight);
+ setElementPosition(promptDisplay, paddingLeft, textY);
+ }
+ }
+
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var contentBackgroundColor:uint = getStyle("contentBackgroundColor");
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ //change border color and thickness when in focus
+ var borderColor:uint = isFocused ? getStyle("focusColor") : getStyle("borderColor");
+ var selectWidth:uint = isFocused ? layoutBorderSize + 1 : layoutBorderSize;
+ if (isNaN(contentBackgroundAlpha))
+ {
+ contentBackgroundAlpha = 1;
+ }
+ if (getStyle("contentBackgroundBorder") == "flat")
+ {
+ var halfGap:int = flatheight * 2;
+ //background
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth, unscaledHeight - flatheight);
+ graphics.endFill();
+ //begin flat border
+ graphics.beginFill(borderColor, 1);
+ //left half border
+ graphics.drawRect(0, unscaledHeight - halfGap, selectWidth, flatheight );
+ //bottom border
+ graphics.drawRect(0, unscaledHeight - flatheight, unscaledWidth, selectWidth);
+ //right border
+ graphics.drawRect(unscaledWidth - selectWidth, unscaledHeight - halfGap, selectWidth, flatheight);
+ graphics.endFill();
+ }
+ else if (getStyle("contentBackgroundBorder") == "rectangle")
+ {
+ var borderWidth:uint = layoutBorderSize * 2;
+ //rectangle border and background
+ graphics.lineStyle(selectWidth, borderColor, 1);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function editableChangedHandler(event:Event):void
+ {
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ * The text changed in some way.
+ *
+ * Dynamic fields (ie !editable) with no text measure with width=0 and height=0.
+ * If the text changed, need to remeasure the text to get the correct height so it
+ * will be laid out correctly.
+ */
+ private function valueCommitHandler(event:Event):void
+ {
+ if (textDisplay && !textDisplay.editable)
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ private function textDisplay_softKeyboardActivatingHandler(event:SoftKeyboardEvent):void
+ {
+ if (event.isDefaultPrevented())
+ return;
+
+ _isEditing = true;
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ private function textDisplay_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
+ {
+ _isEditing = false;
+ invalidateDisplayList();
+ }
+
+ private function focusChangeHandler(event:FocusEvent):void
+ {
+ isFocused = event.type == FocusEvent.FOCUS_IN;
+ invalidateDisplayList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ToggleSwitchSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/ToggleSwitchSkin.as
new file mode 100644
index 0000000000..c5b99aa35e
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ToggleSwitchSkin.as
@@ -0,0 +1,506 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.BlendMode;
+ import flash.events.Event;
+
+ import mx.core.DPIClassification;
+ import mx.core.IVisualElement;
+ import mx.core.UIComponent;
+
+ import spark.components.ToggleSwitch;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.core.SpriteVisualElement;
+ import spark.skins.android4.assets.ToggleSwitchBackground;
+ import spark.skins.android4.assets.ToggleSwitchThumb_off;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+
+ /**
+ * ActionScript-based Android 4.x specific skin for the ToggleSwitch control.
+ * This class is responsible for most of the
+ * graphics drawing, with additional fxg assets.
+ *
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ *
+ * @see spark.components.ToggleSwitch
+ */
+ public class ToggleSwitchSkin extends MobileSkin
+ {
+ //----------------------------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //----------------------------------------------------------------------------------------------
+
+ /**
+ * The thumb skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var thumb:IVisualElement;
+ /**
+ * The track skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var track:IVisualElement;
+
+ //----------------------------------
+ // hostComponent
+ //----------------------------------
+
+ private var _hostComponent:ToggleSwitch;
+ public var selectedLabelDisplay:LabelDisplayComponent;
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public function get hostComponent():ToggleSwitch
+ {
+ return _hostComponent;
+ }
+
+ public function set hostComponent(value:ToggleSwitch):void
+ {
+ if (_hostComponent)
+ _hostComponent.removeEventListener("thumbPositionChanged", thumbPositionChanged_handler);
+ _hostComponent = value;
+ if (_hostComponent)
+ _hostComponent.addEventListener("thumbPositionChanged", thumbPositionChanged_handler);
+ }
+
+ //----------------------------------
+ // selectedLabel
+ //----------------------------------
+
+ private var _selectedLabel:String;
+ /**
+ * The text of the label showing when the component is selected.
+ * Subclasses can set or override this property to customize the selected label.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected function get selectedLabel():String
+ {
+ return _selectedLabel;
+ }
+
+ protected function set selectedLabel(value:String):void
+ {
+ _selectedLabel = value;
+ }
+
+ //----------------------------------
+ // unselectedLabel
+ //----------------------------------
+
+ private var _unselectedLabel:String;
+ /**
+ * The text of the label showing when the component is not selected.
+ * Subclasses can set or override this property to customize the unselected label.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected function get unselectedLabel():String
+ {
+ return _unselectedLabel;
+ }
+
+ protected function set unselectedLabel(value:String):void
+ {
+ _unselectedLabel = value;
+ }
+
+
+ /**
+ * The contents inside the skin, not including the outline
+ * stroke
+ */
+ private var contents:UIComponent;
+ private var switchTrack:Class;
+ private var switchOff:Class;
+ private var switchOn:Class;
+ protected var trackWidth:Number;
+ protected var trackHeight:Number;
+ protected var layoutThumbWidth:Number;
+ protected var layoutThumbHeight:Number;
+ private var thumbOn:IVisualElement;
+ private var thumbOff:IVisualElement;
+
+ public function ToggleSwitchSkin()
+ {
+ super();
+
+ switchTrack = spark.skins.android4.assets.ToggleSwitchBackground;
+ switchOn = spark.skins.android4.assets.ToggleSwitchThumb_on;
+ switchOff = spark.skins.android4.assets.ToggleSwitchThumb_off;
+
+ switch(applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ layoutThumbWidth = 188;
+ layoutThumbHeight = 96;
+ trackWidth = 388;
+ trackHeight = 96;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ layoutThumbWidth = 140;
+ layoutThumbHeight = 72;
+ trackWidth = 291;
+ trackHeight = 72;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ layoutThumbWidth = 94;
+ layoutThumbHeight = 48;
+ trackWidth = 194;
+ trackHeight = 48;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ layoutThumbWidth = 70;
+ layoutThumbHeight = 36;
+ trackWidth = 146;
+ trackHeight = 36;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ layoutThumbWidth = 35;
+ layoutThumbHeight = 18;
+ trackWidth = 73;
+ trackHeight = 18;
+ break;
+ }
+ default:
+ {
+ layoutThumbWidth = 47;
+ layoutThumbHeight = 24;
+ trackWidth = 97;
+ trackHeight = 24;
+ break;
+ }
+ }
+
+ selectedLabel = resourceManager.getString("components","toggleSwitchSelectedLabel");
+ unselectedLabel = resourceManager.getString("components","toggleSwitchUnselectedLabel");
+ }
+
+ override protected function createChildren():void
+ {
+ super.createChildren();
+ contents = new UIComponent();
+ contents.blendMode = BlendMode.LAYER;
+ addChild(contents);
+ drawTrack();
+ drawThumbs();
+ drawLabel();
+ }
+
+ override protected function measure():void
+ {
+ // The skin must be at least as large as the thumb
+ measuredMinWidth = layoutThumbWidth;
+ measuredMinHeight = layoutThumbHeight;
+
+ // The preferred size will display all label text
+ var labelWidth:Number = getElementPreferredWidth(selectedLabelDisplay);
+ measuredWidth = layoutThumbWidth + labelWidth;
+ measuredHeight = layoutThumbHeight;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ toggleSelectionState();
+ layoutThumbs();
+ layoutLabel();
+ }
+
+ //The label is called selectedLabelDisplay because the hostComponent expects it
+ protected function drawLabel():void
+ {
+ selectedLabelDisplay = new LabelDisplayComponent();
+ selectedLabelDisplay.id = "selectedLabelDisplay";
+ selectedLabelDisplay.text = selectedLabel;
+ setElementSize(selectedLabelDisplay,thumb.width,thumb.height);
+ contents.addChild(selectedLabelDisplay);
+ }
+
+ //Draw the track behind everything else
+ protected function drawTrack():void
+ {
+ if(track == null)
+ {
+ track = new switchTrack();
+ track.width = trackWidth;
+ track.height = trackHeight;
+ contents.addChildAt(SpriteVisualElement(track),0);
+ }
+ }
+
+ //Draw both thumbs. Set skinpart thumb to be thumbOff because default state of the switch is OFF
+ protected function drawThumbs():void
+ {
+ drawThumbOff();
+ drawThumbOn();
+ if(thumb == null)
+ {
+ thumb = thumbOff;
+ }
+ }
+
+ //Thumb ON the right side; Thumb OFF is on the left side
+ protected function layoutThumbs():void
+ {
+ setElementPosition(thumbOn,trackWidth/2,0);
+ setElementPosition(thumbOff,0,0);
+ }
+
+ //Label display sould be at the same location as the thumb
+ protected function layoutLabel():void
+ {
+ if(selectedLabelDisplay != null)
+ {
+ if(currentState.indexOf("AndSelected") != -1)
+ {
+ setElementPosition(selectedLabelDisplay,trackWidth/2,0);
+ }
+ else
+ {
+ setElementPosition(selectedLabelDisplay,0,0);
+ }
+ }
+ }
+
+ //Depending on current state, set skinpart thumb accordingly
+ protected function toggleSelectionState():void
+ {
+ if(currentState.indexOf("AndSelected") != -1)
+ {
+ thumbOn.visible = true;
+ thumbOff.visible = false;
+ thumb = thumbOn;
+ selectedLabelDisplay.text = selectedLabel;
+ }
+ else
+ {
+ thumbOff.visible = true;
+ thumbOn.visible = false;
+ thumb = thumbOff;
+ selectedLabelDisplay.text = unselectedLabel;
+ }
+ }
+
+ protected function drawThumbOn():void
+ {
+ thumbOn = new switchOn();
+ thumbOn.width = layoutThumbWidth;
+ thumbOn.height = layoutThumbHeight;
+ contents.addChildAt(SpriteVisualElement(thumbOn),1);
+ }
+
+ protected function drawThumbOff():void
+ {
+ thumbOff = new switchOff();
+ thumbOff.width = layoutThumbWidth;
+ thumbOff.height = layoutThumbHeight;
+ contents.addChildAt(SpriteVisualElement(thumbOff),1);
+ }
+
+ //Hostcomponent dispatches this event whenever the thumb position changes
+ protected function thumbPositionChanged_handler(event:Event):void
+ {
+ moveSlidingContent();
+ }
+
+ //Move the current thumb and label along with the animating content
+ protected function moveSlidingContent():void
+ {
+ if (!hostComponent)
+ return;
+ var x:Number = (track.getLayoutBoundsWidth() - thumb.getLayoutBoundsWidth()) *
+ hostComponent.thumbPosition + track.getLayoutBoundsX();
+ var y:Number = thumb.getLayoutBoundsY();
+ setElementPosition(thumb, x, y);
+ setElementPosition(selectedLabelDisplay, x, y);
+ }
+ }
+}
+
+
+import flash.events.Event;
+
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.IDisplayText;
+
+use namespace mx_internal;
+
+/**
+ * @private
+ * Component combining two labels to create the effect of text and its drop
+ * shadow. The component can be used with advanced style selectors and the
+ * styles "color", "textShadowColor", and "textShadowAlpha". Based off of
+ * ActionBar.TitleDisplayComponent. These two should eventually be factored.
+ */
+class LabelDisplayComponent extends UIComponent implements IDisplayText
+{
+ public var shadowYOffset:Number = 0;
+ private var labelChanged:Boolean = false;
+ private var labelDisplay:StyleableTextField;
+ private var labelDisplayShadow:StyleableTextField;
+ private var _text:String;
+
+ public function LabelDisplayComponent()
+ {
+ super();
+ _text = "";
+ }
+
+ override public function get baselinePosition():Number
+ {
+ return labelDisplay.baselinePosition;
+ }
+
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ labelDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ labelDisplay.styleName = this;
+ labelDisplay.editable = false;
+ labelDisplay.selectable = false;
+ labelDisplay.multiline = false;
+ labelDisplay.wordWrap = false;
+ labelDisplay.addEventListener(FlexEvent.VALUE_COMMIT,
+ labelDisplay_valueCommitHandler);
+
+ labelDisplayShadow = StyleableTextField(createInFontContext(StyleableTextField));
+ labelDisplayShadow.styleName = this;
+ labelDisplayShadow.colorName = "textShadowColor";
+ labelDisplayShadow.editable = false;
+ labelDisplayShadow.selectable = false;
+ labelDisplayShadow.multiline = false;
+ labelDisplayShadow.wordWrap = false;
+
+ addChild(labelDisplayShadow);
+ addChild(labelDisplay);
+ }
+
+ override protected function commitProperties():void
+ {
+ super.commitProperties();
+
+ if (labelChanged)
+ {
+ labelDisplay.text = text;
+ invalidateSize();
+ invalidateDisplayList();
+ labelChanged = false;
+ }
+ }
+
+ override protected function measure():void
+ {
+ if (labelDisplay.isTruncated)
+ labelDisplay.text = text;
+ labelDisplay.commitStyles();
+ measuredWidth = labelDisplay.getPreferredBoundsWidth();
+ measuredHeight = labelDisplay.getPreferredBoundsHeight();
+ }
+
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ if (labelDisplay.isTruncated)
+ labelDisplay.text = text;
+ labelDisplay.commitStyles();
+
+ var labelHeight:Number = labelDisplay.getPreferredBoundsHeight();
+ var labelY:Number = (unscaledHeight - labelHeight) / 2;
+
+ var labelWidth:Number = Math.min(unscaledWidth, labelDisplay.getPreferredBoundsWidth());
+ var labelX:Number = (unscaledWidth - labelWidth) / 2;
+
+ labelDisplay.setLayoutBoundsSize(labelWidth, labelHeight);
+ labelDisplay.setLayoutBoundsPosition(labelX, labelY);
+
+ labelDisplay.truncateToFit();
+
+ labelDisplayShadow.commitStyles();
+ labelDisplayShadow.setLayoutBoundsSize(labelWidth, labelHeight);
+ labelDisplayShadow.setLayoutBoundsPosition(labelX, labelY + shadowYOffset);
+
+ labelDisplayShadow.alpha = getStyle("textShadowAlpha");
+
+ // unless the label was truncated, labelDisplayShadow.text was set in
+ // the value commit handler
+ if (labelDisplay.isTruncated)
+ labelDisplayShadow.text = labelDisplay.text;
+ }
+
+ private function labelDisplay_valueCommitHandler(event:Event):void
+ {
+ labelDisplayShadow.text = labelDisplay.text;
+ }
+
+ public function get text():String
+ {
+ return _text;
+ }
+
+ public function set text(value:String):void
+ {
+ _text = value;
+ labelChanged = true;
+ invalidateProperties();
+ }
+
+ public function get isTruncated():Boolean
+ {
+ return labelDisplay.isTruncated;
+ }
+
+ public function showShadow(value:Boolean):void
+ {
+ labelDisplayShadow.visible = value;
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/TransparentActionButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/TransparentActionButtonSkin.as
new file mode 100644
index 0000000000..dadab3c2ae
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/TransparentActionButtonSkin.as
@@ -0,0 +1,108 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.display.Graphics;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.skins.mobile.assets.TransparentActionButton_down;
+import spark.skins.mobile.assets.TransparentActionButton_up;
+import spark.skins.mobile.supportClasses.ActionBarButtonSkinBase;
+import spark.skins.mobile.supportClasses.MobileSkin;
+import spark.skins.mobile320.assets.TransparentActionButton_down;
+import spark.skins.mobile320.assets.TransparentActionButton_up;
+import spark.skins.mobile480.assets.TransparentActionButton_down;
+import spark.skins.mobile480.assets.TransparentActionButton_up;
+import spark.skins.mobile640.assets.TransparentActionButton_down;
+import spark.skins.mobile640.assets.TransparentActionButton_up;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for buttons in the action area of the Spark ActionBar component
+ * in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TransparentActionButtonSkin extends ActionBarButtonSkinBase
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function TransparentActionButtonSkin()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ upBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ upBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ upBorderSkin = spark.skins.mobile320.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile320.assets.TransparentActionButton_down;
+
+ break;
+ }
+ default:
+ {
+ upBorderSkin = spark.skins.mobile.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile.assets.TransparentActionButton_down;
+
+ break;
+ }
+ }
+ }
+
+ override mx_internal function layoutBorder(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // don't call super, don't layout twice
+ // leading vertical separator is outside the left bounds of the button
+ setElementSize(border, unscaledWidth + layoutBorderSize, unscaledHeight);
+ setElementPosition(border, -layoutBorderSize, 0);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/TransparentNavigationButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/TransparentNavigationButtonSkin.as
new file mode 100644
index 0000000000..0709b65849
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/TransparentNavigationButtonSkin.as
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.display.Graphics;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.skins.mobile.assets.TransparentNavigationButton_down;
+import spark.skins.mobile.assets.TransparentNavigationButton_up;
+import spark.skins.mobile.supportClasses.ActionBarButtonSkinBase;
+import spark.skins.mobile.supportClasses.MobileSkin;
+import spark.skins.mobile320.assets.TransparentNavigationButton_down;
+import spark.skins.mobile320.assets.TransparentNavigationButton_up;
+import spark.skins.mobile480.assets.TransparentNavigationButton_down;
+import spark.skins.mobile480.assets.TransparentNavigationButton_up;
+import spark.skins.mobile640.assets.TransparentNavigationButton_down;
+import spark.skins.mobile640.assets.TransparentNavigationButton_up;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for buttons in the navigation area of the Spark ActionBar component
+ * in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TransparentNavigationButtonSkin extends ActionBarButtonSkinBase
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function TransparentNavigationButtonSkin()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ upBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ upBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ upBorderSkin = spark.skins.mobile320.assets.TransparentNavigationButton_up;
+ downBorderSkin = spark.skins.mobile320.assets.TransparentNavigationButton_down;
+
+ break;
+ }
+ default:
+ {
+ upBorderSkin = spark.skins.mobile.assets.TransparentNavigationButton_up;
+ downBorderSkin = spark.skins.mobile.assets.TransparentNavigationButton_down;
+
+ break;
+ }
+ }
+ }
+
+ override mx_internal function layoutBorder(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // trailing vertical separator is outside the right bounds of the button
+ setElementSize(border, unscaledWidth + layoutBorderSize, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/VScrollBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/VScrollBarSkin.as
new file mode 100644
index 0000000000..1a2a0df78e
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/VScrollBarSkin.as
@@ -0,0 +1,207 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.Button;
+import spark.components.VScrollBar;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for VScrollBar components in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class VScrollBarSkin extends MobileSkin
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function VScrollBarSkin()
+ {
+ super();
+
+ minHeight = 20;
+ thumbSkinClass = VScrollBarThumbSkin;
+ var paddingRight:int;
+ var paddingVertical:int;
+
+ // Depending on density set our measured width
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ minWidth = 24;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_640DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ minWidth = 18;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_480DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ minWidth = 12;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_320DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ minWidth = 9;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_240DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ minWidth = 9;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_120DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_120DPI;
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ minWidth = 6;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_DEFAULTDPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_DEFAULTDPI;
+ break;
+ }
+ }
+
+ // The minimum height is set such that, at it's smallest size, the thumb appears
+ // as high as it is wide.
+ minThumbHeight = (minWidth - paddingRight) + (paddingVertical * 2);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:VScrollBar;
+
+ /**
+ * Minimum height for the thumb
+ */
+ protected var minThumbHeight:Number;
+
+ /**
+ * Skin to use for the thumb Button skin part
+ */
+ protected var thumbSkinClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * VScrollbar track skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var track:Button;
+
+ /**
+ * VScrollbar thumb skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var thumb:Button;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Create our skin parts if necessary: track and thumb.
+ if (!track)
+ {
+ // We don't want a visible track so we set the skin to MobileSkin
+ track = new Button();
+ track.setStyle("skinClass", spark.skins.mobile.supportClasses.MobileSkin);
+ track.width = minWidth;
+ track.height = minHeight;
+ addChild(track);
+ }
+ if (!thumb)
+ {
+ thumb = new Button();
+ thumb.minHeight = minThumbHeight;
+ thumb.setStyle("skinClass", thumbSkinClass);
+ thumb.width = minWidth;
+ thumb.height = minWidth;
+ addChild(thumb);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(track, unscaledWidth, unscaledHeight);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/VScrollBarThumbSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/VScrollBarThumbSkin.as
new file mode 100644
index 0000000000..07fb0d1980
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/VScrollBarThumbSkin.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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+import spark.components.Button;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+/**
+ * ActionScript-based skin for the VScrollBar thumb skin part in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class VScrollBarThumbSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ // These constants are also accessed from VScrollBarSkin
+ mx_internal static const PADDING_RIGHT_640DPI:int = 10;
+ mx_internal static const PADDING_VERTICAL_640DPI:int = 8;
+ mx_internal static const PADDING_RIGHT_480DPI:int = 8;
+ mx_internal static const PADDING_VERTICAL_480DPI:int = 6;
+ mx_internal static const PADDING_RIGHT_320DPI:int = 5;
+ mx_internal static const PADDING_VERTICAL_320DPI:int = 4;
+ mx_internal static const PADDING_RIGHT_240DPI:int = 4;
+ mx_internal static const PADDING_VERTICAL_240DPI:int = 3;
+ mx_internal static const PADDING_RIGHT_120DPI:int = 2;
+ mx_internal static const PADDING_VERTICAL_120DPI:int = 1;
+ mx_internal static const PADDING_RIGHT_DEFAULTDPI:int = 3;
+ mx_internal static const PADDING_VERTICAL_DEFAULTDPI:int = 2;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function VScrollBarThumbSkin()
+ {
+ super();
+
+ // Depending on density set padding
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ minWidth = 19;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_640DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ minWidth = 19;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_480DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ paddingRight = PADDING_RIGHT_320DPI;
+ paddingVertical = PADDING_VERTICAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ paddingRight = PADDING_RIGHT_240DPI;
+ paddingVertical = PADDING_VERTICAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ paddingRight = PADDING_RIGHT_120DPI;
+ paddingVertical = PADDING_VERTICAL_120DPI;
+ break;
+ }
+ default:
+ {
+ paddingRight = PADDING_RIGHT_DEFAULTDPI;
+ paddingVertical = PADDING_VERTICAL_DEFAULTDPI;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Padding from the right
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingRight:int;
+
+ /**
+ * Vertical padding from top and bottom
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingVertical:int;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @protected
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var thumbWidth:Number = unscaledWidth - paddingRight;
+
+ graphics.beginFill(getStyle("color"), 1);
+ graphics.drawRect(0.5, paddingVertical + 0.5,thumbWidth, unscaledHeight - 2 * paddingVertical);
+
+ graphics.endFill();
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ViewMenuItemSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/ViewMenuItemSkin.as
new file mode 100644
index 0000000000..6a75c65caa
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ViewMenuItemSkin.as
@@ -0,0 +1,238 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.GradientType;
+import flash.display.Graphics;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.IconPlacement;
+import spark.skins.mobile.assets.ViewMenuItem_down;
+import spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile.assets.ViewMenuItem_up;
+import spark.skins.mobile.supportClasses.ButtonSkinBase;
+import spark.skins.mobile120.assets.ViewMenuItem_down;
+import spark.skins.mobile120.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile120.assets.ViewMenuItem_up;
+import spark.skins.mobile320.assets.ViewMenuItem_down;
+import spark.skins.mobile320.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile320.assets.ViewMenuItem_up;
+import spark.skins.mobile480.assets.ViewMenuItem_down;
+import spark.skins.mobile480.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile480.assets.ViewMenuItem_up;
+import spark.skins.mobile640.assets.ViewMenuItem_down;
+import spark.skins.mobile640.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile640.assets.ViewMenuItem_up;
+
+
+use namespace mx_internal;
+
+/**
+ * Default skin for ViewMenuItem. Supports a label, icon and iconPlacement and draws a background.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ViewMenuItemSkin extends ButtonSkin
+{
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ViewMenuItemSkin()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ upBorderSkin = spark.skins.mobile640.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile640.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile640.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 24;
+ layoutPaddingLeft = 24;
+ layoutPaddingRight = 24;
+ layoutPaddingTop = 24;
+ layoutPaddingBottom = 24;
+ layoutBorderSize = 3;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ // Note provisional may need changes
+ upBorderSkin = spark.skins.mobile.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 16;
+ layoutPaddingLeft = 16;
+ layoutPaddingRight = 16;
+ layoutPaddingTop = 16;
+ layoutPaddingBottom = 16;
+ layoutBorderSize = 2;
+
+ break;
+
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ upBorderSkin = spark.skins.mobile320.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile320.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile320.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 12;
+ layoutPaddingLeft = 12;
+ layoutPaddingRight = 12;
+ layoutPaddingTop = 12;
+ layoutPaddingBottom = 12;
+ layoutBorderSize = 2;
+
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ upBorderSkin = spark.skins.mobile.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 8;
+ layoutPaddingLeft = 8;
+ layoutPaddingRight = 8;
+ layoutPaddingTop = 8;
+ layoutPaddingBottom = 8;
+ layoutBorderSize = 1;
+
+ break;
+
+ }
+ case DPIClassification.DPI_120:
+ {
+ upBorderSkin = spark.skins.mobile120.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile120.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile120.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 4;
+ layoutPaddingLeft = 4;
+ layoutPaddingRight = 4;
+ layoutPaddingTop = 4;
+ layoutPaddingBottom = 4;
+ layoutBorderSize = 1;
+
+ break;
+
+ }
+ default:
+ {
+ upBorderSkin = spark.skins.mobile.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 6;
+ layoutPaddingLeft = 6;
+ layoutPaddingRight = 6;
+ layoutPaddingTop = 6;
+ layoutPaddingBottom = 6;
+ layoutBorderSize = 1;
+ }
+ }
+
+ }
+
+ /**
+ * Class to use for the border in the showsCaret state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ * @default Button_down
+ */
+ protected var showsCaretBorderSkin:Class;
+
+ /**
+ * @private
+ */
+ override protected function getBorderClassForCurrentState():Class
+ {
+ var borderClass:Class = super.getBorderClassForCurrentState();
+
+ if (currentState == "showsCaret")
+ borderClass = showsCaretBorderSkin;
+
+ return borderClass;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ var iconPlacement:String = getStyle("iconPlacement");
+ useCenterAlignment = (iconPlacement == IconPlacement.LEFT)
+ || (iconPlacement == IconPlacement.RIGHT);
+
+ super.layoutContents(unscaledWidth, unscaledHeight);
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // omit call to super.drawBackground(), drawRect instead
+
+ if (currentState == "showsCaret" || currentState == "down")
+ {
+ graphics.beginFill(getStyle("focusColor"));
+ }
+ else
+ {
+ colorMatrix.createGradientBox(unscaledWidth,
+ unscaledHeight,
+ Math.PI / 2, 0, 0);
+ var chromeColor:uint = getStyle("chromeColor");
+
+ graphics.beginGradientFill(GradientType.LINEAR,
+ [chromeColor, chromeColor],
+ [1.0, 1.0],
+ [0, 255],
+ colorMatrix);
+ }
+ graphics.drawRect(0,0,unscaledWidth,unscaledHeight);
+ graphics.lineStyle(0.5,0,0.2);
+ graphics.drawRect(0,unscaledHeight,unscaledWidth,0.5);
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/ViewMenuSkin.mxml b/frameworks/projects/mobiletheme/src/spark/skins/android4/ViewMenuSkin.mxml
new file mode 100644
index 0000000000..67fd754ff5
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/ViewMenuSkin.mxml
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ActionBarBackground.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ActionBarBackground.fxg
new file mode 100644
index 0000000000..febd3f71aa
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ActionBarBackground.fxg
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
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 0000000000..e04248f34b
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/BusyIndicator.fxg
@@ -0,0 +1,64 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_down.fxg
new file mode 100644
index 0000000000..4a7c5f7f2d
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_down.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_selectedDown.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_selectedDown.fxg
new file mode 100644
index 0000000000..110f940605
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_selectedDown.fxg
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_selectedUp.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_selectedUp.fxg
new file mode 100644
index 0000000000..52b1a90b44
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_selectedUp.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_up.fxg
new file mode 100644
index 0000000000..59b9cd9144
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarFirstButton_up.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_down.fxg
new file mode 100644
index 0000000000..4e4f80b7af
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_down.fxg
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_selectedDown.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_selectedDown.fxg
new file mode 100644
index 0000000000..ec3707782d
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_selectedDown.fxg
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_selectedUp.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_selectedUp.fxg
new file mode 100644
index 0000000000..88a46439a8
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_selectedUp.fxg
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_up.fxg
new file mode 100644
index 0000000000..be1b61922d
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ButtonBarMiddleButton_up.fxg
@@ -0,0 +1,65 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/Button_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/Button_down.fxg
new file mode 100644
index 0000000000..79a535c0db
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/Button_down.fxg
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/Button_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/Button_up.fxg
new file mode 100644
index 0000000000..af7d033a3f
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/Button_up.fxg
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CalloutContentBackground.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CalloutContentBackground.fxg
new file mode 100644
index 0000000000..8442b969b6
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CalloutContentBackground.fxg
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_down.fxg
new file mode 100644
index 0000000000..426df3d2f7
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_down.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_downSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_downSelected.fxg
new file mode 100644
index 0000000000..ea7c3c43cf
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_downSelected.fxg
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_downSymbolSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_downSymbolSelected.fxg
new file mode 100644
index 0000000000..f59d001cb8
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_downSymbolSelected.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_up.fxg
new file mode 100644
index 0000000000..9d652603bf
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_up.fxg
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_upSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_upSelected.fxg
new file mode 100644
index 0000000000..f51d7df976
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_upSelected.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_upSymbolSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_upSymbolSelected.fxg
new file mode 100644
index 0000000000..a728d3d9ab
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/CheckBox_upSymbolSelected.fxg
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderThumb_normal.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderThumb_normal.fxg
new file mode 100644
index 0000000000..c046673755
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderThumb_normal.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderThumb_pressed.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderThumb_pressed.fxg
new file mode 100644
index 0000000000..416f7950fc
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderThumb_pressed.fxg
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderTrack.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderTrack.fxg
new file mode 100644
index 0000000000..ee464e0b16
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderTrack.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderTrack_filled.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderTrack_filled.fxg
new file mode 100644
index 0000000000..c4d4f74bf5
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/HSliderTrack_filled.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_down.fxg
new file mode 100644
index 0000000000..dc744148d3
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_down.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_downSymbolSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_downSymbolSelected.fxg
new file mode 100644
index 0000000000..374c9fc056
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_downSymbolSelected.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_up.fxg
new file mode 100644
index 0000000000..4110262b43
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_up.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_upSymbolSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_upSymbolSelected.fxg
new file mode 100644
index 0000000000..5b844b6e62
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/RadioButton_upSymbolSelected.fxg
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerBackground.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerBackground.fxg
new file mode 100644
index 0000000000..78d8c59701
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerBackground.fxg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerSelectionIndicator.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerSelectionIndicator.fxg
new file mode 100644
index 0000000000..067afb1e11
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerSelectionIndicator.fxg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerShadow.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerShadow.fxg
new file mode 100644
index 0000000000..41c1955e7a
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/SpinnerListContainerShadow.fxg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchBackground.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchBackground.fxg
new file mode 100644
index 0000000000..b26457326f
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchBackground.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchThumb_off.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchThumb_off.fxg
new file mode 100644
index 0000000000..8f9d046b9f
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchThumb_off.fxg
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchThumb_on.fxg b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchThumb_on.fxg
new file mode 100644
index 0000000000..d003f72cbf
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/ToggleSwitchThumb_on.fxg
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/fonts/Roboto-Bold.ttf b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/fonts/Roboto-Bold.ttf
new file mode 100644
index 0000000000..aaf374d2cc
Binary files /dev/null and b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/fonts/Roboto-Bold.ttf differ
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/fonts/Roboto-Regular.ttf b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/fonts/Roboto-Regular.ttf
new file mode 100644
index 0000000000..3e6e2e7613
Binary files /dev/null and b/frameworks/projects/mobiletheme/src/spark/skins/android4/assets/fonts/Roboto-Regular.ttf differ
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/CalloutArrow.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/CalloutArrow.as
new file mode 100644
index 0000000000..64f6e0cf17
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/CalloutArrow.as
@@ -0,0 +1,457 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.supportClasses
+{
+import flash.display.BlendMode;
+import flash.display.GradientType;
+import flash.display.Graphics;
+import flash.display.GraphicsPathCommand;
+import flash.display.Sprite;
+
+import mx.core.DPIClassification;
+import mx.core.FlexGlobals;
+import mx.core.IVisualElement;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.utils.ColorUtil;
+
+import spark.components.Application;
+import spark.components.ArrowDirection;
+import spark.components.Callout;
+import spark.skins.android4.CalloutSkin;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * The arrow skin part for CalloutSkin.
+ *
+ * @see spark.skin.mobile.CalloutSkin
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+public class CalloutArrow extends UIComponent
+{
+ public function CalloutArrow()
+ {
+ super();
+
+ useBackgroundGradient = true;
+
+ var applicationDPI:Number = DPIClassification.DPI_160;
+ if (FlexGlobals.topLevelApplication is Application)
+ {
+ applicationDPI = Application(FlexGlobals.topLevelApplication).applicationDPI;
+ }
+
+ // Copy DPI-specific values from CalloutSkin
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ // Note provisional may need changes
+ gap = 32;
+ backgroundGradientHeight = 440;
+ highlightWeight = 4;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ // Note provisional may need changes
+ gap = 24;
+ backgroundGradientHeight = 330;
+ highlightWeight = 3;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ gap = 16;
+ backgroundGradientHeight = 220;
+ highlightWeight = 2;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ gap = 12;
+ backgroundGradientHeight = 165;
+ highlightWeight = 1;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ // Note provisional may need changes
+ gap = 6;
+ backgroundGradientHeight = 83;
+ highlightWeight = 1;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ gap = 8;
+ backgroundGradientHeight = 110;
+ highlightWeight = 1;
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * A gap on the frame-adjacent side of the arrow graphic to avoid
+ * drawing past the CalloutSkin backgroundCornerRadius.
+ *
+ *
The default implementation matches the gap value with the
+ * backgroundCornerRadius value in CalloutSkin.
+ *
+ * @see spark.skins.mobile.CalloutSkin#backgroundCornerRadius
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var gap:Number;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#backgroundGradientHeight
+ */
+ protected var backgroundGradientHeight:Number;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#highlightWeight
+ */
+ private var highlightWeight:Number;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#useBackgroundGradient
+ */
+ protected var useBackgroundGradient:Boolean;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#borderColor
+ */
+ protected var borderColor:Number = -1; // if not set
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#borderThickness
+ */
+ protected var borderThickness:Number = -1 ; // marker that borderThickness was not set directly
+
+ /**
+ * @private
+ * A sibling of the arrow used to erase the drop shadow in CalloutSkin
+ */
+ private var eraseFill:Sprite;
+
+ /* helper private accessors */
+
+ /* returns borderThickness from style if member is -1, or borderThickness. Returns 0 if NaN */
+ private function get actualBorderThickness():Number
+ {
+ return calloutSkin.actualBorderThickness;
+ }
+
+ private function get actualBorderColor():uint
+ {
+ return calloutSkin.actualBorderColor;
+ }
+
+ protected function get calloutSkin():CalloutSkin
+ {
+ return parent as CalloutSkin ;
+ }
+
+ protected function get calloutHostComponent():Callout {
+ return calloutSkin.hostComponent;
+ }
+
+ /**
+ * @private
+ */
+
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ // eraseFill has the same position and arrow shape in order to erase
+ // the drop shadow under the arrow when backgroundAlpha < 1
+ eraseFill = new Sprite();
+ eraseFill.blendMode = BlendMode.ERASE;
+
+ // layer eraseFill below the arrow
+ parent.addChildAt(eraseFill, parent.getChildIndex(this));
+ }
+
+ /**
+ * @private
+ */
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+ graphics.clear();
+ eraseFill.graphics.clear();
+ var hostComponent: Callout = calloutHostComponent;
+ var arrowDirection:String = hostComponent.arrowDirection;
+
+ if (arrowDirection == ArrowDirection.NONE)
+ return;
+
+ // when drawing the arrow, compensate for cornerRadius via padding
+ var arrowGraphics:Graphics = this.graphics;
+ var eraseGraphics:Graphics = eraseFill.graphics;
+ var arrowWidth:Number = unscaledWidth;
+ var arrowHeight:Number = unscaledHeight;
+ var arrowX:Number = 0;
+ var arrowY:Number = 0;
+ var arrowTipX:Number = 0;
+ var arrowTipY:Number = 0;
+ var arrowEndX:Number = 0;
+ var arrowEndY:Number = 0;
+
+ var borderWeight:Number = actualBorderThickness;
+ var showBorder:Boolean = borderWeight > 0;
+
+ var borderHalf:Number = borderWeight / 2;
+ var isHorizontal:Boolean = false;
+
+ if ((arrowDirection == ArrowDirection.LEFT) ||
+ (arrowDirection == ArrowDirection.RIGHT))
+ {
+ isHorizontal = true;
+
+ arrowX = -borderHalf;
+ arrowY = gap;
+ arrowHeight = arrowHeight - (gap * 2);
+
+ arrowTipX = arrowWidth - borderHalf;
+ arrowTipY = arrowY + (arrowHeight / 2);
+
+ arrowEndX = arrowX;
+ arrowEndY = arrowY + arrowHeight;
+
+ // flip coordinates to point left
+ if (arrowDirection == ArrowDirection.LEFT)
+ {
+ arrowX = arrowWidth - arrowX;
+ arrowTipX = arrowWidth - arrowTipX;
+ arrowEndX = arrowWidth - arrowEndX;
+ }
+ }
+ else
+ {
+ arrowX = gap;
+ arrowY = -borderHalf;
+ arrowWidth = arrowWidth - (gap * 2);
+
+ arrowTipX = arrowX + (arrowWidth / 2);
+ arrowTipY = arrowHeight - borderHalf;
+
+ arrowEndX = arrowX + arrowWidth;
+ arrowEndY = arrowY;
+
+ // flip coordinates to point up
+ if (hostComponent.arrowDirection == ArrowDirection.UP)
+ {
+ arrowY = arrowHeight - arrowY;
+ arrowTipY = arrowHeight - arrowTipY;
+ arrowEndY = arrowHeight - arrowEndY;
+ }
+ }
+
+ var commands:Vector. = new Vector.(3, true);
+ commands[0] = GraphicsPathCommand.MOVE_TO;
+ commands[1] = GraphicsPathCommand.LINE_TO;
+ commands[2] = GraphicsPathCommand.LINE_TO;
+
+ var coords:Vector. = new Vector.(6, true);
+ coords[0] = arrowX;
+ coords[1] = arrowY;
+ coords[2] = arrowTipX
+ coords[3] = arrowTipY;
+ coords[4] = arrowEndX
+ coords[5] = arrowEndY;
+
+ var backgroundColor:Number = getStyle("backgroundColor");
+ var backgroundAlpha:Number = getStyle("backgroundAlpha");
+
+ if (useBackgroundGradient)
+ {
+ var backgroundColorTop:Number = ColorUtil.adjustBrightness2(backgroundColor,
+ CalloutSkin.BACKGROUND_GRADIENT_BRIGHTNESS_TOP);
+ var backgroundColorBottom:Number = ColorUtil.adjustBrightness2(backgroundColor,
+ CalloutSkin.BACKGROUND_GRADIENT_BRIGHTNESS_BOTTOM);
+
+ // translate the gradient based on the arrow position
+ MobileSkin.colorMatrix.createGradientBox(unscaledWidth,
+ backgroundGradientHeight, Math.PI / 2, 0, -getLayoutBoundsY());
+
+ arrowGraphics.beginGradientFill(GradientType.LINEAR,
+ [backgroundColorTop, backgroundColorBottom],
+ [backgroundAlpha, backgroundAlpha],
+ [0, 255],
+ MobileSkin.colorMatrix);
+ }
+ else
+ {
+ arrowGraphics.beginFill(backgroundColor, backgroundAlpha);
+ }
+
+ // cover the adjacent border from the callout frame
+ if (showBorder)
+ {
+ var coverX:Number = 0;
+ var coverY:Number = 0;
+ var coverWidth:Number = 0;
+ var coverHeight:Number = 0;
+
+ switch (arrowDirection)
+ {
+ case ArrowDirection.UP:
+ {
+ coverX = arrowX;
+ coverY = arrowY;
+ coverWidth = arrowWidth;
+ coverHeight = borderWeight;
+ break;
+ }
+ case ArrowDirection.DOWN:
+ {
+ coverX = arrowX;
+ coverY = -borderWeight;
+ coverWidth = arrowWidth;
+ coverHeight = borderWeight;
+ break;
+ }
+ case ArrowDirection.LEFT:
+ {
+ coverX = arrowX;
+ coverY = arrowY;
+ coverWidth = borderWeight;
+ coverHeight = arrowHeight;
+ break;
+ }
+ case ArrowDirection.RIGHT:
+ {
+ coverX = -borderWeight;
+ coverY = arrowY;
+ coverWidth = borderWeight;
+ coverHeight = arrowHeight;
+ break;
+ }
+ }
+
+ arrowGraphics.drawRect(coverX, coverY, coverWidth, coverHeight);
+ }
+
+ // erase the drop shadow from the CalloutSkin
+ if (backgroundAlpha < 1)
+ {
+ // move eraseFill to the same position as the arrow
+ eraseFill.x = getLayoutBoundsX()
+ eraseFill.y = getLayoutBoundsY();
+
+ // draw the arrow shape
+ eraseGraphics.beginFill(0, 1);
+ eraseGraphics.drawPath(commands, coords);
+ eraseGraphics.endFill();
+ }
+
+ // draw arrow path
+ if (showBorder)
+ arrowGraphics.lineStyle(borderWeight, actualBorderColor, 1, true);
+
+ arrowGraphics.drawPath(commands, coords);
+ arrowGraphics.endFill();
+
+ // adjust the highlight position to the origin of the callout
+ var isArrowUp:Boolean = (arrowDirection == ArrowDirection.UP);
+ var offsetY:Number = (isArrowUp) ? unscaledHeight : -getLayoutBoundsY();
+
+ // highlight starts after the backgroundCornerRadius
+ var highlightX:Number = gap - getLayoutBoundsX();
+
+ // highlight Y position is based on the stroke weight
+ var highlightOffset:Number = (highlightWeight * 1.5);
+ var highlightY:Number = highlightOffset + offsetY;
+
+ // highlight width spans the callout width minus the corner radius
+ var highlightWidth:Number = IVisualElement(calloutSkin).getLayoutBoundsWidth() - (gap * 2);
+
+ if (isHorizontal)
+ {
+ highlightWidth -= arrowWidth;
+
+ if (arrowDirection == ArrowDirection.LEFT)
+ highlightX += arrowWidth;
+ }
+
+ // highlight on the top edge is drawn in the arrow only in the UP direction
+ if (useBackgroundGradient)
+ {
+ if (isArrowUp)
+ {
+ // highlight follows the top edge, including the arrow
+ var rightWidth:Number = highlightWidth - arrowWidth;
+
+ // highlight style
+ arrowGraphics.lineStyle(highlightWeight, 0xFFFFFF, 0.2 * backgroundAlpha);
+
+ // in the arrow coordinate space, the highlightX must be less than 0
+ if (highlightX < 0)
+ {
+ arrowGraphics.moveTo(highlightX, highlightY);
+ arrowGraphics.lineTo(arrowX, highlightY);
+
+ // compute the remaining highlight
+ rightWidth -= (arrowX - highlightX);
+ }
+
+ // arrow highlight (adjust Y downward)
+ coords[1] = arrowY + highlightOffset;
+ coords[3] = arrowTipY + highlightOffset;
+ coords[5] = arrowEndY + highlightOffset;
+ arrowGraphics.drawPath(commands, coords);
+
+ // right side
+ if (rightWidth > 0)
+ {
+ arrowGraphics.moveTo(arrowEndX, highlightY);
+ arrowGraphics.lineTo(arrowEndX + rightWidth, highlightY);
+ }
+ }
+ else
+ {
+ // straight line across the top
+ arrowGraphics.lineStyle(highlightWeight, 0xFFFFFF, 0.2 * backgroundAlpha);
+ arrowGraphics.moveTo(highlightX, highlightY);
+ arrowGraphics.lineTo(highlightX + highlightWidth, highlightY);
+ }
+ }
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/StageTextSkinBase.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/StageTextSkinBase.as
new file mode 100644
index 0000000000..3dc1966264
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/StageTextSkinBase.as
@@ -0,0 +1,402 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.supportClasses
+{
+import flash.display.DisplayObject;
+import flash.events.FocusEvent;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.supportClasses.IStyleableEditableText;
+import spark.components.supportClasses.SkinnableTextBase;
+import spark.components.supportClasses.StyleableStageText;
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.IDisplayText;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for text input controls in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+public class StageTextSkinBase extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ *
+ */
+ public function StageTextSkinBase()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultWidth = 1200;
+ measuredDefaultHeight = 132;
+ layoutBorderSize = 4;
+ flatheight = 9;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ measuredDefaultWidth = 880;
+ measuredDefaultHeight = 100;
+ layoutBorderSize = 3;
+ flatheight = 7;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultWidth = 600;
+ measuredDefaultHeight = 66;
+ layoutBorderSize = 2;
+ flatheight = 6;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultWidth = 440;
+ measuredDefaultHeight = 50;
+ layoutBorderSize = 2;
+ flatheight = 5;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultWidth = 220;
+ measuredDefaultHeight = 25;
+ layoutBorderSize = 1;
+ flatheight = 2;
+ break;
+ }
+ default:
+ {
+ measuredDefaultWidth = 300;
+ measuredDefaultHeight = 33;
+ layoutBorderSize = 1;
+ flatheight = 3;
+ break;
+ }
+
+ }
+ addEventListener(FocusEvent.FOCUS_IN, focusChangeHandler);
+ addEventListener(FocusEvent.FOCUS_OUT, focusChangeHandler);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Graphics variables
+ //
+ //--------------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the border's thickness.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ protected var layoutBorderSize:uint;
+
+ protected var flatheight:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var isFocused:Boolean = false;
+
+ /**
+ * @private
+ *
+ * Instance of the border graphics.
+ */
+ protected var border:DisplayObject;
+
+ private var borderVisibleChanged:Boolean = false;
+
+ /**
+ * @private
+ *
+ * Multiline flag.
+ */
+ protected var multiline:Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * textDisplay skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public var textDisplay:IStyleableEditableText;
+
+ [Bindable]
+ /**
+ * Bindable promptDisplay skin part. Bindings fire when promptDisplay is
+ * removed and added for proper updating by the SkinnableTextBase.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public var promptDisplay:IDisplayText;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!textDisplay)
+ {
+ textDisplay = createTextDisplay();
+ textDisplay.editable = true;
+ textDisplay.styleName = this;
+ this.addChild(DisplayObject(textDisplay));
+ }
+ }
+
+ /** Could be overridden by subclasses
+ *
+ * @return instance of IStyleableEditableText
+ */
+ protected function createTextDisplay():IStyleableEditableText
+ {
+ return new StyleableStageText(multiline);
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var contentBackgroundColor:uint = getStyle("contentBackgroundColor");
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ //change border color and thickness when in focus
+ var borderColor:uint = isFocused ? getStyle("focusColor") : getStyle("borderColor");
+ var selectWidth:uint = isFocused ? layoutBorderSize + 1 : layoutBorderSize;
+ if (isNaN(contentBackgroundAlpha))
+ {
+ contentBackgroundAlpha = 1;
+ }
+ var halfGap:int = flatheight * 2;
+ // change the border type
+ if (getStyle("contentBackgroundBorder") == "flat")
+ {
+ //background
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth, unscaledHeight - flatheight);
+ graphics.endFill();
+ //begin flat border
+ graphics.beginFill(borderColor, 1);
+ //left half border
+ graphics.drawRect(0, unscaledHeight - halfGap, selectWidth, flatheight );
+ //bottom border
+ graphics.drawRect(0, unscaledHeight - flatheight, unscaledWidth, selectWidth);
+ //right border
+ graphics.drawRect(unscaledWidth - selectWidth, unscaledHeight - halfGap, selectWidth, flatheight);
+ graphics.endFill();
+ }
+ else if (getStyle("contentBackgroundBorder") == "rectangle")
+ {
+ var borderWidth:uint = layoutBorderSize * 2;
+ //rectangle border and background
+ graphics.lineStyle(selectWidth, borderColor, 1);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || styleProp == "borderVisible")
+ {
+ borderVisibleChanged = true;
+ invalidateProperties();
+ }
+
+ if (allStyles || styleProp.indexOf("padding") == 0)
+ {
+ invalidateDisplayList();
+ }
+ super.styleChanged(styleProp);
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+
+ var showPrompt:Boolean = currentState.indexOf("WithPrompt") != -1;
+
+ if (showPrompt && !promptDisplay)
+ {
+ promptDisplay = createPromptDisplay();
+ promptDisplay.addEventListener(FocusEvent.FOCUS_IN, promptDisplay_focusInHandler);
+ }
+ else if (!showPrompt && promptDisplay)
+ {
+ promptDisplay.removeEventListener(FocusEvent.FOCUS_IN, promptDisplay_focusInHandler);
+ removeChild(promptDisplay as DisplayObject);
+ promptDisplay = null;
+ }
+ super.commitCurrentState();
+
+ invalidateDisplayList();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * Create a control appropriate for displaying the prompt text in a mobile
+ * input field.
+ */
+ protected function createPromptDisplay():IDisplayText
+ {
+ var prompt:StyleableTextField = StyleableTextField(createInFontContext(StyleableTextField));
+ prompt.styleName = this;
+ prompt.editable = false;
+ prompt.mouseEnabled = false;
+ prompt.useTightTextBounds = false;
+ // StageText objects appear in their own layer on top of the display
+ // list. So, even though this prompt may be created after the StageText
+ // for textDisplay, textDisplay will still be on top.
+ addChild(prompt);
+
+ return prompt;
+ }
+
+ /**
+ * @private
+ * Utility function used by subclasses' measure functions to measure their
+ * text host components.
+ */
+ protected function measureTextComponent(hostComponent:SkinnableTextBase):void
+ {
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+ var textHeight:Number = getStyle("fontSize");
+
+ if (textDisplay)
+ {
+ textHeight = getElementPreferredHeight(textDisplay);
+ }
+ // width is based on maxChars (if set)
+ if (hostComponent && hostComponent.maxChars)
+ {
+ // Grab the fontSize and subtract 2 as the pixel value for each character.
+ // This is just an approximation, but it appears to be a reasonable one
+ // for most input and most font.
+ var characterWidth:int = Math.max(1, (textHeight - 2));
+ measuredWidth = (characterWidth * hostComponent.maxChars) + paddingLeft + paddingRight;
+ }
+
+ measuredHeight = paddingTop + textHeight + paddingBottom;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event handlers
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Listen to see if the component gains focus then change the style to selected
+ */
+ private function focusChangeHandler(event:FocusEvent):void
+ {
+ isFocused = event.type == FocusEvent.FOCUS_IN;
+ invalidateDisplayList();
+ }
+
+ /**
+ * If the prompt is focused, we need to move focus to the textDisplay
+ * StageText. This needs to happen outside of the process of setting focus
+ * to the prompt, so we use callLater to do that.
+ */
+ private function focusTextDisplay():void
+ {
+ textDisplay.setFocus();
+ }
+
+ private function promptDisplay_focusInHandler(event:FocusEvent):void
+ {
+ callLater(focusTextDisplay);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/TextSkinBase.as b/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/TextSkinBase.as
new file mode 100644
index 0000000000..31bf7eaa96
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/android4/supportClasses/TextSkinBase.as
@@ -0,0 +1,213 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.supportClasses
+{
+
+ import flash.display.DisplayObject;
+
+ import mx.core.mx_internal;
+
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ use namespace mx_internal;
+
+ /**
+ * ActionScript-based skin for text input controls in mobile applications that
+ * uses a StyleableTextField class for the text display.
+ *
+ * @see spark.components.supportClasses.StyleableTextField
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class TextSkinBase extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function TextSkinBase()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Graphics variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the border.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the corner radius.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+
+ protected var layoutBorderSize:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ *
+ * Instance of the border graphics.
+ */
+ protected var border:DisplayObject;
+
+ private var borderVisibleChanged:Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * textDisplay skin part.
+ */
+ public var textDisplay:StyleableTextField;
+
+ [Bindable]
+ /**
+ * Bindable promptDisplay skin part. Bindings fire when promptDisplay is
+ * removed and added for proper updating by the SkinnableTextBase.
+ */
+ public var promptDisplay:StyleableTextField;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!textDisplay)
+ {
+ textDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ textDisplay.styleName = this;
+ textDisplay.editable = true;
+ textDisplay.useTightTextBounds = false;
+ addChild(textDisplay);
+ }
+ }
+
+ /**
+ * @private
+ */
+ protected function createPromptDisplay():StyleableTextField
+ {
+ var prompt:StyleableTextField = StyleableTextField(createInFontContext(StyleableTextField));
+ prompt.styleName = this;
+ prompt.editable = false;
+ prompt.mouseEnabled = false;
+ prompt.useTightTextBounds = false;
+ prompt.focusEnabled = false;
+ return prompt;
+ }
+
+ /**
+ * @private
+ */
+
+ override public function styleChanged(styleProp:String):void
+ {
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || styleProp == "borderVisible")
+ {
+ borderVisibleChanged = true;
+ invalidateProperties();
+ }
+
+ if (allStyles || styleProp.indexOf("padding") == 0)
+ {
+ invalidateDisplayList();
+ }
+
+ super.styleChanged(styleProp);
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+
+ var showPrompt:Boolean = currentState.indexOf("WithPrompt") >= 0;
+
+ if (showPrompt && !promptDisplay)
+ {
+ promptDisplay = createPromptDisplay();
+ addChild(promptDisplay);
+ }
+ else if (!showPrompt && promptDisplay)
+ {
+ removeChild(promptDisplay);
+ promptDisplay = null;
+ }
+
+ invalidateDisplayList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ActionBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ActionBarSkin.as
new file mode 100644
index 0000000000..1e46d38427
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ActionBarSkin.as
@@ -0,0 +1,727 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.GradientType;
+import flash.events.Event;
+import flash.text.TextFormatAlign;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+import mx.utils.ColorUtil;
+
+import spark.components.ActionBar;
+import spark.components.Group;
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.SpriteVisualElement;
+import spark.layouts.HorizontalAlign;
+import spark.layouts.HorizontalLayout;
+import spark.layouts.VerticalAlign;
+import spark.skins.ios7.assets.ActionBarBackground;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for the Spark ActionBar component in mobile
+ * applications.
+ *
+ * @see spark.components.ActionBar
+ * @see spark.skins.mobile.TransparentNavigationButtonSkin
+ * @see spark.skins.mobile.BeveledBackButtonSkin
+ * @see spark.skins.mobile.TransparentActionButtonSkin
+ * @see spark.skins.mobile.BeveledActionButtonSkin
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ActionBarSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ mx_internal static const ACTIONBAR_CHROME_COLOR_RATIOS:Array = [0, 80];
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ActionBarSkin()
+ {
+ super();
+
+ borderClass = spark.skins.ios7.assets.ActionBarBackground;
+
+ switch (applicationDPI)
+ {
+
+ case DPIClassification.DPI_640:
+ {
+ borderSize = 2;
+ layoutContentGroupHeight = 172;
+ layoutTitleGroupHorizontalPadding = 52;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ borderSize = 2;
+ layoutContentGroupHeight = 130;
+ layoutTitleGroupHorizontalPadding = 40;
+
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ borderSize = 2;
+ layoutContentGroupHeight = 86;
+ layoutTitleGroupHorizontalPadding = 26;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ borderSize = 1;
+ layoutContentGroupHeight = 65;
+ layoutTitleGroupHorizontalPadding = 20;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ borderSize = 1;
+ layoutContentGroupHeight = 32;
+ layoutTitleGroupHorizontalPadding = 10;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ borderSize = 1;
+ layoutContentGroupHeight = 43;
+ layoutTitleGroupHorizontalPadding = 13;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Graphics variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * FXG Class reference for the ActionBar background border graphic.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var borderClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ private var borderSize:uint;
+
+ /**
+ * Default height for navigationGroup, titleGroup and actionGroup.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var layoutContentGroupHeight:uint;
+
+ /**
+ * Default horizontal padding for the titleGroup and titleDisplay.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var layoutTitleGroupHorizontalPadding:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:ActionBar;
+
+ /**
+ * @private
+ */
+ private var _navigationVisible:Boolean = false;
+
+ /**
+ * @private
+ */
+ private var _titleContentVisible:Boolean = false;
+
+ /**
+ * @private
+ */
+ private var _actionVisible:Boolean = false;
+
+ /**
+ * @private
+ */
+ private var border:SpriteVisualElement;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.components.ActionBar#navigationGroup
+ */
+ public var navigationGroup:Group;
+
+ /**
+ * @copy spark.components.ActionBar#titleGroup
+ */
+ public var titleGroup:Group;
+
+ /**
+ * @copy spark.components.ActionBar#actionGroup
+ */
+ public var actionGroup:Group;
+
+ /**
+ * @copy spark.components.ActionBar#titleDisplay
+ *
+ * @private
+ * Wraps a StyleableTextField in a UIComponent to be compatible with
+ * ViewTransition effects.
+ */
+ public var titleDisplay:TitleDisplayComponent;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ if (borderClass)
+ {
+ border = new borderClass();
+ addChild(border);
+ }
+
+ navigationGroup = new Group();
+ var hLayout:HorizontalLayout = new HorizontalLayout();
+ hLayout.horizontalAlign = HorizontalAlign.LEFT;
+ hLayout.verticalAlign = VerticalAlign.MIDDLE;
+ hLayout.gap = 0;
+ hLayout.paddingLeft = hLayout.paddingTop = hLayout.paddingRight =
+ hLayout.paddingBottom = 0;
+ navigationGroup.layout = hLayout;
+ navigationGroup.id = "navigationGroup";
+
+ titleGroup = new Group();
+ hLayout = new HorizontalLayout();
+ hLayout.horizontalAlign = HorizontalAlign.LEFT;
+ hLayout.verticalAlign = VerticalAlign.MIDDLE;
+ hLayout.gap = 0;
+ hLayout.paddingLeft = hLayout.paddingRight = layoutTitleGroupHorizontalPadding;
+ hLayout.paddingTop = hLayout.paddingBottom = 0;
+ titleGroup.layout = hLayout;
+ titleGroup.id = "titleGroup";
+
+ actionGroup = new Group();
+ hLayout = new HorizontalLayout();
+ hLayout.horizontalAlign = HorizontalAlign.RIGHT;
+ hLayout.verticalAlign = VerticalAlign.MIDDLE;
+ hLayout.gap = 0;
+ hLayout.paddingLeft = hLayout.paddingTop = hLayout.paddingRight =
+ hLayout.paddingBottom = 0;
+ actionGroup.layout = hLayout;
+ actionGroup.id = "actionGroup";
+
+ titleDisplay = new TitleDisplayComponent();
+ titleDisplay.id = "titleDisplay";
+
+ // initialize titleAlign style (center is managed explicitly in layoutContents)
+ var titleAlign:String = getStyle("titleAlign");
+ titleAlign = (titleAlign == "center") ? TextFormatAlign.LEFT : titleAlign;
+ titleDisplay.setStyle("textAlign", titleAlign);
+
+ addChild(navigationGroup);
+ addChild(titleGroup);
+ addChild(actionGroup);
+ addChild(titleDisplay);
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ var titleWidth:Number = 0;
+ var titleHeight:Number = 0;
+
+ if (_titleContentVisible)
+ {
+ titleWidth = titleGroup.getPreferredBoundsWidth();
+ titleHeight = titleGroup.getPreferredBoundsHeight();
+ }
+ else
+ {
+ // use titleLayout for paddingLeft and paddingRight
+ var layoutObject:Object = hostComponent.titleLayout;
+ titleWidth = ((layoutObject.paddingLeft) ? Number(layoutObject.paddingLeft) : 0)
+ + ((layoutObject.paddingRight) ? Number(layoutObject.paddingRight) : 0)
+ + titleDisplay.getPreferredBoundsWidth();
+
+ titleHeight = titleDisplay.getPreferredBoundsHeight();
+ }
+
+ measuredWidth =
+ getStyle("paddingLeft")
+ + navigationGroup.getPreferredBoundsWidth()
+ + titleWidth
+ + actionGroup.getPreferredBoundsWidth()
+ + getStyle("paddingRight");
+
+ // measuredHeight is contentGroupHeight, 2x border on top and bottom
+ measuredHeight =
+ getStyle("paddingTop")
+ + Math.max(layoutContentGroupHeight,
+ navigationGroup.getPreferredBoundsHeight(),
+ actionGroup.getPreferredBoundsHeight(),
+ titleHeight)
+ + getStyle("paddingBottom");
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ _titleContentVisible = currentState.indexOf("titleContent") >= 0;
+ _navigationVisible = currentState.indexOf("Navigation") >= 0;
+ _actionVisible = currentState.indexOf("Action") >= 0;
+
+ invalidateSize();
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ if (titleDisplay)
+ {
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || (styleProp == "titleAlign"))
+ {
+ var titleAlign:String = getStyle("titleAlign");
+
+ if (titleAlign == "center")
+ {
+ // If the title align is set to center, the alignment is set to LEFT
+ // so that the skin can manually center the component in layoutContents
+ titleDisplay.setStyle("textAlign", TextFormatAlign.LEFT);
+ }
+ else
+ {
+ titleDisplay.setStyle("textAlign", titleAlign);
+ }
+ }
+ }
+
+ super.styleChanged(styleProp);
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ var navigationGroupWidth:Number = 0;
+
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var titleCompX:Number = paddingLeft;
+ var titleCompWidth:Number = 0;
+
+ var actionGroupX:Number = unscaledWidth;
+ var actionGroupWidth:Number = 0;
+
+ // remove top and bottom padding from content group height
+ var contentGroupsHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+
+ if (border)
+ {
+ // FXG uses scale-9, drop shadow is drawn outside the bounds
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ }
+
+ // position groups, overlap of navigation and action groups is allowed
+ // when overlap occurs, titleDisplay/titleGroup is not visible
+ if (_navigationVisible)
+ {
+ navigationGroupWidth = navigationGroup.getPreferredBoundsWidth();
+ titleCompX += navigationGroupWidth;
+
+ setElementSize(navigationGroup, navigationGroupWidth, contentGroupsHeight);
+ setElementPosition(navigationGroup, paddingLeft, paddingTop);
+ }
+
+ if (_actionVisible)
+ {
+ // actionGroup x position can be negative
+ actionGroupWidth = actionGroup.getPreferredBoundsWidth();
+ actionGroupX = unscaledWidth - actionGroupWidth - paddingRight;
+
+ setElementSize(actionGroup, actionGroupWidth, contentGroupsHeight);
+ setElementPosition(actionGroup, actionGroupX, paddingTop);
+ }
+
+ // titleGroup or titleDisplay is given remaining width after navigation
+ // and action groups preferred widths
+ titleCompWidth = unscaledWidth - navigationGroupWidth - actionGroupWidth
+ - paddingLeft - paddingRight;
+
+ if (titleCompWidth <= 0)
+ {
+ titleDisplay.visible = false;
+ titleGroup.visible = false;
+ }
+ else if (_titleContentVisible)
+ {
+ titleDisplay.visible = false;
+ titleGroup.visible = true;
+
+ // use titleGroup for titleContent
+ setElementSize(titleGroup, titleCompWidth, contentGroupsHeight);
+ setElementPosition(titleGroup, titleCompX, paddingTop);
+ }
+ else
+ {
+ // use titleDisplay for title text label
+ titleGroup.visible = false;
+
+ // use titleLayout for paddingLeft and paddingRight
+ var layoutObject:Object = hostComponent.titleLayout;
+ var titlePaddingLeft:Number = (layoutObject.paddingLeft) ? Number(layoutObject.paddingLeft) : 0;
+ var titlePaddingRight:Number = (layoutObject.paddingRight) ? Number(layoutObject.paddingRight) : 0;
+
+ // align titleDisplay to the absolute center
+ var titleAlign:String = getStyle("titleAlign");
+
+ // check for available width after padding
+ if ((titleCompWidth - titlePaddingLeft - titlePaddingRight) <= 0)
+ {
+ titleCompX = 0;
+ titleCompWidth = 0;
+ }
+ else if (titleAlign == "center")
+ {
+ // use LEFT instead of CENTER
+ titleCompWidth = titleDisplay.getExplicitOrMeasuredWidth();
+
+ // use x position of titleDisplay to implement CENTER
+ titleCompX = Math.round((unscaledWidth - titleCompWidth) / 2);
+
+ var navigationOverlap:Number = navigationGroupWidth + titlePaddingLeft - titleCompX;
+ var actionOverlap:Number = (titleCompX + titleCompWidth + titlePaddingRight) - actionGroupX;
+
+ // shrink and/or move titleDisplay width if there is any
+ // overlap after centering
+ if ((navigationOverlap > 0) && (actionOverlap > 0))
+ {
+ // remaining width
+ titleCompX = navigationGroupWidth + titlePaddingLeft;
+ titleCompWidth = unscaledWidth - navigationGroupWidth - actionGroupWidth - titlePaddingLeft - titlePaddingRight;
+ }
+ else if ((navigationOverlap > 0) || (actionOverlap > 0))
+ {
+ if (navigationOverlap > 0)
+ {
+ // nudge to the right
+ titleCompX += navigationOverlap;
+ }
+ else if (actionOverlap > 0)
+ {
+ // nudge to the left
+ titleCompX -= actionOverlap;
+
+ // force left padding
+ if (titleCompX < (navigationGroupWidth + titlePaddingLeft))
+ titleCompX = navigationGroupWidth + titlePaddingLeft;
+ }
+
+ // recompute action overlap and force right padding
+ actionOverlap = (titleCompX + titleCompWidth + titlePaddingRight) - actionGroupX;
+
+ if (actionOverlap > 0)
+ titleCompWidth -= actionOverlap;
+ }
+ }
+ else
+ {
+ // implement padding by adjusting width and position
+ titleCompX += titlePaddingLeft;
+ titleCompWidth = titleCompWidth - titlePaddingLeft - titlePaddingRight;
+ }
+
+ // check for negative width
+ titleCompWidth = (titleCompWidth < 0) ? 0 : titleCompWidth;
+
+ setElementSize(titleDisplay, titleCompWidth, contentGroupsHeight);
+ setElementPosition(titleDisplay, titleCompX, paddingTop);
+
+ titleDisplay.visible = true;
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var chromeColor:uint = getStyle("chromeColor");
+ var backgroundAlphaValue:Number = getStyle("backgroundAlpha");
+ var colors:Array = [];
+
+ // apply alpha to chromeColor fill only
+ var backgroundAlphas:Array = [backgroundAlphaValue, backgroundAlphaValue];
+
+ // exclude top and bottom 1px borders
+ colorMatrix.createGradientBox(unscaledWidth, unscaledHeight - (borderSize * 2), Math.PI / 2, 0, 0);
+
+ colors[0] = ColorUtil.adjustBrightness2(chromeColor, 20);
+ colors[1] = chromeColor;
+
+ graphics.beginGradientFill(GradientType.LINEAR, colors, backgroundAlphas, ACTIONBAR_CHROME_COLOR_RATIOS, colorMatrix);
+ graphics.drawRect(0, borderSize, unscaledWidth, unscaledHeight - (borderSize * 2));
+ graphics.endFill();
+ }
+
+}
+}
+import flash.events.Event;
+
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.IDisplayText;
+
+use namespace mx_internal;
+
+/**
+ * @private
+ * Component that holds StyleableTextFields to produce a drop shadow effect.
+ * Combines label and shadow into a single component to allow transitions to
+ * target them both.
+ */
+class TitleDisplayComponent extends UIComponent implements IDisplayText
+{
+ private var titleDisplay:StyleableTextField;
+ private var titleDisplayShadow:StyleableTextField;
+ private var title:String;
+ private var titleChanged:Boolean;
+
+ public function TitleDisplayComponent()
+ {
+ super();
+ title = "";
+ }
+
+ override public function get baselinePosition():Number
+ {
+ return titleDisplay.baselinePosition;
+ }
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ titleDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ titleDisplay.styleName = this;
+ titleDisplay.editable = false;
+ titleDisplay.selectable = false;
+ titleDisplay.multiline = false;
+ titleDisplay.wordWrap = false;
+ titleDisplay.addEventListener(FlexEvent.VALUE_COMMIT,
+ titleDisplay_valueCommitHandler);
+
+ titleDisplayShadow =
+ StyleableTextField(createInFontContext(StyleableTextField));
+ titleDisplayShadow.styleName = this;
+ titleDisplayShadow.colorName = "textShadowColor";
+ titleDisplayShadow.editable = false;
+ titleDisplayShadow.selectable = false;
+ titleDisplayShadow.multiline = false;
+ titleDisplayShadow.wordWrap = false;
+
+ addChild(titleDisplayShadow);
+ addChild(titleDisplay);
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitProperties():void
+ {
+ super.commitProperties();
+
+ if (titleChanged)
+ {
+ titleDisplay.text = title;
+
+ invalidateSize();
+ invalidateDisplayList();
+
+ titleChanged = false;
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ // reset text if it was truncated before.
+ if (titleDisplay.isTruncated)
+ titleDisplay.text = title;
+
+ measuredWidth = titleDisplay.getPreferredBoundsWidth();
+
+ // tightTextHeight
+ measuredHeight = titleDisplay.getPreferredBoundsHeight();
+ }
+
+ /**
+ * @private
+ */
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+ // reset text if it was truncated before.
+ if (titleDisplay.isTruncated)
+ titleDisplay.text = title;
+ titleDisplay.commitStyles();
+
+ // use preferred height, setLayoutBoundsSize will accommodate for tight
+ // text adjustment
+ var tightHeight:Number = titleDisplay.getPreferredBoundsHeight();
+ var tightY:Number = (unscaledHeight - tightHeight) / 2;
+
+ titleDisplay.setLayoutBoundsSize(unscaledWidth, tightHeight);
+ titleDisplay.setLayoutBoundsPosition(0, (unscaledHeight - tightHeight) / 2);
+
+ // now truncate the text
+ titleDisplay.truncateToFit();
+
+ titleDisplayShadow.commitStyles();
+ titleDisplayShadow.setLayoutBoundsSize(unscaledWidth, tightHeight);
+ titleDisplayShadow.setLayoutBoundsPosition(0, tightY + 1);
+
+ titleDisplayShadow.alpha = getStyle("textShadowAlpha");
+
+ // if labelDisplay is truncated, then push it down here as well.
+ // otherwise, it would have gotten pushed in the labelDisplay_valueCommitHandler()
+ if (titleDisplay.isTruncated)
+ titleDisplayShadow.text = titleDisplay.text;
+ }
+
+ /**
+ * @private
+ */
+ private function titleDisplay_valueCommitHandler(event:Event):void
+ {
+ titleDisplayShadow.text = titleDisplay.text;
+ }
+
+ public function get text():String
+ {
+ return title;
+ }
+
+ public function set text(value:String):void
+ {
+ title = value;
+ titleChanged = true;
+
+ invalidateProperties();
+ }
+
+ public function get isTruncated():Boolean
+ {
+ return titleDisplay.isTruncated;
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/BusyIndicatorSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/BusyIndicatorSkin.as
new file mode 100644
index 0000000000..9f8e42faf2
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/BusyIndicatorSkin.as
@@ -0,0 +1,220 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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();
+ }
+ 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,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
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarFirstButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarFirstButtonSkin.as
new file mode 100644
index 0000000000..ab4a73ab24
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarFirstButtonSkin.as
@@ -0,0 +1,56 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.skins.ios7.assets.ButtonBarFirstButton_up;
+
+ /**
+ * iOS7+ specific Button skin for the first Button in a ButtonBar.
+ *
+ * @see spark.components.ButtonBar#firstButton
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class ButtonBarFirstButtonSkin extends IOS7ButtonBarButtonSkinBase
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ButtonBarFirstButtonSkin()
+ {
+ super();
+
+ upBorderSkin = spark.skins.ios7.assets.ButtonBarFirstButton_up;
+ downBorderSkin = spark.skins.ios7.assets.ButtonBarFirstButton_down;
+ selectedBorderSkin = spark.skins.ios7.assets.ButtonBarFirstButton_down;
+ selectedDownBorderSkin = spark.skins.ios7.assets.ButtonBarFirstButton_up;
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarLastButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarLastButtonSkin.as
new file mode 100644
index 0000000000..8abe433138
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarLastButtonSkin.as
@@ -0,0 +1,56 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.skins.ios7.assets.ButtonBarLastButton_up;
+
+ /**
+ * iOS7+ specific Button skin for the last Button in a ButtonBar.
+ *
+ * @see spark.components.ButtonBar#lastButton
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class ButtonBarLastButtonSkin extends IOS7ButtonBarButtonSkinBase
+ {
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ButtonBarLastButtonSkin()
+ {
+ super();
+
+ upBorderSkin = spark.skins.ios7.assets.ButtonBarLastButton_up
+ downBorderSkin = spark.skins.ios7.assets.ButtonBarLastButton_down;
+ selectedBorderSkin = spark.skins.ios7.assets.ButtonBarLastButton_down;
+ selectedDownBorderSkin = spark.skins.ios7.assets.ButtonBarLastButton_up;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarMiddleButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarMiddleButtonSkin.as
new file mode 100644
index 0000000000..9f69ab8ba9
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarMiddleButtonSkin.as
@@ -0,0 +1,57 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.skins.ios7.assets.ButtonBarMiddleButton_up;
+
+ /**
+ * Android 4.x specific Button skin for middle Buttons in a ButtonBar.
+ *
+ * @see spark.components.ButtonBar#middleButton
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class ButtonBarMiddleButtonSkin extends IOS7ButtonBarButtonSkinBase
+ {
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ButtonBarMiddleButtonSkin()
+ {
+ super();
+
+ upBorderSkin = spark.skins.ios7.assets.ButtonBarMiddleButton_up
+ downBorderSkin = spark.skins.ios7.assets.ButtonBarMiddleButton_down;
+ selectedBorderSkin = spark.skins.ios7.assets.ButtonBarMiddleButton_down;
+ selectedDownBorderSkin = spark.skins.ios7.assets.ButtonBarMiddleButton_up;
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarSkin.as
new file mode 100644
index 0000000000..a1649b60cd
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonBarSkin.as
@@ -0,0 +1,165 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.components.ButtonBar;
+import spark.components.ButtonBarButton;
+import spark.components.DataGroup;
+import spark.components.supportClasses.ButtonBarHorizontalLayout;
+import spark.skins.mobile.supportClasses.ButtonBarButtonClassFactory;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+/**
+ * iOS7+ specific skin class for the Spark ButtonBar component.
+ *
+ * @see spark.components.ButtonBar
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ButtonBarSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function ButtonBarSkin()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:ButtonBar;
+
+ /**
+ * @copy spark.components.ButtonBar#firstButton
+ */
+ public var firstButton:ButtonBarButtonClassFactory;
+
+ /**
+ * @copy spark.components.ButtonBar#lastButton
+ */
+ public var lastButton:ButtonBarButtonClassFactory;
+
+ /**
+ * @copy spark.components.ButtonBar#middleButton
+ */
+ public var middleButton:ButtonBarButtonClassFactory;
+
+ /**
+ * @copy spark.components.SkinnableDataContainer#dataGroup
+ */
+ public var dataGroup:DataGroup;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Set up the class factories for the buttons
+ if (!firstButton)
+ {
+ firstButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ firstButton.skinClass = spark.skins.ios7.ButtonBarFirstButtonSkin;
+ }
+
+ if (!lastButton)
+ {
+ lastButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ lastButton.skinClass = spark.skins.ios7.ButtonBarLastButtonSkin;
+ }
+
+ if (!middleButton)
+ {
+ middleButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ middleButton.skinClass = spark.skins.ios7.ButtonBarMiddleButtonSkin;
+ }
+
+ // create the data group to house the buttons
+ if (!dataGroup)
+ {
+ dataGroup = new DataGroup();
+ var hLayout:ButtonBarHorizontalLayout = new ButtonBarHorizontalLayout();
+ //TODO: Gap should vary depending on current DPI
+ hLayout.gap = -1;
+ dataGroup.layout = hLayout;
+ addChild(dataGroup);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ alpha = (currentState == "disabled") ? 0.5 : 1;
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = dataGroup.measuredWidth;
+ measuredHeight = dataGroup.measuredHeight;
+
+ measuredMinWidth = dataGroup.measuredMinWidth;
+ measuredMinHeight = dataGroup.measuredMinHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementPosition(dataGroup, 0, 0);
+ setElementSize(dataGroup, unscaledWidth, unscaledHeight);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonSkin.as
new file mode 100644
index 0000000000..114b3659a7
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ButtonSkin.as
@@ -0,0 +1,387 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+
+import spark.components.supportClasses.StyleableTextField;
+import spark.skins.ios7.assets.Button_up;
+import spark.skins.mobile.supportClasses.ButtonSkinBase;
+
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for Button controls in mobile applications. The skin supports
+ * iconClass and labelPlacement. It uses FXG classes to
+ * implement the vector drawing.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ButtonSkin extends ButtonSkinBase
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * An array of color distribution ratios.
+ * This is used in the chrome color fill.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ mx_internal static const CHROME_COLOR_RATIOS:Array = [0, 127.5];
+
+ /**
+ * An array of alpha values for the corresponding colors in the colors array.
+ * This is used in the chrome color fill.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ mx_internal static const CHROME_COLOR_ALPHAS:Array = [1, 1];
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ButtonSkin()
+ {
+ super();
+ //In iOS7, buttons look like simple links, without any shape containing the text
+ //We still need to assign an asset to determine the size of the button
+ //Button_up is a simple transparent graphic object
+ upBorderSkin = spark.skins.ios7.assets.Button_up;
+ downBorderSkin = spark.skins.ios7.assets.Button_up;
+ layoutCornerEllipseSize = 0;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ layoutGap = 20;
+ layoutPaddingLeft = 40;
+ layoutPaddingRight = 40;
+ layoutPaddingTop = 40;
+ layoutPaddingBottom = 40;
+ layoutBorderSize = 2;
+ measuredDefaultWidth = 128;
+ measuredDefaultHeight = 172;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ layoutGap = 14;
+ layoutPaddingLeft = 30;
+ layoutPaddingRight = 30;
+ layoutPaddingTop = 30;
+ layoutPaddingBottom = 30;
+ layoutBorderSize = 2;
+ measuredDefaultWidth = 96;
+ measuredDefaultHeight = 130;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ layoutGap = 10;
+ layoutPaddingLeft = 20;
+ layoutPaddingRight = 20;
+ layoutPaddingTop = 20;
+ layoutPaddingBottom = 20;
+ layoutBorderSize = 2;
+ measuredDefaultWidth = 64;
+ measuredDefaultHeight = 86;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+
+ layoutGap = 7;
+ layoutPaddingLeft = 15;
+ layoutPaddingRight = 15;
+ layoutPaddingTop = 15;
+ layoutPaddingBottom = 15;
+ layoutBorderSize = 1;
+ measuredDefaultWidth = 48;
+ measuredDefaultHeight = 65;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+
+ layoutGap = 4;
+ layoutPaddingLeft = 8;
+ layoutPaddingRight = 8;
+ layoutPaddingTop = 8;
+ layoutPaddingBottom = 8;
+ layoutBorderSize = 1;
+ measuredDefaultWidth = 24;
+ measuredDefaultHeight = 33;
+
+ break;
+ }
+ default:
+ {
+
+ layoutGap = 5;
+ layoutPaddingLeft = 10;
+ layoutPaddingRight = 10;
+ layoutPaddingTop = 10;
+ layoutPaddingBottom = 10;
+ layoutBorderSize = 1;
+ measuredDefaultWidth = 32;
+ measuredDefaultHeight = 43;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the corner radius.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var layoutCornerEllipseSize:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ private var _border:DisplayObject;
+
+ private var changeFXGSkin:Boolean = false;
+
+ private var borderClass:Class;
+
+ mx_internal var fillColorStyleName:String = "chromeColor";
+
+ /**
+ * Defines the shadow for the Button control's label.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var labelDisplayShadow:StyleableTextField;
+
+ /**
+ * Read-only button border graphic. Use getBorderClassForCurrentState()
+ * to specify a graphic per-state.
+ *
+ * @see #getBorderClassForCurrentState()
+ */
+ protected function get border():DisplayObject
+ {
+ return _border;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Class to use for the border in the up state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ * @default Button_up
+ */
+ protected var upBorderSkin:Class;
+
+ /**
+ * Class to use for the border in the down state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ * @default Button_down
+ */
+ protected var downBorderSkin:Class;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+ setStyle("textAlign", "center");
+ }
+
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.updateDisplayList(unscaledWidth,unscaledHeight);
+ if(currentState == "down")
+ {
+ this.alpha = 0.5;
+ }
+ else
+ {
+ this.alpha = 1.0;
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ borderClass = getBorderClassForCurrentState();
+
+ if (!(_border is borderClass))
+ changeFXGSkin = true;
+
+ // update borderClass and background
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // size the FXG background
+ if (changeFXGSkin)
+ {
+ changeFXGSkin = false;
+
+ if (_border)
+ {
+ removeChild(_border);
+ _border = null;
+ }
+
+ if (borderClass)
+ {
+ _border = new borderClass();
+ addChildAt(_border, 0);
+ }
+ }
+
+ layoutBorder(unscaledWidth, unscaledHeight);
+
+ }
+
+ /**
+ * Position the background of the skin. Override this function to re-position the background.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ mx_internal function layoutBorder(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+
+ /**
+ * Returns the borderClass to use based on the currentState.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected function getBorderClassForCurrentState():Class
+ {
+ if (currentState == "down")
+ return downBorderSkin;
+ else
+ return upBorderSkin;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event Handlers
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function labelDisplay_valueCommitHandler(event:FlexEvent):void
+ {
+ super.labelDisplay_valueCommitHandler(event);
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutActionBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutActionBarSkin.as
new file mode 100644
index 0000000000..8f22ff6463
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutActionBarSkin.as
@@ -0,0 +1,102 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+/**
+ * Additional skin class for the Spark ActionBar component for use with a
+ * ViewNavigator inside a Callout component.
+ *
+ * Uses a transparent background instead of a gradient fill.
+ *
+ * @see spark.skins.mobile.ActionBarSkin
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+public class CalloutActionBarSkin extends ActionBarSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ public function CalloutActionBarSkin()
+ {
+ super();
+
+ // remove default background
+ //borderClass = null;
+
+ // shorten ActionBar height visual paddingTop comes from CalloutSkin
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ layoutContentGroupHeight = 108;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ layoutContentGroupHeight = 84;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ layoutContentGroupHeight = 54;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ layoutContentGroupHeight = 42;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ layoutContentGroupHeight = 21;
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ layoutContentGroupHeight = 28;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // do not draw chromeColor
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutSkin.as
new file mode 100644
index 0000000000..b57840689e
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutSkin.as
@@ -0,0 +1,779 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.BlendMode;
+import flash.display.GradientType;
+import flash.display.Graphics;
+import flash.display.Sprite;
+import flash.events.Event;
+
+import mx.core.DPIClassification;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.events.EffectEvent;
+import mx.events.FlexEvent;
+import mx.utils.ColorUtil;
+
+import spark.components.ArrowDirection;
+import spark.components.Callout;
+import spark.components.ContentBackgroundAppearance;
+import spark.components.Group;
+import spark.core.SpriteVisualElement;
+import spark.effects.Fade;
+import spark.primitives.RectangularDropShadow;
+import spark.skins.ios7.supportClasses.CalloutArrow;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for the Spark Callout component in mobile
+ * applications.
+ *
+ *
The contentGroup lies above a backgroundColor fill
+ * which frames the contentGroup. The position and size of the frame
+ * adjust based on the host component arrowDirection, leaving
+ * space for the arrow to appear on the outside edge of the
+ * frame.
+ *
+ *
The arrow skin part is not positioned by the skin. Instead,
+ * the Callout component positions the arrow relative to the owner in
+ * updateSkinDisplayList(). This method assumes that Callout skin
+ * and the arrow use the same coordinate space.
+ *
+ * @see spark.components.Callout
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+public class CalloutSkin extends MobileSkin
+{
+ mx_internal static const BACKGROUND_GRADIENT_BRIGHTNESS_TOP:int = 15;
+
+ mx_internal static const BACKGROUND_GRADIENT_BRIGHTNESS_BOTTOM:int = -15;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public function CalloutSkin()
+ {
+ super();
+
+ dropShadowAlpha = 0;
+ contentBackgroundInsetClass = null;
+ frameThickness = 0;
+ backgroundCornerRadius = 0;
+ backgroundGradientHeight = 0;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ arrowWidth = 160;
+ arrowHeight = 80;
+ contentCornerRadius = 40;
+ dropShadowBlurX = 64;
+ dropShadowBlurY = 64;
+ dropShadowDistance = 12;
+ highlightWeight = 4;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ arrowWidth = 120;
+ arrowHeight = 60;
+ contentCornerRadius = 30;
+ dropShadowBlurX = 48;
+ dropShadowBlurY = 48;
+ dropShadowDistance = 8;
+ highlightWeight = 2;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ arrowWidth = 80;
+ arrowHeight = 40;
+ contentCornerRadius = 20;
+ dropShadowBlurX = 32;
+ dropShadowBlurY = 32;
+ dropShadowDistance = 6;
+ highlightWeight = 2;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ arrowWidth = 60;
+ arrowHeight = 30;
+ contentCornerRadius = 15;
+ dropShadowBlurX = 24;
+ dropShadowBlurY = 24;
+ dropShadowDistance = 4;
+ highlightWeight = 1;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ arrowWidth = 30;
+ arrowHeight = 15;
+ contentCornerRadius = 7.5;
+ dropShadowBlurX = 12;
+ dropShadowBlurY = 12;
+ dropShadowDistance = 2;
+ highlightWeight = 0.5;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ arrowWidth = 40;
+ arrowHeight = 20;
+ contentCornerRadius = 10;
+ dropShadowBlurX = 16;
+ dropShadowBlurY = 16;
+ dropShadowDistance = 3;
+ highlightWeight = 1;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Callout;
+
+ /**
+ * Enables a RectangularDropShadow behind the backgroundColor frame.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var dropShadowVisible:Boolean = false;
+
+ /**
+ * Enables a vertical linear gradient in the backgroundColor frame. This
+ * gradient fill is drawn across both the arrow and the frame. By default,
+ * the gradient brightens the background color by 15% and darkens it by 60%.
+ *
+ * @default true
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var useBackgroundGradient:Boolean = true;
+
+ /**
+ * Corner radius used for the contentBackgroundColor fill.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var contentCornerRadius:uint;
+
+ /**
+ * A class reference to an FXG class that is layered underneath the
+ * contentGroup. The instance of this class is sized to match the
+ * contentGroup.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var contentBackgroundInsetClass:Class;
+
+ /**
+ * Corner radius of the backgroundColor "frame".
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var backgroundCornerRadius:Number;
+
+ /**
+ * The thickness of the backgroundColor "frame" that surrounds the
+ * contentGroup.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var frameThickness:Number;
+
+ /**
+ * Color of the border stroke around the backgroundColor "frame".
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderColor:Number = -1; // not set
+
+ /**
+ * Thickness of the border stroke around the backgroundColor
+ * "frame".
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderThickness:Number = -1 ; // marker that borderThickness was not set directly
+
+ /**
+ * Width of the arrow in vertical directions. This property also controls
+ * the height of the arrow in horizontal directions.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var arrowWidth:Number;
+
+ /**
+ * Height of the arrow in vertical directions. This property also controls
+ * the width of the arrow in horizontal directions.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var arrowHeight:Number;
+
+ /**
+ * @private
+ * Instance of the contentBackgroundClass
+ */
+ mx_internal var contentBackgroundGraphic:SpriteVisualElement;
+
+ /**
+ * @private
+ * Tracks changes to the skin state to support the fade out tranisition
+ * when closed;
+ */
+ mx_internal var isOpen:Boolean;
+
+ private var backgroundGradientHeight:Number;
+
+ private var contentMask:Sprite;
+
+ private var backgroundFill:SpriteVisualElement;
+
+ private var dropShadow:RectangularDropShadow;
+
+ private var dropShadowBlurX:Number;
+
+ private var dropShadowBlurY:Number;
+
+ private var dropShadowDistance:Number;
+
+ private var dropShadowAlpha:Number;
+
+ private var fade:Fade;
+
+ private var highlightWeight:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.components.SkinnableContainer#contentGroup
+ */
+ public var contentGroup:Group;
+
+ /**
+ * @copy spark.components.Callout#arrow
+ */
+ public var arrow:UIComponent;
+
+ /* helper private accessors */
+
+ /* returns borderThickness from style if member is -1, or borderThickness. Returns 0 if NaN */
+ mx_internal function get actualBorderThickness():Number
+ {
+ var border: Number = borderThickness != -1 ? borderThickness : getStyle('borderThickness');
+ return isNaN(border)? 0: border;
+ }
+
+ mx_internal function get actualBorderColor():uint
+ {
+ return borderColor != -1 ? borderColor: getStyle('borderColor');
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (dropShadowVisible)
+ {
+ dropShadow = new RectangularDropShadow();
+ dropShadow.angle = 90;
+ dropShadow.distance = dropShadowDistance;
+ dropShadow.blurX = dropShadowBlurX;
+ dropShadow.blurY = dropShadowBlurY;
+ dropShadow.tlRadius = dropShadow.trRadius = dropShadow.blRadius =
+ dropShadow.brRadius = backgroundCornerRadius ;
+ dropShadow.mouseEnabled = false;
+ dropShadow.alpha = dropShadowAlpha;
+ addChild(dropShadow);
+ }
+
+ // background fill placed above the drop shadow
+ backgroundFill = new SpriteVisualElement();
+ addChild(backgroundFill);
+
+ // arrow
+ if (!arrow)
+ {
+ arrow = new CalloutArrow();
+ arrow.id = "arrow";
+ arrow.styleName = this;
+ addChild(arrow);
+ }
+
+ // contentGroup
+ if (!contentGroup)
+ {
+ contentGroup = new Group();
+ contentGroup.id = "contentGroup";
+ addChild(contentGroup);
+ }
+
+
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitProperties():void
+ {
+ super.commitProperties();
+
+ // add or remove the contentBackgroundGraphic
+ var contentBackgroundAppearance:String = getStyle("contentBackgroundAppearance");
+
+ if (contentBackgroundAppearance == ContentBackgroundAppearance.INSET)
+ {
+ // create the contentBackgroundGraphic
+ if (!contentBackgroundGraphic && contentBackgroundInsetClass)
+ {
+ contentBackgroundGraphic = new contentBackgroundInsetClass() as SpriteVisualElement;
+
+ // with the current skin structure, contentBackgroundGraphic is
+ // always the last child
+ addChild(contentBackgroundGraphic);
+ }
+ }
+ else if (contentBackgroundGraphic)
+ {
+ // if already created, remove the graphic for "flat" and "none"
+ removeChild(contentBackgroundGraphic);
+ contentBackgroundGraphic = null;
+ }
+
+ // always invalidate to accomodate arrow direction changes
+ invalidateSize();
+ invalidateDisplayList();
+ }
+
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var borderWeight:Number =actualBorderThickness;
+ var frameAdjustment:Number = (frameThickness + borderWeight) * 2;
+
+ var arrowMeasuredWidth:Number;
+ var arrowMeasuredHeight:Number;
+
+ // pad the arrow so that the edges are within the background corner radius
+ if (isArrowHorizontal)
+ {
+ arrowMeasuredWidth = arrowHeight;
+ arrowMeasuredHeight = arrowWidth + (backgroundCornerRadius * 2);
+ }
+ else if (isArrowVertical)
+ {
+ arrowMeasuredWidth = arrowWidth + (backgroundCornerRadius * 2);
+ arrowMeasuredHeight = arrowHeight;
+ }
+
+ // count the contentGroup size and frame size
+ measuredMinWidth = contentGroup.measuredMinWidth + frameAdjustment;
+ measuredMinHeight = contentGroup.measuredMinHeight + frameAdjustment;
+
+ measuredWidth = contentGroup.getPreferredBoundsWidth() + frameAdjustment;
+ measuredHeight = contentGroup.getPreferredBoundsHeight() + frameAdjustment;
+
+ // add the arrow size based on the arrowDirection
+ if (isArrowHorizontal)
+ {
+ measuredMinWidth += arrowMeasuredWidth;
+ measuredMinHeight = Math.max(measuredMinHeight, arrowMeasuredHeight);
+
+ measuredWidth += arrowMeasuredWidth;
+ measuredHeight = Math.max(measuredHeight, arrowMeasuredHeight);
+ }
+ else if (isArrowVertical)
+ {
+ measuredMinWidth += Math.max(measuredMinWidth, arrowMeasuredWidth);
+ measuredMinHeight += arrowMeasuredHeight;
+
+ measuredWidth = Math.max(measuredWidth, arrowMeasuredWidth);
+ measuredHeight += arrowMeasuredHeight;
+ }
+ }
+
+ /**
+ * @private
+ * SkinnaablePopUpContainer skins must dispatch a
+ * FlexEvent.STATE_CHANGE_COMPLETE event for the component to properly
+ * update the skin state.
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ var isNormal:Boolean = (currentState == "normal");
+ var isDisabled:Boolean = (currentState == "disabled")
+
+ // play a fade out if the callout was previously open
+ if (!(isNormal || isDisabled) && isOpen)
+ {
+ if (!fade)
+ {
+ fade = new Fade();
+ fade.target = this;
+ fade.duration = 200;
+ fade.alphaTo = 0;
+ }
+
+ // BlendMode.LAYER while fading out
+ blendMode = BlendMode.LAYER;
+
+ // play a short fade effect
+ fade.addEventListener(EffectEvent.EFFECT_END, stateChangeComplete);
+ fade.play();
+
+ isOpen = false;
+ }
+ else
+ {
+ isOpen = isNormal || isDisabled;
+
+ // handle re-opening the Callout while fading out
+ if (fade && fade.isPlaying)
+ {
+ // Do not dispatch a state change complete.
+ // SkinnablePopUpContainer handles state interruptions.
+ fade.removeEventListener(EffectEvent.EFFECT_END, stateChangeComplete);
+ fade.stop();
+ }
+
+ if (isDisabled)
+ {
+ // BlendMode.LAYER to allow CalloutArrow BlendMode.ERASE
+ blendMode = BlendMode.LAYER;
+
+ alpha = 0.5;
+ }
+ else
+ {
+ // BlendMode.NORMAL for non-animated state transitions
+ blendMode = BlendMode.NORMAL;
+
+ if (isNormal)
+ alpha = 1;
+ else
+ alpha = 0;
+ }
+
+ stateChangeComplete();
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var frameEllipseSize:Number = backgroundCornerRadius * 2;
+
+ // account for borderThickness center stroke alignment
+ var borderWeight:Number =actualBorderThickness;
+ var showBorder:Boolean = borderWeight > 0 ;
+
+
+ // contentBackgroundGraphic already accounts for the arrow position
+ // use it's positioning instead of recalculating based on unscaledWidth
+ // and unscaledHeight
+ var frameX:Number = Math.floor(contentGroup.getLayoutBoundsX() - frameThickness) - (borderWeight / 2);
+ var frameY:Number = Math.floor(contentGroup.getLayoutBoundsY() - frameThickness) - (borderWeight / 2);
+ var frameWidth:Number = contentGroup.getLayoutBoundsWidth() + (frameThickness * 2) + borderWeight;
+ var frameHeight:Number = contentGroup.getLayoutBoundsHeight() + (frameThickness * 2) + borderWeight;
+
+ var backgroundColor:Number = getStyle("contentBackgroundColor");
+ var backgroundAlpha:Number = getStyle("backgroundAlpha");
+
+ var bgFill:Graphics = backgroundFill.graphics;
+ bgFill.clear();
+
+ // draw content background styles
+ var contentBackgroundAppearance:String = getStyle("contentBackgroundAppearance");
+
+ if (contentBackgroundAppearance != ContentBackgroundAppearance.NONE)
+ {
+ var contentEllipseSize:Number = contentCornerRadius * 2;
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ var contentWidth:Number = contentGroup.getLayoutBoundsWidth();
+ var contentHeight:Number = contentGroup.getLayoutBoundsHeight();
+
+ // all appearance values except for "none" use a mask
+ if (!contentMask)
+ contentMask = new SpriteVisualElement();
+
+ contentGroup.mask = contentMask;
+
+ // draw contentMask in contentGroup coordinate space
+ var maskGraphics:Graphics = contentMask.graphics;
+ maskGraphics.clear();
+ maskGraphics.beginFill(0, 1);
+ maskGraphics.drawRoundRect(0, 0, contentWidth, contentHeight,
+ contentEllipseSize, contentEllipseSize);
+ maskGraphics.endFill();
+
+ // reset line style to none
+ if (showBorder)
+ bgFill.lineStyle(NaN);
+
+ // draw the contentBackgroundColor
+ bgFill.beginFill(getStyle("contentBackgroundColor"),
+ contentBackgroundAlpha);
+ bgFill.drawRoundRect(contentGroup.getLayoutBoundsX(),
+ contentGroup.getLayoutBoundsY(),
+ contentWidth, contentHeight, contentEllipseSize, contentEllipseSize);
+ bgFill.endFill();
+
+ if (contentBackgroundGraphic)
+ contentBackgroundGraphic.alpha = contentBackgroundAlpha;
+ }
+ else // if (contentBackgroundAppearance == CalloutContentBackgroundAppearance.NONE))
+ {
+ // remove the mask
+ if (contentMask)
+ {
+ contentGroup.mask = null;
+ contentMask = null;
+ }
+ }
+
+ // draw highlight in the callout when the arrow is hidden
+ if (useBackgroundGradient && !isArrowHorizontal && !isArrowVertical)
+ {
+ // highlight width spans the callout width minus the corner radius
+ var highlightWidth:Number = frameWidth - frameEllipseSize;
+ var highlightX:Number = frameX + backgroundCornerRadius;
+ var highlightOffset:Number = (highlightWeight * 1.5);
+
+ // straight line across the top
+ bgFill.lineStyle(highlightWeight, 0xFFFFFF, 0.2 * backgroundAlpha);
+ bgFill.moveTo(highlightX, highlightOffset);
+ bgFill.lineTo(highlightX + highlightWidth, highlightOffset);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // pad the arrow so that the edges are within the background corner radius
+ if (isArrowHorizontal)
+ {
+ arrow.width = arrowHeight;
+ arrow.height = arrowWidth + (backgroundCornerRadius * 2);
+ }
+ else if (isArrowVertical)
+ {
+ arrow.width = arrowWidth + (backgroundCornerRadius * 2);
+ arrow.height = arrowHeight;
+ }
+
+ setElementSize(backgroundFill, unscaledWidth, unscaledHeight);
+ setElementPosition(backgroundFill, 0, 0);
+
+ var frameX:Number = 0;
+ var frameY:Number = 0;
+ var frameWidth:Number = unscaledWidth;
+ var frameHeight:Number = unscaledHeight;
+
+ switch (hostComponent.arrowDirection)
+ {
+ case ArrowDirection.UP:
+ frameY = arrow.height;
+ frameHeight -= arrow.height;
+ break;
+ case ArrowDirection.DOWN:
+ frameHeight -= arrow.height;
+ break;
+ case ArrowDirection.LEFT:
+ frameX = arrow.width;
+ frameWidth -= arrow.width;
+ break;
+ case ArrowDirection.RIGHT:
+ frameWidth -= arrow.width;
+ break;
+ default:
+ // no arrow, content takes all available space
+ break;
+ }
+
+ if (dropShadow)
+ {
+ setElementSize(dropShadow, frameWidth, frameHeight);
+ setElementPosition(dropShadow, frameX, frameY);
+ }
+
+ // Show frameThickness by inset of contentGroup
+ var borderWeight:Number = actualBorderThickness;
+ var contentBackgroundAdjustment:Number = frameThickness + borderWeight;
+
+ var contentBackgroundX:Number = frameX + contentBackgroundAdjustment;
+ var contentBackgroundY:Number = frameY + contentBackgroundAdjustment;
+
+ contentBackgroundAdjustment = contentBackgroundAdjustment * 2;
+ var contentBackgroundWidth:Number = frameWidth - contentBackgroundAdjustment;
+ var contentBackgroundHeight:Number = frameHeight - contentBackgroundAdjustment;
+
+ if (contentBackgroundGraphic)
+ {
+ setElementSize(contentBackgroundGraphic, contentBackgroundWidth, contentBackgroundHeight);
+ setElementPosition(contentBackgroundGraphic, contentBackgroundX, contentBackgroundY);
+ }
+
+ setElementSize(contentGroup, contentBackgroundWidth, contentBackgroundHeight);
+ setElementPosition(contentGroup, contentBackgroundX, contentBackgroundY);
+
+ // mask position is in the contentGroup coordinate space
+ if (contentMask)
+ setElementSize(contentMask, contentBackgroundWidth, contentBackgroundHeight);
+ }
+
+ override public function styleChanged(styleProp:String):void
+ {
+ super.styleChanged(styleProp);
+
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || (styleProp == "contentBackgroundAppearance"))
+ invalidateProperties();
+
+ if (allStyles || (styleProp == "backgroundAlpha"))
+ {
+ var backgroundAlpha:Number = getStyle("backgroundAlpha");
+
+ // Use BlendMode.LAYER to allow CalloutArrow to erase the dropShadow
+ // when the Callout background is transparent
+ blendMode = (backgroundAlpha < 1) ? BlendMode.LAYER : BlendMode.NORMAL;
+ }
+ }
+
+ /**
+ * @private
+ */
+ mx_internal function get isArrowHorizontal():Boolean
+ {
+ return (hostComponent.arrowDirection == ArrowDirection.LEFT
+ || hostComponent.arrowDirection == ArrowDirection.RIGHT);
+ }
+
+ /**
+ * @private
+ */
+ mx_internal function get isArrowVertical():Boolean
+ {
+ return (hostComponent.arrowDirection == ArrowDirection.UP
+ || hostComponent.arrowDirection == ArrowDirection.DOWN);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event handlers
+ //
+ //--------------------------------------------------------------------------
+
+ private function stateChangeComplete(event:Event=null):void
+ {
+ if (fade && event)
+ fade.removeEventListener(EffectEvent.EFFECT_END, stateChangeComplete);
+
+ // SkinnablePopUpContainer relies on state changes for open and close
+ dispatchEvent(new FlexEvent(FlexEvent.STATE_CHANGE_COMPLETE));
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutViewNavigatorSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutViewNavigatorSkin.as
new file mode 100644
index 0000000000..a8b972df71
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CalloutViewNavigatorSkin.as
@@ -0,0 +1,236 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.Graphics;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.core.SpriteVisualElement;
+import spark.skins.mobile.ViewNavigatorSkin;
+
+use namespace mx_internal;
+
+/**
+ * The ActionScript-based skin for view navigators inside a callout.
+ * This skin lays out the action bar and content
+ * group in a vertical fashion, where the action bar is on top.
+ * Unlike the default skin, overlay modes are not supported.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+public class CalloutViewNavigatorSkin extends ViewNavigatorSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public function CalloutViewNavigatorSkin()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ contentCornerRadius = 28;
+ gap = 48;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ contentCornerRadius = 14;
+ gap = 24;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ contentCornerRadius = 10;
+ gap = 16;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ contentCornerRadius = 7;
+ gap = 12;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ contentCornerRadius = 4;
+ gap = 6;
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ contentCornerRadius = 5;
+ gap = 8;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ mx_internal var gap:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ mx_internal var contentCornerRadius:Number;
+
+ private var contentMask:SpriteVisualElement;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ // mask the ViewNavigator contentGroup
+ contentMask = new SpriteVisualElement();
+ contentGroup.mask = contentMask;
+
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ measuredWidth = Math.max(actionBar.getPreferredBoundsWidth(),
+ contentGroup.getPreferredBoundsWidth());
+ measuredHeight = actionBar.getPreferredBoundsHeight()
+ + contentGroup.getPreferredBoundsHeight()
+ + gap;
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ // Force a layout pass on the components
+ invalidateProperties();
+ invalidateSize();
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // omit super call
+
+ var actionBarHeight:Number = 0;
+
+ // The action bar is always placed at 0,0 and stretches the entire
+ // width of the navigator
+ if (actionBar.includeInLayout)
+ {
+ actionBarHeight = Math.min(actionBar.getPreferredBoundsHeight(), unscaledHeight);
+ setElementSize(actionBar, unscaledWidth, actionBarHeight);
+ setElementPosition(actionBar, 0, 0);
+ actionBarHeight = actionBar.getLayoutBoundsHeight();
+ }
+
+ // If the hostComponent is in overlay mode, the contentGroup extends
+ // the entire bounds of the navigator and the alpha for the action
+ // bar changes
+ // If this changes, also update validateEstimatedSizesOfChild
+ var contentGroupHeight:Number = 0;
+
+ if (contentGroup.includeInLayout)
+ {
+ contentGroupHeight = Math.max(unscaledHeight - actionBarHeight - gap, 0);
+
+ setElementSize(contentGroup, unscaledWidth, contentGroupHeight);
+ setElementPosition(contentGroup, 0, actionBarHeight + gap);
+
+ }
+
+ setElementSize(contentMask, unscaledWidth, contentGroupHeight);
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ // draw the contentBackgroundColor
+ // the shading and highlight are drawn in FXG
+ var contentEllipseSize:Number = contentCornerRadius * 2;
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ var contentWidth:Number = contentGroup.getLayoutBoundsWidth();
+ var contentHeight:Number = contentGroup.getLayoutBoundsHeight();
+
+ graphics.beginFill(getStyle("contentBackgroundColor"),
+ contentBackgroundAlpha);
+ graphics.endFill();
+
+ if (contentMask)
+ {
+ // content mask in contentGroup coordinate space
+ var maskGraphics:Graphics = contentMask.graphics;
+ maskGraphics.clear();
+ maskGraphics.beginFill(0, 1);
+ maskGraphics.drawRoundRect(0, 0, contentWidth, contentHeight,
+ contentEllipseSize, contentEllipseSize);
+ maskGraphics.endFill();
+ }
+
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/CheckBoxSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CheckBoxSkin.as
new file mode 100644
index 0000000000..1e77c870c9
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/CheckBoxSkin.as
@@ -0,0 +1,266 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+ import spark.skins.ios7.assets.CheckBox_up;
+ import spark.skins.mobile.supportClasses.SelectableButtonSkinBase;
+
+ /**
+ * ActionScript-based skin for CheckBox components in mobile applications.
+ *
+ * @see spark.components.CheckBox
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class CheckBoxSkin extends SelectableButtonSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ private static const exclusions:Array = ["labelDisplay", "labelDisplayShadow"];
+
+ //--------------------------------------------------------------------------
+ //
+ // Member variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var symbolOffsetX:Number;
+ protected var symbolOffsetY:Number;
+ protected var iconWidth:Number;
+ protected var iconHeight:Number;
+ protected var symbolWidth:Number;
+ protected var symbolHeight:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function CheckBoxSkin()
+ {
+ super();
+
+ layoutPaddingLeft = 0;
+ layoutPaddingRight = 0;
+ layoutPaddingTop = 0;
+ layoutPaddingBottom = 0;
+
+ upIconClass = spark.skins.ios7.assets.CheckBox_up;
+ upSymbolIconClass = null;
+ upSelectedIconClass = spark.skins.ios7.assets.CheckBox_upSelected;
+ upSymbolIconSelectedClass = spark.skins.ios7.assets.CheckBox_upSymbolSelected;
+
+ downIconClass = spark.skins.ios7.assets.CheckBox_up;
+ downSymbolIconClass = null
+ downSelectedIconClass = spark.skins.ios7.assets.CheckBox_up;
+ downSymbolIconSelectedClass = null;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ layoutGap = 16;
+ minWidth = 128;
+ minHeight = 128;
+ layoutBorderSize = 6;
+ iconWidth = 128;
+ iconHeight = 128;
+ symbolWidth = 80;
+ symbolHeight = 80;
+ symbolOffsetX = 2;
+ symbolOffsetY = 0;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ layoutGap = 12;
+ minWidth = 96;
+ minHeight = 96;
+ layoutBorderSize = 4;
+ iconWidth = 96;
+ iconHeight = 96;
+ symbolWidth = 60;
+ symbolHeight = 60;
+ symbolOffsetX = 2;
+ symbolOffsetY = 0;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ layoutGap = 8;
+ minWidth = 64;
+ minHeight = 64;
+ layoutBorderSize = 3;
+ iconWidth = 64;
+ iconHeight = 64;
+ symbolWidth = 40;
+ symbolHeight = 40;
+ symbolOffsetX = 1;
+ symbolOffsetY = 0;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+
+ layoutGap = 6;
+ minWidth = 48;
+ minHeight = 48;
+ layoutBorderSize = 2;
+ iconWidth = 48;
+ iconHeight = 48;
+ symbolWidth = 30;
+ symbolHeight = 30;
+ symbolOffsetX = 0;
+ symbolOffsetY = 0;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+
+ layoutGap = 3;
+ minWidth = 24;
+ minHeight = 24;
+ layoutBorderSize = 1;
+ iconWidth = 24;
+ iconHeight = 24;
+ symbolWidth = 16;
+ symbolHeight = 16;
+ symbolOffsetX = 0;
+ symbolOffsetY = -1;
+
+ break;
+ }
+ default:
+ {
+ layoutGap = 4;
+ minWidth = 32;
+ minHeight = 32;
+ layoutBorderSize = 2;
+ iconWidth = 32;
+ iconHeight = 32;
+ symbolWidth = 20;
+ symbolHeight = 20;
+ symbolOffsetX = 0.5;
+ symbolOffsetY = 0;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * CheckBox chromeColor is drawn to match the FXG rectangle
+ * shape and position.
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // super draws a transparent hit zone
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ // get the size and position of iconDisplay
+ var currentIcon:DisplayObject = getIconDisplay();
+ var widthAdjustment:Number = layoutBorderSize * 2;
+
+ graphics.beginFill(getStyle("chromeColor"));
+ graphics.drawRoundRect(currentIcon.x + layoutBorderSize,
+ currentIcon.y + layoutBorderSize,
+ currentIcon.width - widthAdjustment,
+ currentIcon.height - widthAdjustment, layoutBorderSize, layoutBorderSize);
+ graphics.endFill();
+ }
+
+ /**
+ * List of IDs of items that should be excluded when rendering the focus ring.
+ * Only items of type DisplayObject or GraphicElement should be excluded. Items
+ * of other types are ignored.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ override protected function get focusSkinExclusions():Array
+ {
+ return exclusions;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+ if(symbolIcon != null)
+ {
+ symbolIcon.width = symbolWidth;
+ symbolIcon.height = symbolHeight;
+ }
+ var iconDisplay:DisplayObject = getIconDisplay();
+ if(iconDisplay != null)
+ {
+ iconDisplay.width = iconWidth;
+ iconDisplay.height = iconHeight;
+ }
+ }
+
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+ // position the symbols to align with the background "icon"
+ if (symbolIcon)
+ {
+ var currentIcon:DisplayObject = getIconDisplay();
+ setElementPosition(symbolIcon, symbolOffsetX, symbolOffsetY);
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/HScrollBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HScrollBarSkin.as
new file mode 100644
index 0000000000..1a99e1bf1c
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HScrollBarSkin.as
@@ -0,0 +1,205 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.Button;
+import spark.components.HScrollBar;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for HScrollBar components in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class HScrollBarSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function HScrollBarSkin()
+ {
+ super();
+
+ minWidth = 20;
+ thumbSkinClass = HScrollBarThumbSkin;
+ var paddingBottom:int;
+ var paddingHorizontal:int;
+
+ // Depending on density set our measured height
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ minHeight = 24;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_640DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ minHeight = 18;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_480DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ minHeight = 12;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_320DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ minHeight = 9;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_240DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ minHeight = 5;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_120DPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_120DPI;
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ minHeight = 6;
+ paddingBottom = HScrollBarThumbSkin.PADDING_BOTTOM_DEFAULTDPI;
+ paddingHorizontal = HScrollBarThumbSkin.PADDING_HORIZONTAL_DEFAULTDPI;
+ break;
+ }
+ }
+
+ // The minimum width is set such that, at it's smallest size, the thumb appears
+ // as wide as it is high.
+ minThumbWidth = (minHeight - paddingBottom) + (paddingHorizontal * 2);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:HScrollBar;
+
+ /**
+ * Minimum width for the thumb
+ */
+ protected var minThumbWidth:Number;
+
+ /**
+ * Skin to use for the thumb Button skin part
+ */
+ protected var thumbSkinClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * HScrollbar track skin part.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var track:Button;
+
+ /**
+ * HScrollbar thumb skin part.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var thumb:Button;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Create our skin parts if necessary: track and thumb.
+ if (!track)
+ {
+ // We don't want a visible track so we set the skin to MobileSkin
+ track = new Button();
+ track.setStyle("skinClass", spark.skins.mobile.supportClasses.MobileSkin);
+ track.width = minWidth;
+ track.height = minHeight;
+ addChild(track);
+ }
+
+ if (!thumb)
+ {
+ thumb = new Button();
+ thumb.minWidth = minThumbWidth;
+ thumb.setStyle("skinClass", thumbSkinClass);
+ thumb.width = minHeight;
+ thumb.height = minHeight;
+ addChild(thumb);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(track, unscaledWidth, unscaledHeight);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/HScrollBarThumbSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HScrollBarThumbSkin.as
new file mode 100644
index 0000000000..90d758f967
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HScrollBarThumbSkin.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 spark.skins.ios7
+{
+
+import flash.display.CapsStyle;
+import flash.display.JointStyle;
+import flash.display.LineScaleMode;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.Button;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for the HScrollBar thumb skin part in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class HScrollBarThumbSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ // These constants are also accessed from HScrollBarSkin
+ mx_internal static const PADDING_BOTTOM_640DPI:int = 10;
+ mx_internal static const PADDING_HORIZONTAL_640DPI:int = 8;
+ mx_internal static const PADDING_BOTTOM_480DPI:int = 8;
+ mx_internal static const PADDING_HORIZONTAL_480DPI:int = 6;
+ mx_internal static const PADDING_BOTTOM_320DPI:int = 5;
+ mx_internal static const PADDING_HORIZONTAL_320DPI:int = 4;
+ mx_internal static const PADDING_BOTTOM_240DPI:int = 4;
+ mx_internal static const PADDING_HORIZONTAL_240DPI:int = 3;
+ mx_internal static const PADDING_BOTTOM_120DPI:int = 2;
+ mx_internal static const PADDING_HORIZONTAL_120DPI:int = 2;
+ mx_internal static const PADDING_BOTTOM_DEFAULTDPI:int = 3;
+ mx_internal static const PADDING_HORIZONTAL_DEFAULTDPI:int = 2;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function HScrollBarThumbSkin()
+ {
+ super();
+
+ // Depending on density set padding
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ paddingBottom = PADDING_BOTTOM_640DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ paddingBottom = PADDING_BOTTOM_480DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ paddingBottom = PADDING_BOTTOM_320DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ paddingBottom = PADDING_BOTTOM_240DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ paddingBottom = PADDING_BOTTOM_120DPI;
+ paddingHorizontal = PADDING_HORIZONTAL_120DPI;
+ break;
+ }
+ default:
+ {
+ paddingBottom = PADDING_BOTTOM_DEFAULTDPI;
+ paddingHorizontal = PADDING_HORIZONTAL_DEFAULTDPI;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Padding from bottom.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingBottom:int;
+
+ /**
+ * Horizontal padding from left and right.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingHorizontal:int;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var thumbHeight:Number = unscaledHeight - paddingBottom;
+
+ graphics.beginFill(getStyle("thumbColor"), 1);
+ graphics.drawRect(paddingHorizontal + .5, 0.5, unscaledWidth - 2 * paddingHorizontal, thumbHeight);
+
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderSkin.as
new file mode 100644
index 0000000000..db59b7fefc
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderSkin.as
@@ -0,0 +1,300 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.BlendMode;
+ import flash.display.DisplayObject;
+ import flash.events.Event;
+
+ import mx.core.ClassFactory;
+ import mx.core.IFactory;
+ import mx.events.FlexEvent;
+
+ import spark.components.Button;
+ import spark.components.HSlider;
+ import spark.skins.ios7.assets.HSliderTrack_filled;
+ import spark.skins.mobile.supportClasses.HSliderDataTip;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ /**
+ * Android 4.x specific ActionScript-based skin for HSlider controls in mobile applications.
+ *
+ *
The base Flex implementation creates an HSlider with fixed height
+ * and variable width with a fixed-size thumb. As the height of the
+ * HSlider component increases, the vertical dimensions of the visible HSlider remain
+ * the same, and the HSlider stays vertically centered.
+ *
+ *
The thumb and track implementations can be customized by subclassing
+ * this skin class and overriding the thumbSkinClass, trackSkinClass,
+ * and/or dataTipClass variables as necessary.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class HSliderSkin extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function HSliderSkin()
+ {
+ super();
+
+ thumbSkinClass = spark.skins.ios7.HSliderThumbSkin;
+ trackSkinClass = spark.skins.ios7.HSliderTrackSkin;
+ filledTrackSkinClass = spark.skins.ios7.assets.HSliderTrack_filled;
+ dataTipClass = spark.skins.mobile.supportClasses.HSliderDataTip;
+
+ blendMode = BlendMode.LAYER;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ private var _hostComponent:HSlider;
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public function get hostComponent():HSlider
+ {
+ return _hostComponent;
+ }
+
+ public function set hostComponent(value:HSlider):void
+ {
+ if (_hostComponent)
+ {
+ _hostComponent.removeEventListener(Event.CHANGE, thumbPositionChanged_handler);
+ _hostComponent.removeEventListener(FlexEvent.VALUE_COMMIT, thumbPositionChanged_handler);
+ }
+ _hostComponent = value;
+ if (_hostComponent)
+ {
+ _hostComponent.addEventListener(Event.CHANGE, thumbPositionChanged_handler);
+ _hostComponent.addEventListener(FlexEvent.VALUE_COMMIT, thumbPositionChanged_handler);
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * HSlider track skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var track:Button;
+
+ /**
+ * HSlider track skin part that
+ * depicts area that is filled
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var filledTrack:DisplayObject;
+
+ /**
+ * HSlider thumb skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var thumb:Button;
+
+ /**
+ * HSlider dataTip class factory
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var dataTip:IFactory;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Specifies the skin class that will be used for the HSlider thumb.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbSkinClass:Class;
+
+ /**
+ * Specifies the skin class that will be used for the HSlider track.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackSkinClass:Class;
+ /**
+ * Specifies the skin class that will be used for the HSlider track's
+ * filled area.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var filledTrackSkinClass:Class;
+
+ /**
+ * Specifies the class that will be used for the HSlider datatip.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var dataTipClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ if (currentState == "disabled")
+ alpha = 0.5;
+ else if (currentState == "normal")
+ alpha = 1;
+ }
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Create our skin parts: track and thumb
+ track = new Button();
+ track.setStyle("skinClass", trackSkinClass);
+ addChild(track);
+
+ filledTrack = new filledTrackSkinClass();
+ addChild(filledTrack);
+
+ thumb = new Button();
+ thumb.setStyle("skinClass", thumbSkinClass);
+ addChild(thumb);
+
+ // Set up the class factory for the dataTip
+ dataTip = new ClassFactory();
+ ClassFactory(dataTip).generator = dataTipClass;
+ }
+
+ /**
+ * @private
+ * The HSliderSkin width will be no less than the width of the thumb skin.
+ * The HSliderSkin height will be no less than the greater of the heights of
+ * the thumb and track skins.
+ */
+ override protected function measure():void
+ {
+ measuredWidth = track.getPreferredBoundsWidth();
+ measuredHeight = Math.max(track.getPreferredBoundsHeight(), thumb.getPreferredBoundsHeight());
+
+ measuredMinHeight = Math.max(track.getPreferredBoundsHeight(), thumb.getPreferredBoundsHeight());
+ measuredMinWidth = thumb.getPreferredBoundsWidth();
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // minimum height is no smaller than the larger of the thumb or track
+ var calculatedSkinHeight:int = Math.max(Math.max(thumb.getPreferredBoundsHeight(), track.getPreferredBoundsHeight()),
+ unscaledHeight);
+
+ // minimum width is no smaller than the thumb
+ var calculatedSkinWidth:int = Math.max(thumb.getPreferredBoundsWidth(),
+ unscaledWidth);
+
+ // once we know the skin height, center the thumb and track
+ thumb.y = Math.max(Math.round((calculatedSkinHeight - thumb.getPreferredBoundsHeight()) / 2), 0);
+ var calculatedTrackY:int = Math.max(Math.round((calculatedSkinHeight - track.getPreferredBoundsHeight()) / 2), 0);
+
+ // size and position
+ setElementSize(thumb, thumb.getPreferredBoundsWidth(), thumb.getPreferredBoundsHeight()); // thumb does NOT scale
+ setElementSize(track, calculatedSkinWidth, track.getPreferredBoundsHeight()); // note track is NOT scaled vertically
+ setElementPosition(track, 0, calculatedTrackY);
+
+ //Set size and position of filled area based on thumb's current location
+ var filledTrackWidth:Number = thumb.getLayoutBoundsX();
+ setElementSize(filledTrack, filledTrackWidth, track.getPreferredBoundsHeight()); // note track is NOT scaled vertically
+ setElementPosition(filledTrack, track.x + HSliderTrackSkin(track.skin).visibleTrackOffset , calculatedTrackY);
+ }
+
+ private function thumbPositionChanged_handler(event:Event):void
+ {
+ //Just trigger a redraw so that the filled area of the track updates itself
+ invalidateDisplayList();
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderThumbSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderThumbSkin.as
new file mode 100644
index 0000000000..9f770300c1
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderThumbSkin.as
@@ -0,0 +1,333 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+import spark.components.Button;
+import spark.skins.ios7.assets.HSliderThumb_normal;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+/**
+ * Android 4.x specific ActionScript-based skin for the HSlider thumb skin part in mobile applications.
+ *
+ *
Note that this particular implementation defines a hit zone which is larger than
+ * the visible thumb for better usability on mobile screens.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class HSliderThumbSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function HSliderThumbSkin()
+ {
+ super();
+
+ thumbNormalClass = spark.skins.ios7.assets.HSliderThumb_normal;
+ thumbPressedClass = spark.skins.ios7.assets.HSliderThumb_pressed;
+
+ // set the dimensions to use based on the screen density
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ thumbImageWidth = 116;
+ thumbImageHeight = 116;
+
+ hitZoneOffset = 20;
+ hitZoneSideLength = 160;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ // Note provisional may need changes
+ thumbImageWidth = 88;
+ thumbImageHeight = 88;
+
+ hitZoneOffset = 20;
+ hitZoneSideLength = 130;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ thumbImageWidth = 58;
+ thumbImageHeight = 58;
+
+ hitZoneOffset = 10;
+ hitZoneSideLength = 80;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ thumbImageWidth = 44;
+ thumbImageHeight = 44;
+
+ hitZoneOffset = 10;
+ hitZoneSideLength = 65;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ thumbImageWidth = 22;
+ thumbImageHeight = 22;
+
+ hitZoneOffset = 5;
+ hitZoneSideLength = 33;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ thumbImageWidth = 29;
+ thumbImageHeight = 29;
+
+ hitZoneOffset = 5;
+ hitZoneSideLength = 40;
+
+ break;
+ }
+
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ // FXG thumb classes
+ /**
+ * Specifies the FXG class to use when the thumb is in the normal state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbNormalClass:Class;
+
+ /**
+ * Specifies the FXG class to use when the thumb is in the pressed state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbPressedClass:Class;
+
+ /**
+ * Specifies the DisplayObject to use when the thumb is in the normal state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbSkin_normal:DisplayObject;
+
+ /**
+ * Specifies the DisplayObject to use when the thumb is in the pressed state
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbSkin_pressed:DisplayObject;
+
+ /**
+ * Specifies the current DisplayObject that should be shown
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var currentThumbSkin:DisplayObject;
+
+ /**
+ * Width of the overall thumb image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbImageWidth:int;
+
+ /**
+ * Height of the overall thumb image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var thumbImageHeight:int;
+
+ /**
+ * Length of the sizes of the hitzone (assumed to be square)
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var hitZoneSideLength:int;
+
+ /**
+ * Distance between the left edge of the hitzone and the left edge
+ * of the thumb
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var hitZoneOffset:int;
+
+ /**
+ * @private
+ * Remember which state is currently being displayed
+ */
+ private var displayedState:String;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ if (currentState == "up")
+ {
+ // show the normal button
+ if (!thumbSkin_normal)
+ {
+ thumbSkin_normal = new thumbNormalClass();
+ addChild(thumbSkin_normal);
+ }
+ else
+ {
+ thumbSkin_normal.visible = true;
+ }
+ currentThumbSkin = thumbSkin_normal;
+
+ // hide the pressed button
+ if (thumbSkin_pressed)
+ thumbSkin_pressed.visible = false;
+ }
+ else if (currentState == "down")
+ {
+ // show the pressed button
+ if (!thumbSkin_pressed)
+ {
+ thumbSkin_pressed = new thumbPressedClass();
+ addChild(thumbSkin_pressed);
+ }
+ else
+ {
+ thumbSkin_pressed.visible = true;
+ }
+ currentThumbSkin = thumbSkin_pressed;
+
+ // hide the normal button
+ if (thumbSkin_normal)
+ thumbSkin_normal.visible = false;
+ }
+
+ displayedState = currentState;
+
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = thumbImageWidth;
+ measuredHeight = thumbImageHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(currentThumbSkin, unscaledWidth, unscaledHeight);
+ setElementPosition(currentThumbSkin, 0, 0)
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // put in a larger hit zone than the thumb
+ graphics.beginFill(0xffffff, 0);
+ graphics.drawRect(-hitZoneOffset, -hitZoneOffset, hitZoneSideLength, hitZoneSideLength);
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderTrackSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderTrackSkin.as
new file mode 100644
index 0000000000..3b2aec93ee
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/HSliderTrackSkin.as
@@ -0,0 +1,227 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+ import spark.components.Button;
+ import spark.skins.ios7.assets.HSliderTrack;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ /**
+ * ActionScript-based skin for the HSlider track skin part in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class HSliderTrackSkin extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function HSliderTrackSkin()
+ {
+ super();
+
+ trackClass = spark.skins.ios7.assets.HSliderTrack;
+
+ // set the right dimensions to use based on the screen density
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ trackWidth = 1200;
+ trackHeight = 8;
+
+ visibleTrackOffset = 48;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ trackWidth = 900;
+ trackHeight = 6;
+
+ visibleTrackOffset = 38;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ trackWidth = 600;
+ trackHeight = 4;
+
+ visibleTrackOffset = 24;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ trackWidth = 450;
+ trackHeight = 3;
+
+ visibleTrackOffset = 18;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ trackWidth = 225;
+ trackHeight = 2;
+
+ visibleTrackOffset = 9;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ trackWidth = 300;
+ trackHeight = 2;
+
+ visibleTrackOffset = 12;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Specifies the FXG class to use for the track image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackClass:Class;
+
+ /**
+ * Specifies the DisplayObject for the track image
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackSkin:DisplayObject;
+
+ /**
+ * Specifies the track image width
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackWidth:int;
+
+ /**
+ * Specifies the track image height
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var trackHeight:int;
+
+ /**
+ * Specifies the offset from the left and right edge to where
+ * the visible track begins. This should match the offset in the FXG assets.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var visibleTrackOffset:int;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ trackSkin = new trackClass();
+ addChild(trackSkin);
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = trackWidth;
+ measuredHeight = trackHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ var unscaledTrackWidth:int = unscaledWidth - (2 * visibleTrackOffset);
+ setElementSize(trackSkin, unscaledTrackWidth, unscaledHeight);
+ setElementPosition(trackSkin, visibleTrackOffset, 0);
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/IOS7ButtonBarButtonSkinBase.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/IOS7ButtonBarButtonSkinBase.as
new file mode 100644
index 0000000000..9ef5d38141
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/IOS7ButtonBarButtonSkinBase.as
@@ -0,0 +1,161 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+ import spark.skins.ios7.assets.ButtonBarMiddleButton_down;
+ import spark.skins.ios7.assets.ButtonBarMiddleButton_up;
+ import spark.skins.mobile.supportClasses.ButtonBarButtonSkinBase;
+
+ /**
+ * iOS7+ specific Button skin base for the Buttons in a ButtonBar.
+ *
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class IOS7ButtonBarButtonSkinBase extends ButtonBarButtonSkinBase
+ {
+
+ /**
+ * Class to use for the border in the selected and down state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var selectedDownBorderSkin:Class;
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function IOS7ButtonBarButtonSkinBase()
+ {
+ super();
+
+ // set the dimensions to use based on the screen density
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultHeight = 116;
+ measuredDefaultWidth = 400;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ measuredDefaultHeight = 88;
+ measuredDefaultWidth = 300;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultHeight = 58;
+ measuredDefaultWidth = 200;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultHeight = 44;
+ measuredDefaultWidth = 150;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultHeight = 22;
+ measuredDefaultWidth = 75;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ measuredDefaultHeight = 29;
+ measuredDefaultWidth = 100;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ //Dont draw background
+ }
+
+ override protected function getBorderClassForCurrentState():Class
+ {
+ var isSelected:Boolean = currentState.indexOf("Selected") >= 0;
+ var isDown:Boolean = currentState.indexOf("down") >= 0;
+
+ if (isSelected && !isDown )
+ return selectedBorderSkin;
+ else if (isSelected && isDown)
+ return selectedDownBorderSkin;
+ else if (!isSelected && !isDown)
+ return upBorderSkin;
+ else
+ return downBorderSkin;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+ var isSelected:Boolean = currentState.indexOf("Selected") >= 0;
+ var isDown:Boolean = currentState.indexOf("down") >= 0;
+
+ if(xor(isSelected,isDown))
+ {
+ var highlightColor:uint = getStyle("highlightTextColor");
+ labelDisplay.setStyle("color",highlightColor);
+ }
+ else
+ {
+ var color:uint = getStyle("color");
+ labelDisplay.setStyle("color",color);
+ }
+
+ }
+
+ private function xor(lhs:Boolean, rhs:Boolean):Boolean {
+ return !( lhs && rhs ) && ( lhs || rhs );
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/RadioButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/RadioButtonSkin.as
new file mode 100644
index 0000000000..4eaf8231fa
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/RadioButtonSkin.as
@@ -0,0 +1,253 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+
+import spark.skins.ios7.assets.RadioButton_up;
+import spark.skins.mobile.supportClasses.SelectableButtonSkinBase;
+
+/**
+ * ActionScript-based skin for RadioButton controls in mobile applications.
+ *
+ * @see spark.components.RadioButton
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class RadioButtonSkin extends SelectableButtonSkinBase
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ static private const exclusions:Array = ["labelDisplay", "labelDisplayShadow"];
+
+ //--------------------------------------------------------------------------
+ //
+ // Member variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var symbolOffsetX:Number;
+ protected var symbolOffsetY:Number;
+ protected var iconWidth:Number;
+ protected var iconHeight:Number;
+ protected var symbolWidth:Number;
+ protected var symbolHeight:Number;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function RadioButtonSkin()
+ {
+ super();
+
+ layoutPaddingLeft = 0;
+ layoutPaddingRight = 0;
+ layoutPaddingTop = 0;
+ layoutPaddingBottom = 0;
+
+ upIconClass = spark.skins.ios7.assets.RadioButton_up;
+ upSelectedIconClass = spark.skins.ios7.assets.RadioButton_up;
+ downIconClass = spark.skins.ios7.assets.RadioButton_down;
+ downSelectedIconClass = spark.skins.ios7.assets.RadioButton_down;
+ upSymbolIconClass = null;
+ downSymbolIconClass = null;
+ upSymbolIconSelectedClass = spark.skins.ios7.assets.RadioButton_upSymbolSelected;
+ downSymbolIconSelectedClass = spark.skins.ios7.assets.RadioButton_downSymbolSelected;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ layoutGap = 16;
+ minWidth = 128;
+ minHeight = 128;
+ iconWidth = 128;
+ iconHeight = 128;
+ symbolWidth = 44;
+ symbolHeight = 44;
+ symbolOffsetX = 44;
+ symbolOffsetY = 44;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ layoutGap = 12;
+ minWidth = 96;
+ minHeight = 96;
+ iconWidth = 96;
+ iconHeight = 96;
+ symbolWidth = 33;
+ symbolHeight = 33;
+ symbolOffsetX = 33;
+ symbolOffsetY = 33;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ layoutGap = 8;
+ minWidth = 64;
+ minHeight = 64;
+ iconWidth = 64;
+ iconHeight = 64;
+ symbolWidth = 22;
+ symbolHeight = 22;
+ symbolOffsetX = 22;
+ symbolOffsetY = 22;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+
+ layoutGap = 6;
+ minWidth = 48;
+ minHeight = 48;
+ iconWidth = 48;
+ iconHeight = 48;
+ symbolWidth = 16.5;
+ symbolHeight = 16.5;
+ symbolOffsetX = 16.5;
+ symbolOffsetY = 16.5;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+
+ layoutGap = 3;
+ minWidth = 24;
+ minHeight = 24;
+ iconWidth = 24;
+ iconHeight = 24;
+ symbolWidth = 8.25;
+ symbolHeight = 8.25;
+ symbolOffsetX = 8.25;
+ symbolOffsetY = 8.25;
+
+ break;
+ }
+ default:
+ {
+
+ layoutGap = 4;
+ minWidth = 32;
+ minHeight = 32;
+ iconWidth = 32;
+ iconHeight = 32;
+ symbolWidth = 11;
+ symbolHeight = 11;
+ symbolOffsetX = 11;
+ symbolOffsetY = 11;
+
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * RadioButton chromeColor is drawn to match the FXG ellipse
+ * shape and position.
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // super draws a transparent hit zone
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ // get the size and position of iconDisplay
+ var currentIcon:DisplayObject = getIconDisplay();
+
+ graphics.beginFill(getStyle("chromeColor"));
+ graphics.drawEllipse(currentIcon.x + 1, currentIcon.y + 1, currentIcon.width - 2, currentIcon.height - 2);
+ graphics.endFill();
+ }
+
+ /**
+ * @private
+ */
+ override protected function get focusSkinExclusions():Array
+ {
+ return exclusions;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+ if(symbolIcon != null)
+ {
+ symbolIcon.width = symbolWidth;
+ symbolIcon.height = symbolHeight;
+ }
+ var iconDisplay:DisplayObject = getIconDisplay();
+ if(iconDisplay != null)
+ {
+ iconDisplay.width = iconWidth;
+ iconDisplay.height = iconHeight;
+ }
+ }
+
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+ // position the symbols to align with the background "icon"
+ if (symbolIcon)
+ {
+ var currentIcon:DisplayObject = getIconDisplay();
+ setElementPosition(symbolIcon, symbolOffsetX, symbolOffsetY);
+ }
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListContainerSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListContainerSkin.as
new file mode 100644
index 0000000000..aa2b05b647
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListContainerSkin.as
@@ -0,0 +1,261 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.Graphics;
+ import flash.display.InteractiveObject;
+ import flash.display.Sprite;
+
+ import mx.core.DPIClassification;
+ import mx.core.mx_internal;
+
+ import spark.components.Group;
+ import spark.components.SpinnerListContainer;
+ import spark.layouts.HorizontalLayout;
+ import spark.skins.ios7.assets.SpinnerListContainerBackground;
+ import spark.skins.ios7.assets.SpinnerListContainerSelectionIndicator;
+ import spark.skins.ios7.assets.SpinnerListContainerShadow;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ use namespace mx_internal;
+ /**
+ * ActionScript-based skin for the SpinnerListContainer in mobile applications.
+ *
+ * @see spark.components.SpinnerListContainer
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public class SpinnerListContainerSkin extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ *
+ */
+ public function SpinnerListContainerSkin()
+ {
+ super();
+
+ borderClass = spark.skins.ios7.assets.SpinnerListContainerBackground;
+ selectionIndicatorClass = spark.skins.ios7.assets.SpinnerListContainerSelectionIndicator;
+ cornerRadius = 0;
+ borderThickness = 0;
+
+
+ minWidth = 30;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Pixel thickness of the border.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderThickness:Number;
+
+ /**
+ * Radius of the border corners.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var cornerRadius:Number;
+
+ /**
+ * Height of the selection indicator.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+
+ /**
+ * Class for the border part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderClass:Class;
+
+ /**
+ * Class for the selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicatorClass:Class;
+
+ /**
+ * Border skin part which includes the background.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var border:InteractiveObject;
+
+ /**
+ * Selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicator:InteractiveObject;
+
+ /**
+ * Mask for the content group.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var contentGroupMask:Sprite;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * An optional skin part that defines the Group where the content
+ * children are pushed into and laid out.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var contentGroup:Group;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var hostComponent:SpinnerListContainer;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Methods
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!border)
+ {
+ // Border and background
+ border = new borderClass();
+ border.mouseEnabled = false;
+ addChild(border);
+ }
+
+ if (!contentGroup)
+ {
+ // Contains the child elements
+ contentGroup = new Group();
+ var hLayout:HorizontalLayout = new HorizontalLayout();
+ hLayout.gap = 0;
+ hLayout.verticalAlign = "middle";
+ contentGroup.layout = hLayout;
+ contentGroup.id = "contentGroup";
+ addChild(contentGroup);
+ }
+
+ if (!contentGroupMask)
+ {
+ // Create a mask for the content
+ contentGroupMask = new Sprite();
+ addChild(contentGroupMask);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var contentW:Number = contentGroup.getPreferredBoundsWidth();
+ var contentH:Number = contentGroup.getPreferredBoundsHeight();
+
+ measuredWidth = measuredMinWidth = contentW + borderThickness * 2;
+ measuredHeight = contentH + borderThickness * 2;
+
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(contentGroup, unscaledWidth - borderThickness * 2, unscaledHeight - borderThickness * 2);
+ setElementPosition(contentGroup, borderThickness, borderThickness);
+
+ // Inset by the borderThickness horizontally because the selectionIndicator starts at 0
+ setElementSize(border, unscaledWidth - borderThickness * 2, unscaledHeight);
+ setElementPosition(border, borderThickness, 0);
+
+ // The SpinnerLists contain a left and right border. We don't want to show the leftmost
+ // SpinnerLists's left border nor the rightmost one's right border.
+ // We inset the mask on the left and right sides to accomplish this.
+ var g:Graphics = contentGroupMask.graphics;
+ g.clear();
+ g.beginFill(0x00FF00);
+ g.drawRoundRect(borderThickness * 2, borderThickness, unscaledWidth - borderThickness * 4, unscaledHeight - borderThickness * 2, cornerRadius, cornerRadius);
+ g.endFill();
+
+ contentGroup.mask = contentGroupMask;
+ }
+ }
+}
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListScrollerSkin.mxml b/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListScrollerSkin.mxml
new file mode 100644
index 0000000000..270818e903
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListScrollerSkin.mxml
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListSkin.as
new file mode 100644
index 0000000000..57a90b8156
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/SpinnerListSkin.as
@@ -0,0 +1,328 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.InteractiveObject;
+
+ import mx.core.ClassFactory;
+ import mx.core.DPIClassification;
+ import mx.core.mx_internal;
+
+ import spark.components.DataGroup;
+ import spark.components.Scroller;
+ import spark.components.SpinnerList;
+ import spark.components.SpinnerListItemRenderer;
+ import spark.layouts.VerticalSpinnerLayout;
+ import spark.skins.ios7.assets.SpinnerListContainerSelectionIndicator;
+ import spark.skins.ios7.assets.SpinnerListContainerShadow;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+
+ use namespace mx_internal;
+ /**
+ * ActionScript-based skin for the SpinnerList in mobile applications.
+ *
+ * @see spark.components.SpinnerList
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public class SpinnerListSkin extends MobileSkin
+ {
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public function SpinnerListSkin()
+ {
+ super();
+
+ selectionIndicatorClass = spark.skins.ios7.assets.SpinnerListContainerSelectionIndicator;
+ shadowClass = spark.skins.ios7.assets.SpinnerListContainerShadow;
+ borderThickness = 1;
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ selectionIndicatorHeight = 144;
+ minWidth = 64;
+ borderThickness = 3;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ selectionIndicatorHeight = 96;
+ minWidth = 48;
+ borderThickness = 2;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ selectionIndicatorHeight = 72;
+ minWidth = 32;
+ borderThickness = 2;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ selectionIndicatorHeight = 48;
+ minWidth = 24;
+ borderThickness = 1;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ selectionIndicatorHeight = 24;
+ minWidth = 12;
+ borderThickness = 0;
+ break;
+ }
+ default:
+ {
+ selectionIndicatorHeight = 36;
+ minWidth = 16;
+ borderThickness = 1;
+ }
+ }
+
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Scroller skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var scroller:Scroller;
+
+ /**
+ * DataGroup skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var dataGroup:DataGroup;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var hostComponent:SpinnerList;
+
+ /**
+ * Pixel size of the border.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var borderThickness:int;
+
+ /**
+ * Class for the selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicatorClass:Class;
+
+ /**
+ * Selection indicator skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicator:InteractiveObject;
+
+ /**
+ * Height of the selection indicator.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var selectionIndicatorHeight:Number;
+
+ /**
+ * Class for the shadow skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var shadowClass:Class;
+
+ /**
+ * Shadow skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var shadow:InteractiveObject;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+ }
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!dataGroup)
+ {
+ // Create data group layout
+ var layout:VerticalSpinnerLayout = new VerticalSpinnerLayout();
+ layout.requestedRowCount = 9;
+ layout.rowHeight = selectionIndicatorHeight/1.5;
+ layout.gap = 0;
+
+ // Create data group
+ dataGroup = new DataGroup();
+ dataGroup.id = "dataGroup";
+ dataGroup.layout = layout;
+
+ dataGroup.itemRenderer = new ClassFactory(spark.components.SpinnerListItemRenderer);
+ }
+
+ if (!scroller)
+ {
+ // Create scroller
+ scroller = new Scroller();
+ scroller.id = "scroller";
+ scroller.hasFocusableChildren = false;
+ scroller.ensureElementIsVisibleForSoftKeyboard = false;
+
+ // Only support vertical scrolling
+ scroller.setStyle("verticalScrollPolicy","on");
+ scroller.setStyle("horizontalScrollPolicy", "off");
+ scroller.setStyle("skinClass", spark.skins.ios7.SpinnerListScrollerSkin);
+
+ addChild(scroller);
+ }
+
+ if (!shadow)
+ {
+ // Shadowing sits on top of the content
+ shadow = new shadowClass();
+ shadow.mouseEnabled = false;
+ addChild(shadow);
+ }
+
+ if (!selectionIndicator)
+ {
+ // Selection indicator is on top
+ selectionIndicator = new selectionIndicatorClass();
+ selectionIndicator.mouseEnabled = false;
+ addChild(selectionIndicator);
+ }
+
+ // Associate scroller with data group
+ if (!scroller.viewport)
+ scroller.viewport = dataGroup;
+
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ measuredWidth = scroller.getPreferredBoundsWidth() + borderThickness * 2;
+ measuredHeight = scroller.getPreferredBoundsHeight();
+ //add in for selection indicator
+ measuredMinHeight = selectionIndicatorHeight + borderThickness * 4;
+ minHeight = measuredMinHeight;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // Scroller
+ setElementSize(scroller, unscaledWidth - borderThickness * 2, unscaledHeight);
+ setElementPosition(scroller, borderThickness, 0);
+ //selection indicator
+ unscaledHeight = Math.max(unscaledHeight, selectionIndicatorHeight + borderThickness * 4);
+
+ setElementSize(selectionIndicator, unscaledWidth, selectionIndicatorHeight);
+ setElementPosition(selectionIndicator, 0, Math.floor((unscaledHeight - selectionIndicatorHeight) / 2));
+
+ setElementSize(shadow, unscaledWidth - borderThickness * 2, unscaledHeight);
+ setElementPosition(shadow, borderThickness, 0);
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ // Reinitialize the typical element so it picks up the latest styles
+ // Font styles might impact the size of the SpinnerList
+ if (styleProp != "color" && styleProp != "accentColor")
+ {
+ if (dataGroup)
+ dataGroup.invalidateTypicalItemRenderer();
+ }
+
+ super.styleChanged(styleProp);
+ }
+
+ }
+}
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/StageTextAreaSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/StageTextAreaSkin.as
new file mode 100644
index 0000000000..aca69348f2
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/StageTextAreaSkin.as
@@ -0,0 +1,190 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+ import mx.core.mx_internal;
+
+ import spark.components.TextArea;
+ import spark.components.supportClasses.IStyleableEditableText;
+ import spark.components.supportClasses.ScrollableStageText;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.ios7.supportClasses.StageTextSkinBase;
+
+ use namespace mx_internal;
+
+ /**
+ * ActionScript-based skin for TextArea controls in mobile applications that uses a
+ * StyleableStageText class for the text display.
+ *
+ * @see spark.components.TextArea
+ * @see spark.components.supportClasses.StyleableStageText
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public class StageTextAreaSkin extends StageTextSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Class variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * The underlying native text control on iOS has internal margins of its
+ * own. In order to remain faithful to the paddingTop and paddingBottom
+ * style values that developers may specify, those internal margins need to
+ * be compensated for. This variable contains size of that compensation in
+ * pixels.
+ */
+ mx_internal static var iOSVerticalPaddingAdjustment:Number = 5;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function StageTextAreaSkin()
+ {
+ super();
+ multiline = true;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultHeight = 212;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ measuredDefaultHeight = 140;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultHeight = 106;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultHeight = 70;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultHeight = 35;
+ break;
+ }
+ default:
+ {
+ measuredDefaultHeight = 48;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextArea; // SkinnableComponent will populate
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+ measureTextComponent(hostComponent);
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number,
+ unscaledHeight:Number):void
+ {
+ // base class handles border position & size
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size the text
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = Math.max(0, unscaledWidth - paddingLeft - paddingRight);
+ var unscaledTextHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+
+ if (textDisplay)
+ {
+ var verticalPosAdjustment:Number = 0;
+ var heightAdjustment:Number = 0;
+
+ /* if (Platform.isIOS)
+ {
+ verticalPosAdjustment = Math.min(iOSVerticalPaddingAdjustment, paddingTop);
+ heightAdjustment = verticalPosAdjustment + Math.min(iOSVerticalPaddingAdjustment, paddingBottom);
+ }*/
+
+ textDisplay.commitStyles();
+ setElementSize(textDisplay, unscaledTextWidth, unscaledTextHeight + heightAdjustment);
+ setElementPosition(textDisplay, paddingLeft, paddingTop - verticalPosAdjustment);
+ }
+
+ if (promptDisplay)
+ {
+ if (promptDisplay is StyleableTextField)
+ StyleableTextField(promptDisplay).commitStyles();
+
+ setElementSize(promptDisplay, unscaledTextWidth, unscaledTextHeight);
+ setElementPosition(promptDisplay, paddingLeft, paddingTop);
+ }
+ }
+
+ override protected function createTextDisplay():IStyleableEditableText
+ {
+ return new ScrollableStageText(multiline);
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/StageTextInputSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/StageTextInputSkin.as
new file mode 100644
index 0000000000..6d6c81110c
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/StageTextInputSkin.as
@@ -0,0 +1,133 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.components.TextInput;
+ import spark.components.supportClasses.IStyleableEditableText;
+ import spark.components.supportClasses.ScrollableStageText;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.ios7.supportClasses.StageTextSkinBase;
+
+ /**
+ * ActionScript-based skin for TextInput controls in mobile applications that uses a
+ * StyleableStageText class for the text input.
+ *
+ * @see spark.components.TextInput
+ * @see spark.components.supportClasses.StyleableStageText
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public class StageTextInputSkin extends StageTextSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public function StageTextInputSkin()
+ {
+ super();
+ multiline = false;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextInput; // SkinnableComponent will populate
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+ measureTextComponent(hostComponent);
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number,
+ unscaledHeight:Number):void
+ {
+ // base class handles border position & size
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size the text
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = Math.max(0, unscaledWidth - paddingLeft - paddingRight);
+ var unscaledTextHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
+
+ // default vertical positioning is centered
+ var textHeight:Number = getElementPreferredHeight(textDisplay);
+ var textY:Number = Math.round(0.5 * (unscaledTextHeight - textHeight)) + paddingTop;
+
+ if (textDisplay)
+ {
+ textDisplay.commitStyles();
+ setElementSize(textDisplay, unscaledTextWidth, unscaledTextHeight);
+ setElementPosition(textDisplay, paddingLeft, textY);
+ }
+
+ if (promptDisplay)
+ {
+ if (promptDisplay is StyleableTextField)
+ StyleableTextField(promptDisplay).commitStyles();
+
+ var promptHeight:Number = getElementPreferredHeight(promptDisplay);
+ var promptY:Number = Math.round(0.5 * (unscaledTextHeight - promptHeight)) + paddingTop;
+
+ setElementSize(promptDisplay, unscaledTextWidth, promptHeight);
+ setElementPosition(promptDisplay, paddingLeft, promptY);
+ }
+ }
+
+ override protected function createTextDisplay():IStyleableEditableText
+ {
+ return new ScrollableStageText(multiline);
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/TabbedViewNavigatorTabBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TabbedViewNavigatorTabBarSkin.as
new file mode 100644
index 0000000000..fe7a7ac86a
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TabbedViewNavigatorTabBarSkin.as
@@ -0,0 +1,120 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 spark.components.ButtonBarButton;
+import spark.components.DataGroup;
+import spark.skins.mobile.supportClasses.ButtonBarButtonClassFactory;
+import spark.skins.mobile.supportClasses.TabbedViewNavigatorTabBarHorizontalLayout;
+
+/**
+ * The iOS7+ specific skin class for the Spark TabbedViewNavigator tabBar skin part.
+ *
+ * @see spark.components.TabbedViewNavigator#tabBar
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TabbedViewNavigatorTabBarSkin extends ButtonBarSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function TabbedViewNavigatorTabBarSkin()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ if (!firstButton)
+ {
+ firstButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ firstButton.skinClass = spark.skins.ios7.ButtonBarFirstButtonSkin;
+ }
+
+ if (!lastButton)
+ {
+ lastButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ lastButton.skinClass = spark.skins.ios7.ButtonBarLastButtonSkin;
+ }
+
+ if (!middleButton)
+ {
+ middleButton = new ButtonBarButtonClassFactory(ButtonBarButton);
+ middleButton.skinClass = spark.skins.ios7.ButtonBarMiddleButtonSkin;
+ }
+
+ if (!dataGroup)
+ {
+ // TabbedViewNavigatorButtonBarHorizontalLayout for even percent layout
+ var tabLayout:TabbedViewNavigatorTabBarHorizontalLayout =
+ new TabbedViewNavigatorTabBarHorizontalLayout();
+ tabLayout.useVirtualLayout = false;
+
+ dataGroup = new DataGroup();
+ dataGroup.layout = tabLayout;
+ addChild(dataGroup);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ // backgroundAlpha style is not supported by ButtonBar
+ // TabbedViewNavigatorSkin sets a hard-coded value to support
+ // overlayControls
+ var backgroundAlphaValue:* = getStyle("backgroundAlpha");
+ var backgroundAlpha:Number = (backgroundAlphaValue === undefined)
+ ? 1 : getStyle("backgroundAlpha");
+
+ graphics.beginFill(getStyle("chromeColor"), backgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/TextAreaSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TextAreaSkin.as
new file mode 100644
index 0000000000..5133ae82cf
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TextAreaSkin.as
@@ -0,0 +1,889 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.events.Event;
+import flash.events.FocusEvent;
+import flash.events.KeyboardEvent;
+import flash.events.MouseEvent;
+import flash.events.SoftKeyboardEvent;
+import flash.geom.Point;
+import flash.geom.Rectangle;
+import flash.system.Capabilities;
+import flash.text.TextLineMetrics;
+import flash.ui.Keyboard;
+
+import mx.core.DPIClassification;
+import mx.core.EventPriority;
+import mx.core.FlexGlobals;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+import mx.utils.Platform;
+
+import spark.components.Group;
+import spark.components.Scroller;
+import spark.components.TextArea;
+import spark.components.supportClasses.StyleableTextField;
+import spark.events.CaretBoundsChangeEvent;
+import spark.skins.ios7.supportClasses.TextSkinBase;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for TextArea components in mobile applications.
+ *
+ * @see spark.components.TextArea
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TextAreaSkin extends TextSkinBase
+{
+ /**
+ * @private
+ * Right-margin of iOS native text control when editing on a retina display
+ * based on fontSize 32.
+ */
+ mx_internal static var IOS_RIGHT_MARGIN_320:Number = 19;
+
+ /**
+ * @private
+ * Right-margin of iOS native text control when editing on a retina display
+ * based on fontSize 16 scaling from applicationDPI 160.
+ */
+ mx_internal static var IOS_RIGHT_MARGIN_160_SCALED_TO_320:Number = 9.4;
+
+ /**
+ * @private
+ * Right-margin of iOS native text control when editing on a standard display
+ * based on fontSize 16 and runtimeDPI 160.
+ */
+ mx_internal static var IOS_RIGHT_MARGIN_160:Number = 20.6;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function TextAreaSkin()
+ {
+ super();
+
+ addEventListener(Event.RESIZE, resizeHandler);
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultWidth = 1024;
+ measuredDefaultHeight = 212;
+ layoutBorderSize = 3;
+ roundheight = 24;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ measuredDefaultWidth = 880;
+ measuredDefaultHeight = 140;
+ layoutBorderSize = 2;
+ roundheight = 18;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultWidth = 612;
+ measuredDefaultHeight = 106;
+ layoutBorderSize = 1.5;
+ roundheight = 14;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultWidth = 440;
+ measuredDefaultHeight = 70;
+ layoutBorderSize = 1;
+ roundheight = 10;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultWidth = 220;
+ measuredDefaultHeight = 35;
+ layoutBorderSize = .5;
+ roundheight = 5;
+ break;
+ }
+ default:
+ {
+ measuredDefaultWidth = 306;
+ measuredDefaultHeight = 53;
+ layoutBorderSize = .5;
+ roundheight = 7;
+ break;
+ }
+ }
+ addEventListener(FocusEvent.FOCUS_IN, focusChangeHandler);
+ addEventListener(FocusEvent.FOCUS_OUT, focusChangeHandler);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Scroller skin part.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var scroller:Scroller;
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextArea;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var isFocused:Boolean = false;
+
+ protected var roundheight:uint;
+
+ /**
+ * @private
+ * The width of the component on the previous layout manager
+ * pass. This gets set in updateDisplayList() and used in measure() on
+ * the next layout pass. This is so our "guessed width" in measure()
+ * will be as accurate as possible since textDisplay is multiline and
+ * the textDisplay height is dependent on the width.
+ *
+ * In the constructor this is actually set based on the DPI.
+ */
+ mx_internal var oldUnscaledWidth:Number;
+
+ private var textDisplayGroup:Group;
+ private var _isIOS:Boolean;
+ private var invalidateCaretPosition:Boolean = true;
+ private var oldCaretBounds:Rectangle = new Rectangle(-1, -1, -1, -1);
+ private var lastTextHeight:Number;
+ private var lastTextWidth:Number;
+
+ private var isTextDisplayTall:Boolean = true;
+ private var growTextDisplay:Boolean = false;
+ private var shrinkTextDisplay:Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ if (!textDisplay)
+ {
+ // wrap StyleableTextField in UIComponent
+ textDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ textDisplay.styleName = this;
+ textDisplay.multiline = true;
+ textDisplay.editable = true;
+ textDisplay.lineBreak = getStyle("lineBreak");
+ textDisplay.useTightTextBounds = false;
+ textDisplay.scrollToRangeDelegate = scrollToRange;
+
+ // on iOS, resize the TextField and let the native control handle scrolling
+ _isIOS = Platform.isIOS;
+
+ if (_isIOS)
+ {
+ // hard-coded rightMargin for iOS native text control
+ // this value is independent of the paddingRight style
+ var rightMargin:Number = 0;
+ var isRetina:Boolean = false;
+ var isScaling160to320:Boolean = false;
+
+ // check for scaling
+ if ("runtimeDPI" in FlexGlobals.topLevelApplication)
+ {
+ var runtimeDPI:Number = FlexGlobals.topLevelApplication.runtimeDPI as Number;
+ isRetina = (runtimeDPI == DPIClassification.DPI_320);
+ isScaling160to320 = isRetina
+ && (applicationDPI == DPIClassification.DPI_160);
+ }
+
+ if (isRetina && !isScaling160to320)
+ rightMargin = IOS_RIGHT_MARGIN_320;
+ else if (isRetina && isScaling160to320)
+ rightMargin = IOS_RIGHT_MARGIN_160_SCALED_TO_320;
+ else
+ rightMargin = IOS_RIGHT_MARGIN_160;
+
+ textDisplay.rightMargin = rightMargin;
+ }
+ else
+ {
+ textDisplay.addEventListener(KeyboardEvent.KEY_DOWN, textDisplay_keyHandler);
+ }
+
+ textDisplay.addEventListener(Event.CHANGE, textDisplay_changeHandler);
+ textDisplay.addEventListener(FlexEvent.VALUE_COMMIT, textDisplay_changeHandler);
+ textDisplay.addEventListener(Event.SCROLL, textDisplay_scrollHandler);
+ // Use a lower priority so that the StyleableTextField event handler is called first.
+ // That handler cancels the event and we need to check for that case
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, textDisplay_softKeyboardActivatingHandler, false, EventPriority.DEFAULT_HANDLER);
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATE, textDisplay_softKeyboardActivateHandler);
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, textDisplay_softKeyboardDeactivateHandler);
+
+ textDisplay.left = getStyle("paddingLeft");
+ textDisplay.top = getStyle("paddingTop");
+ textDisplay.right = getStyle("paddingRight");
+ textDisplay.bottom = getStyle("paddingBottom");
+
+ // wrap StyleableTextComponent in Group for viewport
+ textDisplayGroup = new Group();
+ textDisplayGroup.clipAndEnableScrolling = true;
+ textDisplayGroup.addElement(textDisplay);
+ }
+
+ if (!scroller)
+ {
+ scroller = new Scroller();
+ scroller.minViewportInset = 0;
+ scroller.measuredSizeIncludesScrollBars = false;
+ scroller.ensureElementIsVisibleForSoftKeyboard = false;
+
+ addChild(scroller);
+ }
+
+ if (!scroller.viewport)
+ scroller.viewport = textDisplayGroup;
+
+ super.createChildren();
+ }
+
+ /**
+ * @private
+ * TextArea prompt supports wrapping and multiline
+ */
+ override protected function createPromptDisplay():StyleableTextField
+ {
+ var prompt:StyleableTextField = super.createPromptDisplay();
+ prompt.editable = true;
+ prompt.wordWrap = true;
+
+ return prompt;
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+
+ // TextDisplay always defaults to 440 pixels wide (the value is DPI dependent),
+ // and tall enough to show all text.
+ //
+ // You can set an explicit width and the height will adjust accordingly. The opposite
+ // is not true: setting an explicit height will not adjust the width accordingly.
+
+ measuredWidth = measuredDefaultWidth;
+
+ // now we need to measure textDisplay's height. Unfortunately, this is tricky and
+ // is dependent on textDisplay's width. Let's use the heuristic that our width
+ // is the same as our last width.
+ // We don't use layoutMeasuredWidth, because that value is just a constant and doesn't
+ // take into account the fact that the TextArea could have an explicitWidth or could
+ // be constrained by some value. However, we still default oldTextDisplayWidth to
+ // be layoutMeasuredWidth the first time through.
+ var textDisplayEstimatedWidth:Number = oldUnscaledWidth - paddingLeft - paddingRight;
+
+ // now we need to measure textDisplay's height. Unfortunately, this is tricky and
+ // is dependent on textDisplay's width.
+ // Use the old textDisplay width as an estimte for the new one.
+ // If we are wrong, we'll find out in updateDisplayList()
+ textDisplay.commitStyles();
+
+ // Clear min sizes first.
+ textDisplay.minWidth = textDisplay.minHeight = NaN;
+
+ // If lineBreak == explicit, always use NaN for estimated width
+ if (getStyle("lineBreak") == "explicit")
+ textDisplayEstimatedWidth = NaN;
+
+ setElementSize(textDisplay, textDisplayEstimatedWidth, NaN);
+
+ measuredHeight = getElementPreferredHeight(textDisplay) + paddingTop + paddingBottom;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size border
+ if (border)
+ {
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+
+ setElementSize(scroller, unscaledWidth, unscaledHeight);
+ setElementPosition(scroller, 0, 0);
+
+ // position & size the text
+ var explicitLineBreak:Boolean = getStyle("lineBreak") == "explicit";
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = unscaledWidth - paddingLeft - paddingRight;
+ var unscaledTextHeight:Number = unscaledHeight - paddingTop - paddingBottom;
+ var textHeight:Number;
+ var textWidth:Number = explicitLineBreak ? textDisplay.measuredTextSize.x : unscaledTextWidth;
+
+ var lineIndex:int;
+ var topCharIndex:int;
+ var charBounds:Rectangle;
+
+ // grab old measured textDisplay height before resizing it
+ var oldPreferredTextHeight:Number = getElementPreferredHeight(textDisplay);
+
+ // set width first to measure height correctly
+ textDisplay.commitStyles();
+ textDisplay.setLayoutBoundsSize(textWidth, NaN);
+
+ // In iOS, when we go into editing mode, the runtime overlays a native
+ // text control over the textDisplay. In order to prevent the text
+ // from overflowing the component and to get scrolling support, the
+ // native text control must be the same size as the TextArea
+ if (_isIOS)
+ {
+ if (shrinkTextDisplay)
+ {
+ // Switching to edit mode. Convert from viewport scrolling to
+ // TextField scrolling
+ var vsp:Number = textDisplayGroup.verticalScrollPosition;
+
+ var lineMetrics:TextLineMetrics = textDisplay.getLineMetrics(0);
+ var lineHeight:Number = lineMetrics.ascent + lineMetrics.descent;
+
+ // TODO Figure out how to get the x offset. Right now is hard coded to 2
+ // At least half the line should be showing before we scroll to that line
+ // This makes the conversion from pixel to line based scrolling a little less jumpy
+ lineIndex = textDisplay.getLineIndexAtPoint(2, vsp + lineHeight / 2) + 1;
+ textDisplayGroup.verticalScrollPosition = 0;
+ isTextDisplayTall = false;
+ //trace("TAS.layoutContents shrinkText vsp",vsp,"lineIndex",lineIndex);
+ }
+
+ else if (growTextDisplay)
+ {
+ // Leaving edit mode. Convert from TextField scrolling to
+ // viewport scrolling
+ var scrollV:Number = textDisplay.scrollV;
+
+ // TODO (jszeto) investigate using lineMetrics.lineHeight * scrollV instead of getCharBoundaries
+ topCharIndex = textDisplay.getLineOffset(scrollV - 1);
+ charBounds = textDisplay.getCharBoundaries(topCharIndex);
+ // If the charBounds is null, just set vsp to 0
+ if (charBounds == null)
+ charBounds = new Rectangle(0, 0, 0, 0);
+ textDisplay.scrollV = 1;
+ isTextDisplayTall = true;
+ //trace("TAS.layoutContents growText scrollV",scrollV,"topCharIndex",topCharIndex,"charBounds",charBounds);
+ }
+ }
+
+ // TextField height should match its content or the TextArea bounds at minimum
+ // iOS special case to prevent Flex Scroller scrolling when editable
+ if (isTextDisplayTall)
+ textHeight = Math.max(textDisplay.measuredTextSize.y, unscaledTextHeight);
+ else
+ textHeight = unscaledTextHeight;
+
+ // FIXME (jasonsj): iOS native scroll bar appears even when explictHeight
+ // is not specified. Focus-in is jumpy.
+
+ if (promptDisplay)
+ {
+ promptDisplay.commitStyles();
+ setElementSize(promptDisplay, unscaledTextWidth, textHeight);
+ setElementPosition(promptDisplay, paddingLeft, paddingTop);
+
+ // no need to update textDisplay if promptDisplay is present
+ return;
+ }
+
+ // keep track of oldUnscaledWidth so we have a good guess as to the width
+ // of the textDisplay on the next measure() pass
+ oldUnscaledWidth = unscaledWidth;
+
+ // set the width of textDisplay to textWidth.
+ // set the height to oldTextHeight. If the height's actually wrong,
+ // we'll invalidateSize() and go through this layout pass again anyways
+ setElementSize(textDisplay, textWidth, textHeight);
+
+ // Set minWidth/Height on the text so the textDisplayGroup sizes accordingly
+ textDisplay.minWidth = textWidth;
+ textDisplay.minHeight = textHeight;
+ textDisplayGroup.invalidateDisplayList();
+
+ // grab new measured textDisplay height after the textDisplay has taken its final width
+ var newPreferredTextHeight:Number = getElementPreferredHeight(textDisplay);
+
+ // if the resize caused the textDisplay's height to change (because of
+ // text reflow), then we need to remeasure ourselves with our new width
+ if (oldPreferredTextHeight != newPreferredTextHeight)
+ invalidateSize();
+
+ if (_isIOS)
+ {
+ if (shrinkTextDisplay)
+ {
+ scroller.validateNow();
+ textDisplay.scrollV = lineIndex;
+ }
+ else if (growTextDisplay)
+ {
+ scroller.validateNow();
+ textDisplayGroup.verticalScrollPosition = charBounds.y;
+ }
+
+ shrinkTextDisplay = false;
+ growTextDisplay = false;
+ }
+
+ //trace("TAS.layoutContents tH",textHeight,"tW",textWidth,"invalidateCaret",invalidateCaretPosition);
+
+ // checking if text fits in TextArea
+ // does not apply to iOS due to native text editing and scrolling
+ // invalidateCaretPosition will never be true for iOS
+ if (invalidateCaretPosition && isTextDisplayTall)
+ {
+ // if the caret is outside the viewport, update the Group verticalScrollPosition
+ var charIndex:int = textDisplay.selectionBeginIndex;
+ var caretBounds:Rectangle = textDisplay.getCharBoundaries(charIndex);
+ lineIndex = textDisplay.getLineIndexOfChar(charIndex);
+
+ // getCharBoundaries() returns null for new lines
+ if (!caretBounds)
+ {
+ // temporarily insert a character at the caretIndex
+ textDisplay.replaceText(charIndex, charIndex, "W");
+ caretBounds = textDisplay.getCharBoundaries(charIndex);
+ lineIndex = textDisplay.getLineIndexOfChar(charIndex);
+ textDisplay.replaceText(charIndex, charIndex + 1, "");
+ }
+
+ if (caretBounds)
+ {
+ // Scroll the internal Scroller to ensure the caret is visible
+ if (textHeight > unscaledTextHeight)
+ {
+
+ if (charIndex == textDisplay.text.length)
+ {
+ // Make sure textDisplayGroup is validated, otherwise the
+ // verticalScrollPosition may be out of bounds, which will
+ // cause a bounce effect.
+ textDisplayGroup.validateNow();
+ textDisplayGroup.verticalScrollPosition = textHeight;
+ }
+ else
+ {
+ // caretTopPositon and caretBottomPosition are TextField-relative positions
+ // the TextField is inset by padding styles of the TextArea (via the VGroup)
+
+ // adjust top position to 0 when on the first line
+ // caretTopPosition will be negative when off stage
+ var caretTopPosition:Number = ((caretBounds.y) < 0 || (lineIndex == 0))
+ ? 0 : caretBounds.y;
+
+ // caretBottomPosition is the y coordinate of the bottom bounds of the caret
+ var caretBottomPosition:Number = caretBounds.y + caretBounds.height;
+
+ // note that verticalScrollPosition min/max do not account for padding
+ var vspTop:Number = textDisplayGroup.verticalScrollPosition;
+
+ // vspBottom should be the max visible Y in the TextField
+ // coordinate space.
+ // remove paddingBottom for some clearance between caret and border
+ var vspBottom:Number = vspTop + unscaledHeight - paddingTop - paddingBottom;
+
+ // is the caret in or below the padding and viewport?
+ if (caretBottomPosition > vspBottom)
+ {
+ // adjust caretBottomPosition to max scroll position when on the last line
+ if (lineIndex + 1 == textDisplay.numLines)
+ {
+ // use textHeight+paddings instead of textDisplayGroup.contentHeight
+ // Group has not been resized by this point
+ textDisplayGroup.verticalScrollPosition = (textHeight + paddingTop + paddingBottom) - textDisplayGroup.height;
+ }
+ else
+ {
+ // bottom edge of the caret moves just inside the bottom edge of the scroller
+ // add delta between caret and vspBottom
+ textDisplayGroup.verticalScrollPosition = vspTop + (caretBottomPosition - vspBottom);
+ }
+ }
+ // is the caret above the viewport?
+ else if (caretTopPosition < vspTop)
+ {
+ // top edge of the caret moves inside the top edge of the scroller
+ textDisplayGroup.verticalScrollPosition = caretTopPosition;
+ }
+ }
+
+ scroller.validateNow();
+ }
+
+ // Convert to local coordinates
+ // Dispatch an event for an ancestor Scroller
+ // It will scroll the TextArea so the caret is in view
+ convertBoundsToLocal(caretBounds);
+ if (oldCaretBounds == null || caretBounds.bottom != oldCaretBounds.bottom || caretBounds.top != oldCaretBounds.top)
+ {
+ //trace("TAS.layoutContents send caret CHANGE");
+ dispatchEvent(new CaretBoundsChangeEvent(CaretBoundsChangeEvent.CARET_BOUNDS_CHANGE,true,true,oldCaretBounds,caretBounds));
+ }
+
+ oldCaretBounds = caretBounds;
+ }
+
+ invalidateCaretPosition = false;
+ }
+
+ // Make sure final scroll position is valid
+ if (isTextDisplayTall)
+ snapTextScrollPosition();
+ }
+
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var contentBackgroundColor:uint = getStyle("contentBackgroundColor");
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ //change border color and thickness when in focus
+ var borderColor:uint = isFocused ? getStyle("focusColor") : getStyle("borderColor");
+ var borderWidth:uint = layoutBorderSize * 2;
+ if (isNaN(contentBackgroundAlpha))
+ {
+ contentBackgroundAlpha = 1;
+ }
+ if (getStyle("contentBackgroundBorder") == "roundedrect")
+ {
+ graphics.lineStyle(layoutBorderSize, borderColor, 1, true);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRoundRectComplex(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth, roundheight, roundheight, roundheight, roundheight);
+ graphics.endFill();
+ }
+ if (getStyle("contentBackgroundBorder") == "rectangle")
+ {
+
+ //rectangle border and background
+ graphics.lineStyle(layoutBorderSize, borderColor, 1);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ else if (getStyle("contentBackgroundBorder") == "none")
+ {
+
+ //rectangle border and background
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ }
+
+ /**
+ * @private
+ * Make sure the scroll positions are valid, and adjust if needed.
+ */
+ private function snapTextScrollPosition():void
+ {
+ var maxHsp:Number = textDisplayGroup.contentWidth > textDisplayGroup.width ?
+ textDisplayGroup.contentWidth-textDisplayGroup.width : 0;
+ textDisplayGroup.horizontalScrollPosition = Math.min(Math.max(0,textDisplayGroup.horizontalScrollPosition),maxHsp);
+
+ var maxVsp:Number = textDisplayGroup.contentHeight > textDisplayGroup.height ?
+ textDisplayGroup.contentHeight-textDisplayGroup.height : 0;
+
+ textDisplayGroup.verticalScrollPosition =
+ Math.min(Math.max(0,textDisplayGroup.verticalScrollPosition),maxVsp);
+ }
+
+ /**
+ * @private
+ * Get the bounds of the caret
+ */
+ private function getCaretBounds():Rectangle
+ {
+ var charIndex:int = textDisplay.selectionBeginIndex;
+ var caretBounds:Rectangle = textDisplay.getCharBoundaries(charIndex);
+
+ if (!caretBounds)
+ {
+ textDisplay.replaceText(charIndex, charIndex, "W");
+ caretBounds = textDisplay.getCharBoundaries(charIndex);
+ textDisplay.replaceText(charIndex, charIndex + 1, "");
+ }
+
+ return caretBounds;
+ }
+
+ /**
+ * @private
+ * Convert bounds from textDisplay to local coordinates
+ */
+ private function convertBoundsToLocal(bounds:Rectangle):void
+ {
+ if (bounds)
+ {
+ var position:Point = new Point(bounds.x, bounds.y);
+ position = textDisplay.localToGlobal(position);
+ position = globalToLocal(position);
+ bounds.x = position.x;
+ bounds.y = position.y;
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function scrollToRange(anchorPosition:int, activePosition:int):void
+ {
+ var pos:int = Math.min(anchorPosition, activePosition);
+ var bounds:Rectangle = textDisplay.getCharBoundaries(pos);
+ var vsp:int = textDisplayGroup.verticalScrollPosition;
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ if (bounds && (bounds.top < vsp - paddingTop ||
+ bounds.bottom > vsp + unscaledHeight - paddingTop - paddingBottom))
+ {
+ textDisplayGroup.verticalScrollPosition = bounds.top + paddingTop;
+ snapTextScrollPosition();
+ }
+ }
+
+ /**
+ * @private
+ * Handle size and caret position changes that occur when text content
+ * changes.
+ */
+ private function textDisplay_changeHandler(event:Event):void
+ {
+ var tH:Number = textDisplay.textHeight;
+ var tW:Number = textDisplay.textWidth;
+ var explicitLineBreak:Boolean = getStyle("lineBreak") == "explicit";
+
+ // Size and caret position have changed if the text height is different or
+ // the text width is different and we aren't word wrapping
+ if (tH != lastTextHeight || ( explicitLineBreak && tW != lastTextWidth))
+ {
+ invalidateSize();
+ invalidateDisplayList();
+ invalidateCaretPosition = true;
+ }
+
+ lastTextHeight = tH;
+ lastTextWidth = tW;
+ }
+
+ /**
+ * @private
+ * Cancels any native scroll that the Flash Player attempts to do
+ */
+ private function textDisplay_scrollHandler(event:Event):void
+ {
+ // if iOS, let the OS handle scrolling
+ if (_isIOS)
+ return;
+
+ // If not IOS, we will handle scrolling, so don't let the native
+ // flash textfield scroll at all.
+ if (textDisplay.scrollV > 1)
+ textDisplay.scrollV = 1;
+ if (textDisplay.scrollH > 0)
+ textDisplay.scrollH = 0;
+ }
+
+ /**
+ * @private
+ * Adjust viewport when using key navigation
+ */
+ private function textDisplay_keyHandler(event:KeyboardEvent):void
+ {
+ // update scroll position when caret changes
+ if ((event.keyCode == Keyboard.UP
+ || event.keyCode == Keyboard.DOWN
+ || event.keyCode == Keyboard.LEFT
+ || event.keyCode == Keyboard.RIGHT))
+ {
+ invalidateDisplayList();
+ invalidateCaretPosition = true;
+ }
+
+ // Change event is not always sent when delete key is pressed, so
+ // invalidate the size here
+ if (event.keyCode == Keyboard.BACKSPACE)
+ {
+ invalidateSize();
+ }
+ }
+
+ /**
+ * @private
+ * When entering edit mode on iOS, we need to shrink the textDisplay to
+ * the size of the TextArea
+ */
+ private function textDisplay_softKeyboardActivatingHandler(event:SoftKeyboardEvent):void
+ {
+ if (event.isDefaultPrevented())
+ return;
+
+ if (_isIOS && isTextDisplayTall)
+ {
+ //trace("TAS.SK ACTIVATING targ",event.target);
+ shrinkTextDisplay = true;
+ invalidateDisplayList();
+ validateNow();
+ }
+ }
+
+ /**
+ * @private
+ * Send a caret change event to an ancestor Scroller
+ */
+ private function textDisplay_softKeyboardActivateHandler(event:SoftKeyboardEvent):void
+ {
+ var keyboardRect:Rectangle = stage.softKeyboardRect;
+
+ if (keyboardRect.width > 0 && keyboardRect.height > 0)
+ {
+ var newCaretBounds:Rectangle = getCaretBounds();
+ convertBoundsToLocal(newCaretBounds);
+
+ if (oldCaretBounds != newCaretBounds)
+ {
+ //trace("TAS.SK ACTIVATE",keyboardRect,"dispatch caret CHANGE","newCaretBounds",newCaretBounds);
+ dispatchEvent(new CaretBoundsChangeEvent(CaretBoundsChangeEvent.CARET_BOUNDS_CHANGE,true,true,oldCaretBounds,newCaretBounds));
+ oldCaretBounds = newCaretBounds;
+ }
+ }
+ }
+
+ /**
+ * @private
+ * On iOS, when leaving edit mode, we need to restore the textDisplay to the
+ * height of the text.
+ */
+ private function textDisplay_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
+ {
+ if (_isIOS && !isTextDisplayTall)
+ {
+ growTextDisplay = true;
+ invalidateDisplayList();
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function resizeHandler(event:Event):void
+ {
+ // Resizing needs to tickle the TextArea's internal auto-scroll logic
+ invalidateCaretPosition = true;
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ super.styleChanged(styleProp);
+
+ // propogate styleChanged explicitly to textDisplay
+ if (textDisplay)
+ textDisplay.styleChanged(styleProp);
+
+ // Check for padding style changes
+ if (!styleProp || styleProp == "styleName" || styleProp.indexOf("padding") >= 0)
+ {
+ if (textDisplay)
+ {
+ textDisplay.left = getStyle("paddingLeft");
+ textDisplay.top = getStyle("paddingTop");
+ textDisplay.right = getStyle("paddingRight");
+ textDisplay.bottom = getStyle("paddingBottom");
+ }
+ }
+ }
+
+ private function focusChangeHandler(event:FocusEvent):void
+ {
+ isFocused = event.type == FocusEvent.FOCUS_IN;
+ invalidateDisplayList();
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/TextInputSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TextInputSkin.as
new file mode 100644
index 0000000000..f2b243e03d
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TextInputSkin.as
@@ -0,0 +1,374 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.events.Event;
+ import flash.events.FocusEvent;
+ import flash.events.SoftKeyboardEvent;
+ import flash.system.Capabilities;
+
+ import mx.core.DPIClassification;
+ import mx.core.EventPriority;
+ import mx.core.mx_internal;
+ import mx.events.FlexEvent;
+ import mx.utils.Platform;
+
+ import spark.components.TextInput;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.ios7.supportClasses.TextSkinBase;
+
+ use namespace mx_internal;
+
+ /**
+ * ActionScript-based skin for TextInput controls in mobile applications.
+ *
+ * @see spark.components.TextInput
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class TextInputSkin extends TextSkinBase
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function TextInputSkin()
+ {
+ super();
+
+ // on iOS, make adjustments for native text rendering
+ _isIOS = Platform.isIOS;
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultWidth = 1200;
+ measuredDefaultHeight = 132;
+ layoutBorderSize = 3;
+ roundheight = 24;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+
+ measuredDefaultWidth = 880;
+ measuredDefaultHeight = 100;
+ layoutBorderSize = 2;
+ roundheight = 18;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultWidth = 600;
+ measuredDefaultHeight = 66;
+ layoutBorderSize = 1.5;
+ roundheight = 14;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultWidth = 440;
+ measuredDefaultHeight = 50;
+ layoutBorderSize = 1;
+ roundheight = 10;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultWidth = 220;
+ measuredDefaultHeight = 25;
+ layoutBorderSize = .5;
+ roundheight = 5;
+ break;
+ }
+ default:
+ {
+ measuredDefaultWidth = 300;
+ measuredDefaultHeight = 33;
+ layoutBorderSize = .5;
+ roundheight = 7;
+ break;
+ }
+ }
+ addEventListener(FocusEvent.FOCUS_IN, focusChangeHandler);
+ addEventListener(FocusEvent.FOCUS_OUT, focusChangeHandler);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var isFocused:Boolean = false;
+
+ protected var roundheight:uint;
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:TextInput; // SkinnableComponent will populate
+
+ /**
+ * @private
+ */
+ private var _isIOS:Boolean;
+
+ /**
+ * @private
+ */
+ private var _isEditing:Boolean;
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ textDisplay.addEventListener("editableChanged", editableChangedHandler);
+ textDisplay.addEventListener(FlexEvent.VALUE_COMMIT, valueCommitHandler);
+
+ // remove hit area improvements on iOS when editing
+ if (_isIOS)
+ {
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_ACTIVATING, textDisplay_softKeyboardActivatingHandler, false, EventPriority.DEFAULT_HANDLER);
+ textDisplay.addEventListener(SoftKeyboardEvent.SOFT_KEYBOARD_DEACTIVATE, textDisplay_softKeyboardDeactivateHandler);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function measure():void
+ {
+ super.measure();
+
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+ var textHeight:Number = getStyle("fontSize") as Number;
+
+ if (textDisplay)
+ {
+ // temporarily change text for measurement
+ var oldText:String = textDisplay.text;
+
+ // commit styles so we can get a valid textHeight
+ textDisplay.text = "Wj";
+ textDisplay.commitStyles();
+
+ textHeight = textDisplay.measuredTextSize.y;
+ textDisplay.text = oldText;
+ }
+
+ // width is based on maxChars (if set)
+ if (hostComponent && hostComponent.maxChars)
+ {
+ // Grab the fontSize and subtract 2 as the pixel value for each character.
+ // This is just an approximation, but it appears to be a reasonable one
+ // for most input and most font.
+ var characterWidth:int = Math.max(1, (getStyle("fontSize") - 2));
+ measuredWidth = (characterWidth * hostComponent.maxChars) +
+ paddingLeft + paddingRight + StyleableTextField.TEXT_WIDTH_PADDING;
+ }
+
+ measuredHeight = paddingTop + textHeight + paddingBottom;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ // position & size border
+ if (border)
+ {
+ setElementSize(border, unscaledWidth, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+
+ // position & size the text
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+
+ var unscaledTextWidth:Number = unscaledWidth - paddingLeft - paddingRight;
+ var unscaledTextHeight:Number = unscaledHeight - paddingTop - paddingBottom;
+
+ // default vertical positioning is centered
+ var textHeight:Number = getElementPreferredHeight(textDisplay);
+ var textY:Number = Math.round(0.5 * (unscaledTextHeight - textHeight)) + paddingTop;
+
+ // On iOS the TextField top and bottom edges are bounded by the padding.
+ // On all other platforms, the height of the textDisplay is
+ // textHeight + paddingBottom to increase hitArea on bottom.
+ // Note: We don't move the Y position upwards because TextField
+ // has way to set vertical positioning.
+ // Note: iOS is a special case due to the clear button provided by the
+ // native text control used while editing.
+ var adjustedTextHeight:Number = (_isIOS && _isEditing) ? textHeight : textHeight + paddingBottom;
+
+ if (textDisplay)
+ {
+ // We're going to do a few tricks to try to increase the size of our hitArea to make it
+ // easier for users to select text or put the caret in a certain spot. To do that,
+ // rather than set textDisplay.x=paddingLeft, we are going to set
+ // textDisplay.leftMargin = paddingLeft. In addition, we're going to size the height
+ // of the textDisplay larger than just the size of the text inside to increase the hitArea
+ // on the bottom. We'll also assign textDisplay.rightMargin = paddingRight to increase the
+ // the hitArea on the right. Unfortunately, there's no way to increase the hitArea on the top
+ // just yet, but these three tricks definitely help out with regards to user experience.
+ // See http://bugs.adobe.com/jira/browse/SDK-29406 and http://bugs.adobe.com/jira/browse/SDK-29405
+
+ // set leftMargin, rightMargin to increase the hitArea. Need to set it before calling commitStyles().
+ var marginChanged:Boolean = ((textDisplay.leftMargin != paddingLeft) ||
+ (textDisplay.rightMargin != paddingRight));
+
+ textDisplay.leftMargin = paddingLeft;
+ textDisplay.rightMargin = paddingRight;
+
+ // need to force a styleChanged() after setting leftMargin, rightMargin if they
+ // changed values. Then we can validate the styles through commitStyles()
+ if (marginChanged)
+ textDisplay.styleChanged(null);
+ textDisplay.commitStyles();
+
+ setElementSize(textDisplay, unscaledWidth, adjustedTextHeight);
+
+ // set x=0 since we're using textDisplay.leftMargin = paddingLeft
+ setElementPosition(textDisplay, 0, textY);
+ }
+
+ if (promptDisplay)
+ {
+ promptDisplay.commitStyles();
+ setElementSize(promptDisplay, unscaledTextWidth, adjustedTextHeight);
+ setElementPosition(promptDisplay, paddingLeft, textY);
+ }
+ }
+
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var contentBackgroundColor:uint = getStyle("contentBackgroundColor");
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ //change border color and thickness when in focus
+ var borderColor:uint = isFocused ? getStyle("focusColor") : getStyle("borderColor");
+ var borderWidth:uint = layoutBorderSize * 2;
+ if (isNaN(contentBackgroundAlpha))
+ {
+ contentBackgroundAlpha = 1;
+ }
+ if (getStyle("contentBackgroundBorder") == "roundedrect")
+ {
+ graphics.lineStyle(layoutBorderSize, borderColor, 1, true);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRoundRectComplex(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth, roundheight, roundheight, roundheight, roundheight);
+ graphics.endFill();
+ }
+ if (getStyle("contentBackgroundBorder") == "rectangle")
+ {
+
+ //rectangle border and background
+ graphics.lineStyle(layoutBorderSize, borderColor, 1);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ else if (getStyle("contentBackgroundBorder") == "none")
+ {
+
+ //rectangle border and background
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ }
+
+ /**
+ * @private
+ */
+ private function editableChangedHandler(event:Event):void
+ {
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ * The text changed in some way.
+ *
+ * Dynamic fields (ie !editable) with no text measure with width=0 and height=0.
+ * If the text changed, need to remeasure the text to get the correct height so it
+ * will be laid out correctly.
+ */
+ private function valueCommitHandler(event:Event):void
+ {
+ if (textDisplay && !textDisplay.editable)
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ private function textDisplay_softKeyboardActivatingHandler(event:SoftKeyboardEvent):void
+ {
+ if (event.isDefaultPrevented())
+ return;
+
+ _isEditing = true;
+ invalidateDisplayList();
+ }
+
+ /**
+ * @private
+ */
+ private function textDisplay_softKeyboardDeactivateHandler(event:SoftKeyboardEvent):void
+ {
+ _isEditing = false;
+ invalidateDisplayList();
+ }
+
+ private function focusChangeHandler(event:FocusEvent):void
+ {
+ isFocused = event.type == FocusEvent.FOCUS_IN;
+ invalidateDisplayList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ToggleSwitchSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ToggleSwitchSkin.as
new file mode 100644
index 0000000000..4d543a747f
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ToggleSwitchSkin.as
@@ -0,0 +1,451 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.BlendMode;
+ import flash.events.Event;
+
+ import mx.core.DPIClassification;
+ import mx.core.IVisualElement;
+ import mx.core.UIComponent;
+
+ import spark.components.ToggleSwitch;
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.core.SpriteVisualElement;
+ import spark.skins.ios7.assets.ToggleSwitchBackground_off;
+ import spark.skins.ios7.assets.ToggleSwitchBackground_on;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+
+ /**
+ * ActionScript-based iOS7+ specific skin for the ToggleSwitch control.
+ * This class is responsible for most of the
+ * graphics drawing, with additional fxg assets.
+ *
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ *
+ * @see spark.components.ToggleSwitch
+ */
+ public class ToggleSwitchSkin extends MobileSkin
+ {
+ //----------------------------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //----------------------------------------------------------------------------------------------
+
+ /**
+ * The thumb skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var thumb:IVisualElement;
+ /**
+ * The track skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ public var track:IVisualElement;
+
+ //----------------------------------
+ // hostComponent
+ //----------------------------------
+
+ private var _hostComponent:ToggleSwitch;
+ //The label is called selectedLabelDisplay because the hostComponent expects it
+ public var selectedLabelDisplay:LabelDisplayComponent;
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public function get hostComponent():ToggleSwitch
+ {
+ return _hostComponent;
+ }
+
+ public function set hostComponent(value:ToggleSwitch):void
+ {
+ if (_hostComponent)
+ _hostComponent.removeEventListener("thumbPositionChanged", thumbPositionChanged_handler);
+ _hostComponent = value;
+ if (_hostComponent)
+ _hostComponent.addEventListener("thumbPositionChanged", thumbPositionChanged_handler);
+ }
+
+ /**
+ * The contents inside the skin, not including the outline
+ * stroke
+ */
+ private var contents:UIComponent;
+ private var switchTrackOn:Class;
+ private var switchTrackOff:Class;
+ private var switchOff:Class;
+ private var switchOn:Class;
+ protected var trackWidth:Number;
+ protected var trackHeight:Number;
+ protected var layoutThumbWidth:Number;
+ protected var layoutThumbHeight:Number;
+ private var thumbOn:IVisualElement;
+ private var thumbOff:IVisualElement;
+ private var trackOn:IVisualElement;
+ private var trackOff:IVisualElement;
+
+ public function ToggleSwitchSkin()
+ {
+ super();
+
+ switchTrackOn = spark.skins.ios7.assets.ToggleSwitchBackground_on;
+ switchTrackOff = spark.skins.ios7.assets.ToggleSwitchBackground_off;
+ switchOn = spark.skins.ios7.assets.ToggleSwitchThumb_on;
+ switchOff = spark.skins.ios7.assets.ToggleSwitchThumb_off;
+
+ switch(applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ layoutThumbWidth = 108;
+ layoutThumbHeight = 108;
+ trackWidth = 224;
+ trackHeight = 124;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ layoutThumbWidth = 80;
+ layoutThumbHeight = 80;
+ trackWidth = 168;
+ trackHeight = 92;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ layoutThumbWidth = 54;
+ layoutThumbHeight = 54;
+ trackWidth = 112;
+ trackHeight = 62;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ layoutThumbWidth = 40;
+ layoutThumbHeight = 40;
+ trackWidth = 84;
+ trackHeight = 46;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ layoutThumbWidth = 20;
+ layoutThumbHeight = 20;
+ trackWidth = 42;
+ trackHeight = 23;
+ break;
+ }
+ default:
+ {
+ layoutThumbWidth = 27;
+ layoutThumbHeight = 27;
+ trackWidth = 56;
+ trackHeight = 31;
+ break;
+ }
+ }
+
+ }
+
+ override protected function createChildren():void
+ {
+ super.createChildren();
+ contents = new UIComponent();
+ addChild(contents);
+ drawTracks();
+ drawThumbs();
+ }
+
+ override protected function measure():void
+ {
+ // The skin must be at least as large as the thumb
+ measuredMinWidth = trackWidth;
+ measuredMinHeight = trackHeight;
+
+ measuredWidth = trackWidth;
+ measuredHeight = trackHeight;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ toggleSelectionState();
+ layoutThumbs();
+ }
+
+ //Draw both thumbs. Set skinpart track to be switchTrackOff because default
+ //state of the switch is OFF
+ protected function drawTracks():void
+ {
+ drawTrackOff();
+ drawTrackOn();
+ if(track == null)
+ {
+ track = trackOff;
+ }
+ }
+
+ //Draw the track behind everything else
+ protected function drawTrackOn():void
+ {
+ trackOn = new switchTrackOn();
+ trackOn.width = trackWidth;
+ trackOn.height = trackHeight;
+ contents.addChildAt(SpriteVisualElement(trackOn),0);
+ }
+
+ protected function drawTrackOff():void
+ {
+ trackOff = new switchTrackOff();
+ trackOff.width = trackWidth;
+ trackOff.height = trackHeight;
+ contents.addChildAt(SpriteVisualElement(trackOff),0);
+ }
+
+ //Draw both thumbs. Set skinpart thumb to be thumbOff because default state of the switch is OFF
+ protected function drawThumbs():void
+ {
+ drawThumbOff();
+ drawThumbOn();
+ if(thumb == null)
+ {
+ thumb = thumbOff;
+ }
+ }
+
+ //Thumb ON the right side; Thumb OFF is on the left side
+ protected function layoutThumbs():void
+ {
+ setElementPosition(thumbOn,trackWidth/2,trackHeight/2 - thumbOn.height/2);
+ setElementPosition(thumbOff,0,trackHeight/2 - thumbOff.height/2);
+ }
+
+ //Depending on current state, set skinpart thumb accordingly
+ protected function toggleSelectionState():void
+ {
+ if(currentState.indexOf("AndSelected") != -1)
+ {
+ thumbOn.visible = true;
+ thumbOff.visible = false;
+ thumb = thumbOn;
+ trackOn.visible = true;
+ trackOff.visible = false;
+ track = trackOn;
+ }
+ else
+ {
+ thumbOff.visible = true;
+ thumbOn.visible = false;
+ thumb = thumbOff;
+ trackOff.visible = true;
+ trackOn.visible = false;
+ track = trackOff;
+ }
+ }
+
+ protected function drawThumbOn():void
+ {
+ thumbOn = new switchOn();
+ thumbOn.width = layoutThumbWidth;
+ thumbOn.height = layoutThumbHeight;
+ contents.addChildAt(SpriteVisualElement(thumbOn),2);
+ }
+
+ protected function drawThumbOff():void
+ {
+ thumbOff = new switchOff();
+ thumbOff.width = layoutThumbWidth;
+ thumbOff.height = layoutThumbHeight;
+ contents.addChildAt(SpriteVisualElement(thumbOff),2);
+ }
+
+ //Hostcomponent dispatches this event whenever the thumb position changes
+ protected function thumbPositionChanged_handler(event:Event):void
+ {
+ moveSlidingContent();
+ }
+
+ //Move the current thumb and label along with the animating content
+ protected function moveSlidingContent():void
+ {
+ if (!hostComponent)
+ return;
+ var x:Number = (track.getLayoutBoundsWidth() - thumb.getLayoutBoundsWidth()) *
+ hostComponent.thumbPosition + track.getLayoutBoundsX();
+ var y:Number = thumb.getLayoutBoundsY();
+ setElementPosition(thumb, x, y);
+ }
+ }
+}
+
+
+import flash.events.Event;
+
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.events.FlexEvent;
+
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.IDisplayText;
+
+use namespace mx_internal;
+
+/**
+ * @private
+ * Component combining two labels to create the effect of text and its drop
+ * shadow. The component can be used with advanced style selectors and the
+ * styles "color", "textShadowColor", and "textShadowAlpha". Based off of
+ * ActionBar.TitleDisplayComponent. These two should eventually be factored.
+ */
+class LabelDisplayComponent extends UIComponent implements IDisplayText
+{
+ public var shadowYOffset:Number = 0;
+ private var labelChanged:Boolean = false;
+ private var labelDisplay:StyleableTextField;
+ private var labelDisplayShadow:StyleableTextField;
+ private var _text:String;
+
+ public function LabelDisplayComponent()
+ {
+ super();
+ _text = "";
+ }
+
+ override public function get baselinePosition():Number
+ {
+ return labelDisplay.baselinePosition;
+ }
+
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ labelDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ labelDisplay.styleName = this;
+ labelDisplay.editable = false;
+ labelDisplay.selectable = false;
+ labelDisplay.multiline = false;
+ labelDisplay.wordWrap = false;
+ labelDisplay.addEventListener(FlexEvent.VALUE_COMMIT,
+ labelDisplay_valueCommitHandler);
+
+ labelDisplayShadow = StyleableTextField(createInFontContext(StyleableTextField));
+ labelDisplayShadow.styleName = this;
+ labelDisplayShadow.colorName = "textShadowColor";
+ labelDisplayShadow.editable = false;
+ labelDisplayShadow.selectable = false;
+ labelDisplayShadow.multiline = false;
+ labelDisplayShadow.wordWrap = false;
+
+ addChild(labelDisplayShadow);
+ addChild(labelDisplay);
+ }
+
+ override protected function commitProperties():void
+ {
+ super.commitProperties();
+
+ if (labelChanged)
+ {
+ labelDisplay.text = text;
+ invalidateSize();
+ invalidateDisplayList();
+ labelChanged = false;
+ }
+ }
+
+ override protected function measure():void
+ {
+ if (labelDisplay.isTruncated)
+ labelDisplay.text = text;
+ labelDisplay.commitStyles();
+ measuredWidth = labelDisplay.getPreferredBoundsWidth();
+ measuredHeight = labelDisplay.getPreferredBoundsHeight();
+ }
+
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ if (labelDisplay.isTruncated)
+ labelDisplay.text = text;
+ labelDisplay.commitStyles();
+
+ var labelHeight:Number = labelDisplay.getPreferredBoundsHeight();
+ var labelY:Number = (unscaledHeight - labelHeight) / 2;
+
+ var labelWidth:Number = Math.min(unscaledWidth, labelDisplay.getPreferredBoundsWidth());
+ var labelX:Number = (unscaledWidth - labelWidth) / 2;
+
+ labelDisplay.setLayoutBoundsSize(labelWidth, labelHeight);
+ labelDisplay.setLayoutBoundsPosition(labelX, labelY);
+
+ labelDisplay.truncateToFit();
+
+ labelDisplayShadow.commitStyles();
+ labelDisplayShadow.setLayoutBoundsSize(labelWidth, labelHeight);
+ labelDisplayShadow.setLayoutBoundsPosition(labelX, labelY + shadowYOffset);
+
+ labelDisplayShadow.alpha = getStyle("textShadowAlpha");
+
+ // unless the label was truncated, labelDisplayShadow.text was set in
+ // the value commit handler
+ if (labelDisplay.isTruncated)
+ labelDisplayShadow.text = labelDisplay.text;
+ }
+
+ private function labelDisplay_valueCommitHandler(event:Event):void
+ {
+ labelDisplayShadow.text = labelDisplay.text;
+ }
+
+ public function get text():String
+ {
+ return _text;
+ }
+
+ public function set text(value:String):void
+ {
+ _text = value;
+ labelChanged = true;
+ invalidateProperties();
+ }
+
+ public function get isTruncated():Boolean
+ {
+ return labelDisplay.isTruncated;
+ }
+
+ public function showShadow(value:Boolean):void
+ {
+ labelDisplayShadow.visible = value;
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/TransparentActionButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TransparentActionButtonSkin.as
new file mode 100644
index 0000000000..b88042a383
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TransparentActionButtonSkin.as
@@ -0,0 +1,108 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.display.Graphics;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.skins.mobile.assets.TransparentActionButton_down;
+import spark.skins.mobile.assets.TransparentActionButton_up;
+import spark.skins.mobile.supportClasses.ActionBarButtonSkinBase;
+import spark.skins.mobile.supportClasses.MobileSkin;
+import spark.skins.mobile320.assets.TransparentActionButton_down;
+import spark.skins.mobile320.assets.TransparentActionButton_up;
+import spark.skins.mobile480.assets.TransparentActionButton_down;
+import spark.skins.mobile480.assets.TransparentActionButton_up;
+import spark.skins.mobile640.assets.TransparentActionButton_down;
+import spark.skins.mobile640.assets.TransparentActionButton_up;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for buttons in the action area of the Spark ActionBar component
+ * in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TransparentActionButtonSkin extends ActionBarButtonSkinBase
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function TransparentActionButtonSkin()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ upBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ upBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ upBorderSkin = spark.skins.mobile320.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile320.assets.TransparentActionButton_down;
+
+ break;
+ }
+ default:
+ {
+ upBorderSkin = spark.skins.mobile.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile.assets.TransparentActionButton_down;
+
+ break;
+ }
+ }
+ }
+
+ override mx_internal function layoutBorder(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // don't call super, don't layout twice
+ // leading vertical separator is outside the left bounds of the button
+ setElementSize(border, unscaledWidth + layoutBorderSize, unscaledHeight);
+ setElementPosition(border, -layoutBorderSize, 0);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/TransparentNavigationButtonSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TransparentNavigationButtonSkin.as
new file mode 100644
index 0000000000..6eccad4a3f
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/TransparentNavigationButtonSkin.as
@@ -0,0 +1,109 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.display.Graphics;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.skins.mobile.assets.TransparentNavigationButton_down;
+import spark.skins.mobile.assets.TransparentNavigationButton_up;
+import spark.skins.mobile.supportClasses.ActionBarButtonSkinBase;
+import spark.skins.mobile.supportClasses.MobileSkin;
+import spark.skins.mobile320.assets.TransparentNavigationButton_down;
+import spark.skins.mobile320.assets.TransparentNavigationButton_up;
+import spark.skins.mobile480.assets.TransparentNavigationButton_down;
+import spark.skins.mobile480.assets.TransparentNavigationButton_up;
+import spark.skins.mobile640.assets.TransparentNavigationButton_down;
+import spark.skins.mobile640.assets.TransparentNavigationButton_up;
+
+use namespace mx_internal;
+
+/**
+ * The default skin class for buttons in the navigation area of the Spark ActionBar component
+ * in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class TransparentNavigationButtonSkin extends ActionBarButtonSkinBase
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function TransparentNavigationButtonSkin()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ upBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile640.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ upBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_up;
+ downBorderSkin = spark.skins.mobile480.assets.TransparentActionButton_down;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ upBorderSkin = spark.skins.mobile320.assets.TransparentNavigationButton_up;
+ downBorderSkin = spark.skins.mobile320.assets.TransparentNavigationButton_down;
+
+ break;
+ }
+ default:
+ {
+ upBorderSkin = spark.skins.mobile.assets.TransparentNavigationButton_up;
+ downBorderSkin = spark.skins.mobile.assets.TransparentNavigationButton_down;
+
+ break;
+ }
+ }
+ }
+
+ override mx_internal function layoutBorder(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // trailing vertical separator is outside the right bounds of the button
+ setElementSize(border, unscaledWidth + layoutBorderSize, unscaledHeight);
+ setElementPosition(border, 0, 0);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/VScrollBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/VScrollBarSkin.as
new file mode 100644
index 0000000000..8b86965cf4
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/VScrollBarSkin.as
@@ -0,0 +1,207 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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 mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.Button;
+import spark.components.VScrollBar;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for VScrollBar components in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class VScrollBarSkin extends MobileSkin
+{
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function VScrollBarSkin()
+ {
+ super();
+
+ minHeight = 20;
+ thumbSkinClass = VScrollBarThumbSkin;
+ var paddingRight:int;
+ var paddingVertical:int;
+
+ // Depending on density set our measured width
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ minWidth = 24;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_640DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ minWidth = 16;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_480DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ minWidth = 12;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_320DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ minWidth = 8;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_240DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ minWidth = 4;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_120DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_120DPI;
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ minWidth = 6;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_DEFAULTDPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_DEFAULTDPI;
+ break;
+ }
+ }
+
+ // The minimum height is set such that, at it's smallest size, the thumb appears
+ // as high as it is wide.
+ minThumbHeight = (minWidth - paddingRight) + (paddingVertical * 2);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:VScrollBar;
+
+ /**
+ * Minimum height for the thumb
+ */
+ protected var minThumbHeight:Number;
+
+ /**
+ * Skin to use for the thumb Button skin part
+ */
+ protected var thumbSkinClass:Class;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * VScrollbar track skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var track:Button;
+
+ /**
+ * VScrollbar thumb skin part
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public var thumb:Button;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ // Create our skin parts if necessary: track and thumb.
+ if (!track)
+ {
+ // We don't want a visible track so we set the skin to MobileSkin
+ track = new Button();
+ track.setStyle("skinClass", spark.skins.mobile.supportClasses.MobileSkin);
+ track.width = minWidth;
+ track.height = minHeight;
+ addChild(track);
+ }
+ if (!thumb)
+ {
+ thumb = new Button();
+ thumb.minHeight = minThumbHeight;
+ thumb.setStyle("skinClass", thumbSkinClass);
+ thumb.width = minWidth;
+ thumb.height = minWidth;
+ addChild(thumb);
+ }
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.layoutContents(unscaledWidth, unscaledHeight);
+
+ setElementSize(track, unscaledWidth, unscaledHeight);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/VScrollBarThumbSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/VScrollBarThumbSkin.as
new file mode 100644
index 0000000000..96b74e309c
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/VScrollBarThumbSkin.as
@@ -0,0 +1,186 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.CapsStyle;
+import flash.display.JointStyle;
+import flash.display.LineScaleMode;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+use namespace mx_internal;
+
+import spark.components.Button;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+/**
+ * ActionScript-based skin for the VScrollBar thumb skin part in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class VScrollBarThumbSkin extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Class constants
+ //
+ //--------------------------------------------------------------------------
+
+ // These constants are also accessed from VScrollBarSkin
+ mx_internal static const PADDING_RIGHT_640DPI:int = 10;
+ mx_internal static const PADDING_VERTICAL_640DPI:int = 8;
+ mx_internal static const PADDING_RIGHT_480DPI:int = 8;
+ mx_internal static const PADDING_VERTICAL_480DPI:int = 6;
+ mx_internal static const PADDING_RIGHT_320DPI:int = 5;
+ mx_internal static const PADDING_VERTICAL_320DPI:int = 4;
+ mx_internal static const PADDING_RIGHT_240DPI:int = 4;
+ mx_internal static const PADDING_VERTICAL_240DPI:int = 3;
+ mx_internal static const PADDING_RIGHT_120DPI:int = 2;
+ mx_internal static const PADDING_VERTICAL_120DPI:int = 1;
+ mx_internal static const PADDING_RIGHT_DEFAULTDPI:int = 3;
+ mx_internal static const PADDING_VERTICAL_DEFAULTDPI:int = 2;
+
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function VScrollBarThumbSkin()
+ {
+ super();
+
+ // Depending on density set padding
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ minWidth = 19;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_640DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_640DPI;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ minWidth = 19;
+ paddingRight = VScrollBarThumbSkin.PADDING_RIGHT_480DPI;
+ paddingVertical = VScrollBarThumbSkin.PADDING_VERTICAL_480DPI;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ paddingRight = PADDING_RIGHT_320DPI;
+ paddingVertical = PADDING_VERTICAL_320DPI;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ paddingRight = PADDING_RIGHT_240DPI;
+ paddingVertical = PADDING_VERTICAL_240DPI;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ paddingRight = PADDING_RIGHT_120DPI;
+ paddingVertical = PADDING_VERTICAL_120DPI;
+ break;
+ }
+ default:
+ {
+ paddingRight = PADDING_RIGHT_DEFAULTDPI;
+ paddingVertical = PADDING_VERTICAL_DEFAULTDPI;
+ break;
+ }
+ }
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Properties
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * @copy spark.skins.spark.ApplicationSkin#hostComponent
+ */
+ public var hostComponent:Button;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Padding from the right
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingRight:int;
+
+ /**
+ * Vertical padding from top and bottom
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ protected var paddingVertical:int;
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @protected
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var thumbWidth:Number = unscaledWidth - paddingRight;
+
+ var thumbColor:uint = getStyle("color");
+
+ graphics.beginFill(thumbColor, 1);
+ graphics.drawRect(0.5, paddingVertical + 0.5,thumbWidth, unscaledHeight - 2 * paddingVertical);
+
+ graphics.endFill();
+ }
+
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ViewMenuItemSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ViewMenuItemSkin.as
new file mode 100644
index 0000000000..77e58650cf
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ViewMenuItemSkin.as
@@ -0,0 +1,238 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.GradientType;
+import flash.display.Graphics;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.IconPlacement;
+import spark.skins.mobile.assets.ViewMenuItem_down;
+import spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile.assets.ViewMenuItem_up;
+import spark.skins.mobile.supportClasses.ButtonSkinBase;
+import spark.skins.mobile120.assets.ViewMenuItem_down;
+import spark.skins.mobile120.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile120.assets.ViewMenuItem_up;
+import spark.skins.mobile320.assets.ViewMenuItem_down;
+import spark.skins.mobile320.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile320.assets.ViewMenuItem_up;
+import spark.skins.mobile480.assets.ViewMenuItem_down;
+import spark.skins.mobile480.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile480.assets.ViewMenuItem_up;
+import spark.skins.mobile640.assets.ViewMenuItem_down;
+import spark.skins.mobile640.assets.ViewMenuItem_showsCaret;
+import spark.skins.mobile640.assets.ViewMenuItem_up;
+
+
+use namespace mx_internal;
+
+/**
+ * Default skin for ViewMenuItem. Supports a label, icon and iconPlacement and draws a background.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+public class ViewMenuItemSkin extends ButtonSkin
+{
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public function ViewMenuItemSkin()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+
+ upBorderSkin = spark.skins.mobile640.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile640.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile640.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 24;
+ layoutPaddingLeft = 24;
+ layoutPaddingRight = 24;
+ layoutPaddingTop = 24;
+ layoutPaddingBottom = 24;
+ layoutBorderSize = 3;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ // Note provisional may need changes
+ upBorderSkin = spark.skins.mobile.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 16;
+ layoutPaddingLeft = 16;
+ layoutPaddingRight = 16;
+ layoutPaddingTop = 16;
+ layoutPaddingBottom = 16;
+ layoutBorderSize = 2;
+
+ break;
+
+ }
+ case DPIClassification.DPI_320:
+ {
+
+ upBorderSkin = spark.skins.mobile320.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile320.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile320.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 12;
+ layoutPaddingLeft = 12;
+ layoutPaddingRight = 12;
+ layoutPaddingTop = 12;
+ layoutPaddingBottom = 12;
+ layoutBorderSize = 2;
+
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ upBorderSkin = spark.skins.mobile.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 8;
+ layoutPaddingLeft = 8;
+ layoutPaddingRight = 8;
+ layoutPaddingTop = 8;
+ layoutPaddingBottom = 8;
+ layoutBorderSize = 1;
+
+ break;
+
+ }
+ case DPIClassification.DPI_120:
+ {
+ upBorderSkin = spark.skins.mobile120.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile120.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile120.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 4;
+ layoutPaddingLeft = 4;
+ layoutPaddingRight = 4;
+ layoutPaddingTop = 4;
+ layoutPaddingBottom = 4;
+ layoutBorderSize = 1;
+
+ break;
+
+ }
+ default:
+ {
+ upBorderSkin = spark.skins.mobile.assets.ViewMenuItem_up;
+ downBorderSkin = spark.skins.mobile.assets.ViewMenuItem_down;
+ showsCaretBorderSkin = spark.skins.mobile.assets.ViewMenuItem_showsCaret;
+
+ layoutGap = 6;
+ layoutPaddingLeft = 6;
+ layoutPaddingRight = 6;
+ layoutPaddingTop = 6;
+ layoutPaddingBottom = 6;
+ layoutBorderSize = 1;
+ }
+ }
+
+ }
+
+ /**
+ * Class to use for the border in the showsCaret state.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ * @default Button_down
+ */
+ protected var showsCaretBorderSkin:Class;
+
+ /**
+ * @private
+ */
+ override protected function getBorderClassForCurrentState():Class
+ {
+ var borderClass:Class = super.getBorderClassForCurrentState();
+
+ if (currentState == "showsCaret")
+ borderClass = showsCaretBorderSkin;
+
+ return borderClass;
+ }
+
+ /**
+ * @private
+ */
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ var iconPlacement:String = getStyle("iconPlacement");
+ useCenterAlignment = (iconPlacement == IconPlacement.LEFT)
+ || (iconPlacement == IconPlacement.RIGHT);
+
+ super.layoutContents(unscaledWidth, unscaledHeight);
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ // omit call to super.drawBackground(), drawRect instead
+
+ if (currentState == "showsCaret" || currentState == "down")
+ {
+ graphics.beginFill(getStyle("focusColor"));
+ }
+ else
+ {
+ colorMatrix.createGradientBox(unscaledWidth,
+ unscaledHeight,
+ Math.PI / 2, 0, 0);
+ var chromeColor:uint = getStyle("chromeColor");
+
+ graphics.beginGradientFill(GradientType.LINEAR,
+ [chromeColor, chromeColor],
+ [1.0, 1.0],
+ [0, 255],
+ colorMatrix);
+ }
+ graphics.drawRect(0,0,unscaledWidth,unscaledHeight);
+ graphics.lineStyle(0.5,0,0.2);
+ graphics.drawRect(0,unscaledHeight,unscaledWidth,0.5);
+ graphics.endFill();
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/ViewMenuSkin.mxml b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ViewMenuSkin.mxml
new file mode 100644
index 0000000000..67fd754ff5
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/ViewMenuSkin.mxml
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ActionBarBackground.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ActionBarBackground.fxg
new file mode 100644
index 0000000000..0322648b31
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ActionBarBackground.fxg
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/BusyIndicator.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/BusyIndicator.fxg
new file mode 100644
index 0000000000..f6930b9ecf
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/BusyIndicator.fxg
@@ -0,0 +1,217 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_down.fxg
new file mode 100644
index 0000000000..d7fc8a8d33
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_down.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_selectedDown.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_selectedDown.fxg
new file mode 100644
index 0000000000..110f940605
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_selectedDown.fxg
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_selectedUp.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_selectedUp.fxg
new file mode 100644
index 0000000000..52b1a90b44
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_selectedUp.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_up.fxg
new file mode 100644
index 0000000000..bacd138778
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarFirstButton_up.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarLastButton_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarLastButton_down.fxg
new file mode 100644
index 0000000000..656cce3b25
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarLastButton_down.fxg
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarLastButton_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarLastButton_up.fxg
new file mode 100644
index 0000000000..5dfab90532
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarLastButton_up.fxg
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_down.fxg
new file mode 100644
index 0000000000..b0ae67a77b
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_down.fxg
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_selectedDown.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_selectedDown.fxg
new file mode 100644
index 0000000000..ec3707782d
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_selectedDown.fxg
@@ -0,0 +1,75 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_selectedUp.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_selectedUp.fxg
new file mode 100644
index 0000000000..88a46439a8
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_selectedUp.fxg
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_up.fxg
new file mode 100644
index 0000000000..0b95878461
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ButtonBarMiddleButton_up.fxg
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/Button_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/Button_down.fxg
new file mode 100644
index 0000000000..79a535c0db
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/Button_down.fxg
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/Button_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/Button_up.fxg
new file mode 100644
index 0000000000..59854b1ce7
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/Button_up.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CalloutContentBackground.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CalloutContentBackground.fxg
new file mode 100644
index 0000000000..8442b969b6
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CalloutContentBackground.fxg
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_up.fxg
new file mode 100644
index 0000000000..89165c93e3
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_up.fxg
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_upSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_upSelected.fxg
new file mode 100644
index 0000000000..6cb00f8904
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_upSelected.fxg
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_upSymbolSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_upSymbolSelected.fxg
new file mode 100644
index 0000000000..3738ae5a5e
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/CheckBox_upSymbolSelected.fxg
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderThumb_normal.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderThumb_normal.fxg
new file mode 100644
index 0000000000..0527454386
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderThumb_normal.fxg
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderThumb_pressed.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderThumb_pressed.fxg
new file mode 100644
index 0000000000..0527454386
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderThumb_pressed.fxg
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderTrack.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderTrack.fxg
new file mode 100644
index 0000000000..f4a2c69072
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderTrack.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderTrack_filled.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderTrack_filled.fxg
new file mode 100644
index 0000000000..07efd90c3f
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/HSliderTrack_filled.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_down.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_down.fxg
new file mode 100644
index 0000000000..4d39346bba
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_down.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_downSymbolSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_downSymbolSelected.fxg
new file mode 100644
index 0000000000..bcbacca9fe
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_downSymbolSelected.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_up.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_up.fxg
new file mode 100644
index 0000000000..05ed5a056c
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_up.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_upSymbolSelected.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_upSymbolSelected.fxg
new file mode 100644
index 0000000000..2be649cc9a
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/RadioButton_upSymbolSelected.fxg
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerBackground.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerBackground.fxg
new file mode 100644
index 0000000000..78d8c59701
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerBackground.fxg
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerSelectionIndicator.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerSelectionIndicator.fxg
new file mode 100644
index 0000000000..50ee56aadc
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerSelectionIndicator.fxg
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerShadow.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerShadow.fxg
new file mode 100644
index 0000000000..41c1955e7a
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/SpinnerListContainerShadow.fxg
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchBackground_off.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchBackground_off.fxg
new file mode 100644
index 0000000000..43342d9db2
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchBackground_off.fxg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchBackground_on.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchBackground_on.fxg
new file mode 100644
index 0000000000..de3761d6c4
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchBackground_on.fxg
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchThumb_off.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchThumb_off.fxg
new file mode 100644
index 0000000000..432d1e8123
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchThumb_off.fxg
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchThumb_on.fxg b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchThumb_on.fxg
new file mode 100644
index 0000000000..e4c75d152b
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/ToggleSwitchThumb_on.fxg
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/fonts/Roboto-Bold.ttf b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/fonts/Roboto-Bold.ttf
new file mode 100644
index 0000000000..aaf374d2cc
Binary files /dev/null and b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/fonts/Roboto-Bold.ttf differ
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/fonts/Roboto-Regular.ttf b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/fonts/Roboto-Regular.ttf
new file mode 100644
index 0000000000..3e6e2e7613
Binary files /dev/null and b/frameworks/projects/mobiletheme/src/spark/skins/ios7/assets/fonts/Roboto-Regular.ttf differ
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/CalloutArrow.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/CalloutArrow.as
new file mode 100644
index 0000000000..7b2fe53ebb
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/CalloutArrow.as
@@ -0,0 +1,498 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.supportClasses
+{
+import flash.display.BlendMode;
+import flash.display.GradientType;
+import flash.display.Graphics;
+import flash.display.GraphicsPathCommand;
+import flash.display.Sprite;
+
+import mx.core.DPIClassification;
+import mx.core.FlexGlobals;
+import mx.core.IVisualElement;
+import mx.core.UIComponent;
+import mx.core.mx_internal;
+import mx.utils.ColorUtil;
+
+import spark.components.Application;
+import spark.components.ArrowDirection;
+import spark.components.Callout;
+import spark.skins.ios7.CalloutSkin;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * The arrow skin part for CalloutSkin.
+ *
+ * @see spark.skin.mobile.CalloutSkin
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+public class CalloutArrow extends UIComponent
+{
+ public function CalloutArrow()
+ {
+ super();
+
+ useBackgroundGradient = false;
+
+ var applicationDPI:Number = DPIClassification.DPI_160;
+ if (FlexGlobals.topLevelApplication is Application)
+ {
+ applicationDPI = Application(FlexGlobals.topLevelApplication).applicationDPI;
+ }
+
+ // Copy DPI-specific values from CalloutSkin
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ // Note provisional may need changes
+ gap = 32;
+ backgroundGradientHeight = 440;
+ highlightWeight = 4;
+ arrowTipCurveAnchorDistance = 12;
+
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ // Note provisional may need changes
+ gap = 24;
+ backgroundGradientHeight = 330;
+ highlightWeight = 3;
+ arrowTipCurveAnchorDistance = 8;
+
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ gap = 16;
+ backgroundGradientHeight = 220;
+ highlightWeight = 2;
+ arrowTipCurveAnchorDistance = 6;
+
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ gap = 12;
+ backgroundGradientHeight = 165;
+ highlightWeight = 1;
+ arrowTipCurveAnchorDistance = 4;
+
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ // Note provisional may need changes
+ gap = 6;
+ backgroundGradientHeight = 83;
+ highlightWeight = 1;
+ arrowTipCurveAnchorDistance = 2;
+
+ break;
+ }
+ default:
+ {
+ // default DPI_160
+ gap = 8;
+ backgroundGradientHeight = 110;
+ highlightWeight = 1;
+ arrowTipCurveAnchorDistance = 3;
+
+ break;
+ }
+ }
+ }
+
+ /**
+ * A gap on the frame-adjacent side of the arrow graphic to avoid
+ * drawing past the CalloutSkin backgroundCornerRadius.
+ *
+ *
The default implementation matches the gap value with the
+ * backgroundCornerRadius value in CalloutSkin.
+ *
+ * @see spark.skins.mobile.CalloutSkin#backgroundCornerRadius
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var gap:Number;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#backgroundGradientHeight
+ */
+ protected var backgroundGradientHeight:Number;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#highlightWeight
+ */
+ private var highlightWeight:Number;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#useBackgroundGradient
+ */
+ protected var useBackgroundGradient:Boolean;
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#borderColor
+ */
+ protected var borderColor:Number = -1; // if not set
+
+ /**
+ * @copy spark.skins.mobile.CalloutSkin#borderThickness
+ */
+ protected var borderThickness:Number = -1 ; // marker that borderThickness was not set directly
+
+ /**
+ * @private
+ * A sibling of the arrow used to erase the drop shadow in CalloutSkin
+ */
+ private var eraseFill:Sprite;
+
+ /**
+ * The distance of the arrow tip's curve's anchor point from arrow tip
+ */
+ private var arrowTipCurveAnchorDistance:Number;
+
+ /* helper private accessors */
+
+ /* returns borderThickness from style if member is -1, or borderThickness. Returns 0 if NaN */
+ private function get actualBorderThickness():Number
+ {
+ return calloutSkin.actualBorderThickness;
+ }
+
+ private function get actualBorderColor():uint
+ {
+ return calloutSkin.actualBorderColor;
+ }
+
+ protected function get calloutSkin():CalloutSkin
+ {
+ return parent as CalloutSkin ;
+ }
+
+ protected function get calloutHostComponent():Callout {
+ return calloutSkin.hostComponent;
+ }
+
+ /**
+ * @private
+ */
+
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ // eraseFill has the same position and arrow shape in order to erase
+ // the drop shadow under the arrow when backgroundAlpha < 1
+ eraseFill = new Sprite();
+ eraseFill.blendMode = BlendMode.ERASE;
+
+ // layer eraseFill below the arrow
+ parent.addChildAt(eraseFill, parent.getChildIndex(this));
+ }
+
+ /**
+ * @private
+ */
+ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+ graphics.clear();
+ eraseFill.graphics.clear();
+ var hostComponent: Callout = calloutHostComponent;
+ var arrowDirection:String = hostComponent.arrowDirection;
+
+ if (arrowDirection == ArrowDirection.NONE)
+ return;
+
+ // when drawing the arrow, compensate for cornerRadius via padding
+ var arrowGraphics:Graphics = this.graphics;
+ var eraseGraphics:Graphics = eraseFill.graphics;
+ var arrowWidth:Number = unscaledWidth;
+ var arrowHeight:Number = unscaledHeight;
+ var arrowX:Number = 0;
+ var arrowY:Number = 0;
+ var arrowTipX:Number = 0;
+ var arrowTipY:Number = 0;
+ var arrowEndX:Number = 0;
+ var arrowEndY:Number = 0;
+
+ var borderWeight:Number = actualBorderThickness;
+ var showBorder:Boolean = borderWeight > 0;
+
+ var borderHalf:Number = borderWeight / 2;
+ var isHorizontal:Boolean = false;
+ var commands:Vector. = new Vector.(4, true);
+ var coords:Vector. = new Vector.(10, true);
+ commands[0] = GraphicsPathCommand.MOVE_TO;
+ commands[1] = GraphicsPathCommand.LINE_TO;
+ commands[2] = GraphicsPathCommand.CURVE_TO;
+ commands[3] = GraphicsPathCommand.LINE_TO;
+
+ if ((arrowDirection == ArrowDirection.LEFT) ||
+ (arrowDirection == ArrowDirection.RIGHT))
+ {
+ isHorizontal = true;
+
+ arrowX = -borderHalf;
+ arrowY = gap;
+ arrowHeight = arrowHeight - (gap * 2);
+
+ arrowTipX = arrowWidth - borderHalf;
+ arrowTipY = arrowY + (arrowHeight / 2);
+
+ arrowEndX = arrowX;
+ arrowEndY = arrowY + arrowHeight;
+
+ // flip coordinates to point left
+ if (arrowDirection == ArrowDirection.LEFT)
+ {
+ arrowX = arrowWidth - arrowX;
+ arrowTipX = arrowWidth - arrowTipX;
+ arrowEndX = arrowWidth - arrowEndX;
+ }
+
+ coords[0] = arrowX;
+ coords[1] = arrowY;
+ coords[2] = arrowTipX + arrowTipCurveAnchorDistance;
+ coords[3] = arrowTipY - arrowTipCurveAnchorDistance;
+ if (arrowDirection == ArrowDirection.LEFT)
+ {
+ coords[4] = arrowTipX - arrowTipCurveAnchorDistance * 2;
+ }
+ else
+ {
+ coords[4] = arrowTipX + arrowTipCurveAnchorDistance * 2;
+ }
+ coords[5] = arrowTipY;
+ coords[6] = arrowTipX + arrowTipCurveAnchorDistance;
+ coords[7] = arrowTipY + arrowTipCurveAnchorDistance;
+ coords[8] = arrowEndX
+ coords[9] = arrowEndY;
+ }
+ else
+ {
+ arrowX = gap;
+ arrowY = -borderHalf;
+ arrowWidth = arrowWidth - (gap * 2);
+
+ arrowTipX = arrowX + (arrowWidth / 2);
+ arrowTipY = arrowHeight - borderHalf;
+
+ arrowEndX = arrowX + arrowWidth;
+ arrowEndY = arrowY;
+
+ // flip coordinates to point up
+ if (hostComponent.arrowDirection == ArrowDirection.UP)
+ {
+ arrowY = arrowHeight - arrowY;
+ arrowTipY = arrowHeight - arrowTipY;
+ arrowEndY = arrowHeight - arrowEndY;
+ }
+
+ coords[0] = arrowX;
+ coords[1] = arrowY;
+ coords[2] = arrowTipX - arrowTipCurveAnchorDistance;
+ coords[3] = arrowTipY - arrowTipCurveAnchorDistance;
+ coords[4] = arrowTipX;
+ if (hostComponent.arrowDirection == ArrowDirection.UP)
+ {
+ coords[5] = arrowTipY - arrowTipCurveAnchorDistance * 2;
+ }
+ else
+ {
+ coords[5] = arrowTipY + arrowTipCurveAnchorDistance * 2;
+ }
+ coords[6] = arrowTipX + arrowTipCurveAnchorDistance;
+ coords[7] = arrowTipY - arrowTipCurveAnchorDistance;
+ coords[8] = arrowEndX
+ coords[9] = arrowEndY;
+ }
+
+
+ var backgroundColor:Number = getStyle("backgroundColor");
+ var backgroundAlpha:Number = getStyle("backgroundAlpha");
+
+ if (useBackgroundGradient)
+ {
+ var backgroundColorTop:Number = ColorUtil.adjustBrightness2(backgroundColor,
+ CalloutSkin.BACKGROUND_GRADIENT_BRIGHTNESS_TOP);
+ var backgroundColorBottom:Number = ColorUtil.adjustBrightness2(backgroundColor,
+ CalloutSkin.BACKGROUND_GRADIENT_BRIGHTNESS_BOTTOM);
+
+ // translate the gradient based on the arrow position
+ MobileSkin.colorMatrix.createGradientBox(unscaledWidth,
+ backgroundGradientHeight, Math.PI / 2, 0, -getLayoutBoundsY());
+
+ arrowGraphics.beginGradientFill(GradientType.LINEAR,
+ [backgroundColorTop, backgroundColorBottom],
+ [backgroundAlpha, backgroundAlpha],
+ [0, 255],
+ MobileSkin.colorMatrix);
+ }
+ else
+ {
+ arrowGraphics.beginFill(backgroundColor, backgroundAlpha);
+ }
+
+ // cover the adjacent border from the callout frame
+ if (showBorder)
+ {
+ var coverX:Number = 0;
+ var coverY:Number = 0;
+ var coverWidth:Number = 0;
+ var coverHeight:Number = 0;
+
+ switch (arrowDirection)
+ {
+ case ArrowDirection.UP:
+ {
+ coverX = arrowX;
+ coverY = arrowY;
+ coverWidth = arrowWidth;
+ coverHeight = borderWeight;
+ break;
+ }
+ case ArrowDirection.DOWN:
+ {
+ coverX = arrowX;
+ coverY = -borderWeight;
+ coverWidth = arrowWidth;
+ coverHeight = borderWeight;
+ break;
+ }
+ case ArrowDirection.LEFT:
+ {
+ coverX = arrowX;
+ coverY = arrowY;
+ coverWidth = borderWeight;
+ coverHeight = arrowHeight;
+ break;
+ }
+ case ArrowDirection.RIGHT:
+ {
+ coverX = -borderWeight;
+ coverY = arrowY;
+ coverWidth = borderWeight;
+ coverHeight = arrowHeight;
+ break;
+ }
+ }
+
+ arrowGraphics.drawRect(coverX, coverY, coverWidth, coverHeight);
+ }
+
+ // erase the drop shadow from the CalloutSkin
+ if (backgroundAlpha < 1)
+ {
+ // move eraseFill to the same position as the arrow
+ eraseFill.x = getLayoutBoundsX()
+ eraseFill.y = getLayoutBoundsY();
+
+ // draw the arrow shape
+ eraseGraphics.beginFill(0, 1);
+ eraseGraphics.drawPath(commands, coords);
+ eraseGraphics.endFill();
+ }
+
+ // draw arrow path
+ if (showBorder)
+ arrowGraphics.lineStyle(borderWeight, actualBorderColor, 1, true);
+
+ arrowGraphics.drawPath(commands, coords);
+ arrowGraphics.endFill();
+
+ // adjust the highlight position to the origin of the callout
+ var isArrowUp:Boolean = (arrowDirection == ArrowDirection.UP);
+ var offsetY:Number = (isArrowUp) ? unscaledHeight : -getLayoutBoundsY();
+
+ // highlight starts after the backgroundCornerRadius
+ var highlightX:Number = gap - getLayoutBoundsX();
+
+ // highlight Y position is based on the stroke weight
+ var highlightOffset:Number = (highlightWeight * 1.5);
+ var highlightY:Number = highlightOffset + offsetY;
+
+ // highlight width spans the callout width minus the corner radius
+ var highlightWidth:Number = IVisualElement(calloutSkin).getLayoutBoundsWidth() - (gap * 2);
+
+ if (isHorizontal)
+ {
+ highlightWidth -= arrowWidth;
+
+ if (arrowDirection == ArrowDirection.LEFT)
+ highlightX += arrowWidth;
+ }
+
+ // highlight on the top edge is drawn in the arrow only in the UP direction
+ if (useBackgroundGradient)
+ {
+ if (isArrowUp)
+ {
+ // highlight follows the top edge, including the arrow
+ var rightWidth:Number = highlightWidth - arrowWidth;
+
+ // highlight style
+ arrowGraphics.lineStyle(highlightWeight, 0xFFFFFF, 0.2 * backgroundAlpha);
+
+ // in the arrow coordinate space, the highlightX must be less than 0
+ if (highlightX < 0)
+ {
+ arrowGraphics.moveTo(highlightX, highlightY);
+ arrowGraphics.lineTo(arrowX, highlightY);
+
+ // compute the remaining highlight
+ rightWidth -= (arrowX - highlightX);
+ }
+
+ // arrow highlight (adjust Y downward)
+ coords[1] = arrowY + highlightOffset;
+ coords[3] = arrowTipY + highlightOffset;
+ coords[5] = arrowEndY + highlightOffset;
+ arrowGraphics.drawPath(commands, coords);
+
+ // right side
+ if (rightWidth > 0)
+ {
+ arrowGraphics.moveTo(arrowEndX, highlightY);
+ arrowGraphics.lineTo(arrowEndX + rightWidth, highlightY);
+ }
+ }
+ else
+ {
+ // straight line across the top
+ arrowGraphics.lineStyle(highlightWeight, 0xFFFFFF, 0.2 * backgroundAlpha);
+ arrowGraphics.moveTo(highlightX, highlightY);
+ arrowGraphics.lineTo(highlightX + highlightWidth, highlightY);
+ }
+ }
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/StageTextSkinBase.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/StageTextSkinBase.as
new file mode 100644
index 0000000000..89b8b13156
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/StageTextSkinBase.as
@@ -0,0 +1,400 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.supportClasses
+{
+import flash.display.DisplayObject;
+import flash.events.FocusEvent;
+
+import mx.core.DPIClassification;
+import mx.core.mx_internal;
+
+import spark.components.supportClasses.IStyleableEditableText;
+import spark.components.supportClasses.SkinnableTextBase;
+import spark.components.supportClasses.StyleableStageText;
+import spark.components.supportClasses.StyleableTextField;
+import spark.core.IDisplayText;
+import spark.skins.mobile.supportClasses.MobileSkin;
+
+use namespace mx_internal;
+
+/**
+ * ActionScript-based skin for text input controls in mobile applications.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+public class StageTextSkinBase extends MobileSkin
+{
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ *
+ */
+ public function StageTextSkinBase()
+ {
+ super();
+
+ switch (applicationDPI)
+ {
+ case DPIClassification.DPI_640:
+ {
+ measuredDefaultWidth = 1200;
+ measuredDefaultHeight = 132;
+ layoutBorderSize = 3;
+ roundheight = 24;
+ break;
+ }
+ case DPIClassification.DPI_480:
+ {
+ measuredDefaultWidth = 880;
+ measuredDefaultHeight = 100;
+ layoutBorderSize = 2;
+ roundheight = 18;
+ break;
+ }
+ case DPIClassification.DPI_320:
+ {
+ measuredDefaultWidth = 600;
+ measuredDefaultHeight = 66;
+ layoutBorderSize = 1.5;
+ roundheight = 14;
+ break;
+ }
+ case DPIClassification.DPI_240:
+ {
+ measuredDefaultWidth = 440;
+ measuredDefaultHeight = 50;
+ layoutBorderSize = 1;
+ roundheight = 10;
+ break;
+ }
+ case DPIClassification.DPI_120:
+ {
+ measuredDefaultWidth = 220;
+ measuredDefaultHeight = 25;
+ layoutBorderSize = .5;
+ roundheight = 5;
+ break;
+ }
+ default:
+ {
+ measuredDefaultWidth = 300;
+ measuredDefaultHeight = 33;
+ layoutBorderSize = .5;
+ roundheight = 7;
+ break;
+ }
+
+ }
+ addEventListener(FocusEvent.FOCUS_IN, focusChangeHandler);
+ addEventListener(FocusEvent.FOCUS_OUT, focusChangeHandler);
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Graphics variables
+ //
+ //--------------------------------------------------------------------------
+
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the border's thickness.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ protected var layoutBorderSize:uint;
+
+ protected var roundheight:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ protected var isFocused:Boolean = false;
+
+ /**
+ * @private
+ *
+ * Instance of the border graphics.
+ */
+ protected var border:DisplayObject;
+
+ private var borderVisibleChanged:Boolean = false;
+
+ /**
+ * @private
+ *
+ * Multiline flag.
+ */
+ protected var multiline:Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * textDisplay skin part.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public var textDisplay:IStyleableEditableText;
+
+ [Bindable]
+ /**
+ * Bindable promptDisplay skin part. Bindings fire when promptDisplay is
+ * removed and added for proper updating by the SkinnableTextBase.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3.0
+ * @productversion Flex 4.6
+ */
+ public var promptDisplay:IDisplayText;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!textDisplay)
+ {
+ textDisplay = createTextDisplay();
+ textDisplay.editable = true;
+ textDisplay.styleName = this;
+ this.addChild(DisplayObject(textDisplay));
+ }
+ }
+
+ /** Could be overridden by subclasses
+ *
+ * @return instance of IStyleableEditableText
+ */
+ protected function createTextDisplay():IStyleableEditableText
+ {
+ return new StyleableStageText(multiline);
+ }
+
+ /**
+ * @private
+ */
+ override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ super.drawBackground(unscaledWidth, unscaledHeight);
+
+ var contentBackgroundColor:uint = getStyle("contentBackgroundColor");
+ var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
+ //change border color and thickness when in focus
+ var borderColor:uint = isFocused ? getStyle("focusColor") : getStyle("borderColor");
+ var borderWidth:uint = layoutBorderSize * 2;
+ if (isNaN(contentBackgroundAlpha))
+ {
+ contentBackgroundAlpha = 1;
+ }
+ // change the border type
+ if (getStyle("contentBackgroundBorder") == "roundedrect")
+ {
+ graphics.lineStyle(layoutBorderSize, borderColor, 1, true);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRoundRectComplex(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth, roundheight, roundheight, roundheight, roundheight);
+ graphics.endFill();
+ }
+ if (getStyle("contentBackgroundBorder") == "rectangle")
+ {
+
+ //rectangle border and background
+ graphics.lineStyle(layoutBorderSize, borderColor, 1);
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(layoutBorderSize, layoutBorderSize, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ else if (getStyle("contentBackgroundBorder") == "none")
+ {
+
+ //rectangle border and background
+ graphics.beginFill(contentBackgroundColor, contentBackgroundAlpha);
+ graphics.drawRect(0, 0, unscaledWidth - borderWidth, unscaledHeight - borderWidth);
+ graphics.endFill();
+ }
+ }
+
+ /**
+ * @private
+ */
+ override public function styleChanged(styleProp:String):void
+ {
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || styleProp == "borderVisible")
+ {
+ borderVisibleChanged = true;
+ invalidateProperties();
+ }
+
+ if (allStyles || styleProp.indexOf("padding") == 0)
+ {
+ invalidateDisplayList();
+ }
+ super.styleChanged(styleProp);
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+
+ var showPrompt:Boolean = currentState.indexOf("WithPrompt") != -1;
+
+ if (showPrompt && !promptDisplay)
+ {
+ promptDisplay = createPromptDisplay();
+ promptDisplay.addEventListener(FocusEvent.FOCUS_IN, promptDisplay_focusInHandler);
+ }
+ else if (!showPrompt && promptDisplay)
+ {
+ promptDisplay.removeEventListener(FocusEvent.FOCUS_IN, promptDisplay_focusInHandler);
+ removeChild(promptDisplay as DisplayObject);
+ promptDisplay = null;
+ }
+ super.commitCurrentState();
+
+ invalidateDisplayList();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ * Create a control appropriate for displaying the prompt text in a mobile
+ * input field.
+ */
+ protected function createPromptDisplay():IDisplayText
+ {
+ var prompt:StyleableTextField = StyleableTextField(createInFontContext(StyleableTextField));
+ prompt.styleName = this;
+ prompt.editable = false;
+ prompt.mouseEnabled = false;
+ prompt.useTightTextBounds = false;
+ // StageText objects appear in their own layer on top of the display
+ // list. So, even though this prompt may be created after the StageText
+ // for textDisplay, textDisplay will still be on top.
+ addChild(prompt);
+
+ return prompt;
+ }
+
+ /**
+ * @private
+ * Utility function used by subclasses' measure functions to measure their
+ * text host components.
+ */
+ protected function measureTextComponent(hostComponent:SkinnableTextBase):void
+ {
+ var paddingLeft:Number = getStyle("paddingLeft");
+ var paddingRight:Number = getStyle("paddingRight");
+ var paddingTop:Number = getStyle("paddingTop");
+ var paddingBottom:Number = getStyle("paddingBottom");
+ var textHeight:Number = getStyle("fontSize");
+
+ if (textDisplay)
+ {
+ textHeight = getElementPreferredHeight(textDisplay);
+ }
+ // width is based on maxChars (if set)
+ if (hostComponent && hostComponent.maxChars)
+ {
+ // Grab the fontSize and subtract 2 as the pixel value for each character.
+ // This is just an approximation, but it appears to be a reasonable one
+ // for most input and most font.
+ var characterWidth:int = Math.max(1, (textHeight - 2));
+ measuredWidth = (characterWidth * hostComponent.maxChars) + paddingLeft + paddingRight;
+ }
+
+ measuredHeight = paddingTop + textHeight + paddingBottom;
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Event handlers
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Listen to see if the component gains focus then change the style to selected
+ */
+ private function focusChangeHandler(event:FocusEvent):void
+ {
+ isFocused = event.type == FocusEvent.FOCUS_IN;
+ invalidateDisplayList();
+ }
+
+ /**
+ * If the prompt is focused, we need to move focus to the textDisplay
+ * StageText. This needs to happen outside of the process of setting focus
+ * to the prompt, so we use callLater to do that.
+ */
+ private function focusTextDisplay():void
+ {
+ textDisplay.setFocus();
+ }
+
+ private function promptDisplay_focusInHandler(event:FocusEvent):void
+ {
+ callLater(focusTextDisplay);
+ }
+}
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/TextSkinBase.as b/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/TextSkinBase.as
new file mode 100644
index 0000000000..319d4a093f
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/ios7/supportClasses/TextSkinBase.as
@@ -0,0 +1,213 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.supportClasses
+{
+
+ import flash.display.DisplayObject;
+
+ import mx.core.mx_internal;
+
+ import spark.components.supportClasses.StyleableTextField;
+ import spark.skins.mobile.supportClasses.MobileSkin;
+
+ use namespace mx_internal;
+
+ /**
+ * ActionScript-based skin for text input controls in mobile applications that
+ * uses a StyleableTextField class for the text display.
+ *
+ * @see spark.components.supportClasses.StyleableTextField
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+ public class TextSkinBase extends MobileSkin
+ {
+ //--------------------------------------------------------------------------
+ //
+ // Constructor
+ //
+ //--------------------------------------------------------------------------
+ /**
+ * Constructor.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ *
+ */
+ public function TextSkinBase()
+ {
+ super();
+ }
+
+ //--------------------------------------------------------------------------
+ //
+ // Graphics variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the border.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+
+ //--------------------------------------------------------------------------
+ //
+ // Layout variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * Defines the corner radius.
+ *
+ * @langversion 3.0
+ * @playerversion Flash 10
+ * @playerversion AIR 2.5
+ * @productversion Flex 4.5
+ */
+
+ protected var layoutBorderSize:uint;
+
+ //--------------------------------------------------------------------------
+ //
+ // Variables
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ *
+ * Instance of the border graphics.
+ */
+ protected var border:DisplayObject;
+
+ private var borderVisibleChanged:Boolean = false;
+
+ //--------------------------------------------------------------------------
+ //
+ // Skin parts
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * textDisplay skin part.
+ */
+ public var textDisplay:StyleableTextField;
+
+ [Bindable]
+ /**
+ * Bindable promptDisplay skin part. Bindings fire when promptDisplay is
+ * removed and added for proper updating by the SkinnableTextBase.
+ */
+ public var promptDisplay:StyleableTextField;
+
+ //--------------------------------------------------------------------------
+ //
+ // Overridden methods
+ //
+ //--------------------------------------------------------------------------
+
+ /**
+ * @private
+ */
+ override protected function createChildren():void
+ {
+ super.createChildren();
+
+ if (!textDisplay)
+ {
+ textDisplay = StyleableTextField(createInFontContext(StyleableTextField));
+ textDisplay.styleName = this;
+ textDisplay.editable = true;
+ textDisplay.useTightTextBounds = false;
+ addChild(textDisplay);
+ }
+ }
+
+ /**
+ * @private
+ */
+ protected function createPromptDisplay():StyleableTextField
+ {
+ var prompt:StyleableTextField = StyleableTextField(createInFontContext(StyleableTextField));
+ prompt.styleName = this;
+ prompt.editable = false;
+ prompt.mouseEnabled = false;
+ prompt.useTightTextBounds = false;
+ prompt.focusEnabled = false;
+ return prompt;
+ }
+
+ /**
+ * @private
+ */
+
+ override public function styleChanged(styleProp:String):void
+ {
+ var allStyles:Boolean = !styleProp || styleProp == "styleName";
+
+ if (allStyles || styleProp == "borderVisible")
+ {
+ borderVisibleChanged = true;
+ invalidateProperties();
+ }
+
+ if (allStyles || styleProp.indexOf("padding") == 0)
+ {
+ invalidateDisplayList();
+ }
+
+ super.styleChanged(styleProp);
+ }
+
+ /**
+ * @private
+ */
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+
+ alpha = currentState.indexOf("disabled") == -1 ? 1 : 0.5;
+
+ var showPrompt:Boolean = currentState.indexOf("WithPrompt") >= 0;
+
+ if (showPrompt && !promptDisplay)
+ {
+ promptDisplay = createPromptDisplay();
+ addChild(promptDisplay);
+ }
+ else if (!showPrompt && promptDisplay)
+ {
+ removeChild(promptDisplay);
+ promptDisplay = null;
+ }
+
+ invalidateDisplayList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ActionBarSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ActionBarSkin.as
index 0d948af77e..6e1bba3bfc 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ActionBarSkin.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ActionBarSkin.as
@@ -109,7 +109,6 @@ public class ActionBarSkin extends MobileSkin
layoutShadowHeight = 9;
layoutContentGroupHeight = 130;
layoutTitleGroupHorizontalPadding = 40;
-
borderClass = spark.skins.mobile480.assets.ActionBarBackground;
break;
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 0000000000..040bf53971
--- /dev/null
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/BusyIndicatorSkin.as
@@ -0,0 +1,469 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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.Event;
+ 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
+ // component changes state when removed but it doesn't get validated in time
+ addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler,false,0,true);
+ }
+
+ 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 = !styleProp || styleProp == "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 || styleProp == "rotationInterval")
+ {
+ // Update the timer if the rotation interval has changed.
+ if (isRotating())
+ {
+ stopRotation();
+ startRotation();
+ }
+ }
+
+ if (allStyles || styleProp == "symbolColor")
+ {
+ updateSpinner(spinnerDiameter);
+ }
+ }
+
+ override protected function measure():void
+ {
+ // 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;
+ }
+
+ override protected function commitCurrentState():void
+ {
+ super.commitCurrentState();
+ if(currentState == "rotatingState")
+ {
+ startRotation();
+ }
+ else
+ {
+ stopRotation();
+ }
+ invalidateSize();
+ invalidateDisplayList();
+ }
+
+ /**
+ * @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;
+ }
+
+ override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
+ {
+ measuredHeight = unscaledHeight;
+ measuredWidth = unscaledWidth;
+ }
+
+ /**
+ * @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();
+ }
+
+ /**
+ * @private
+ */
+ private function removedFromStageHandler(event:Event):void
+ {
+ stopRotation();
+ }
+
+
+ }
+}
\ No newline at end of file
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ToggleSwitchSkin.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ToggleSwitchSkin.as
index fc599d59b0..6169bab00b 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/ToggleSwitchSkin.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/ToggleSwitchSkin.as
@@ -86,7 +86,7 @@ public class ToggleSwitchSkin extends MobileSkin
layoutTextShadowOffset = -2;
layoutInnerPadding = 14;
layoutOuterPadding = 22;
- slidingContentOverlayClass = spark.skins.mobile320.assets.ToggleSwitch_contentShadow;
+ slidingContentOverlayClass = spark.skins.mobile640.assets.ToggleSwitch_contentShadow;
break;
}
case DPIClassification.DPI_480:
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/CalloutArrow.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/CalloutArrow.as
index ea4bcf0498..605e01a77a 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/CalloutArrow.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/CalloutArrow.as
@@ -56,12 +56,16 @@ public class CalloutArrow extends UIComponent
useBackgroundGradient = true;
- var applicationDPI:Number = Application(FlexGlobals.topLevelApplication).applicationDPI;
+ var applicationDPI:Number = DPIClassification.DPI_160;
+ if (FlexGlobals.topLevelApplication is Application)
+ {
+ applicationDPI = Application(FlexGlobals.topLevelApplication).applicationDPI;
+ }
// Copy DPI-specific values from CalloutSkin
switch (applicationDPI)
{
- case DPIClassification.DPI_320:
+ case DPIClassification.DPI_640:
{
// Note provisional may need changes
gap = 32;
diff --git a/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/HSliderDataTip.as b/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/HSliderDataTip.as
index 394d8d759c..2da3213b9e 100644
--- a/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/HSliderDataTip.as
+++ b/frameworks/projects/mobiletheme/src/spark/skins/mobile/supportClasses/HSliderDataTip.as
@@ -29,7 +29,6 @@ import mx.core.UIComponent;
import mx.core.mx_internal;
import spark.components.Application;
-import spark.components.HSlider;
import spark.components.supportClasses.StyleableTextField;
use namespace mx_internal;
@@ -191,9 +190,8 @@ public class HSliderDataTip extends UIComponent implements IDataRenderer
switch (applicationDPI)
{
- case DPIClassification.DPI_320:
+ case DPIClassification.DPI_640:
{
- // Note provisional may need changes
fontSize = "60";
leftTextPadding = 28;
leftRightTextPadding = 56;
@@ -205,7 +203,6 @@ public class HSliderDataTip extends UIComponent implements IDataRenderer
}
case DPIClassification.DPI_480:
{
- // Note provisional may need changes
fontSize = "40";
leftTextPadding = 22;
leftRightTextPadding = 44;
@@ -239,7 +236,6 @@ public class HSliderDataTip extends UIComponent implements IDataRenderer
}
case DPIClassification.DPI_120:
{
- // Note provisional may need changes
fontSize = "10";
leftTextPadding = 6;
leftRightTextPadding = 11;
diff --git a/frameworks/projects/mx/src/mx/core/Version.as b/frameworks/projects/mx/src/mx/core/Version.as
index 90b75ca4f7..647c056b8b 100644
--- a/frameworks/projects/mx/src/mx/core/Version.as
+++ b/frameworks/projects/mx/src/mx/core/Version.as
@@ -23,4 +23,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/rpc/src/mx/core/Version.as b/frameworks/projects/rpc/src/mx/core/Version.as
index 9191675da0..496ab63000 100644
--- a/frameworks/projects/rpc/src/mx/core/Version.as
+++ b/frameworks/projects/rpc/src/mx/core/Version.as
@@ -22,4 +22,4 @@ import mx.core.mx_internal;
* @private
* Version string for this class.
*/
-mx_internal static const VERSION:String = "4.13.0.0";
+mx_internal static const VERSION:String = "4.14.0.0";
diff --git a/frameworks/projects/spark/defaults.css b/frameworks/projects/spark/defaults.css
index 0ced94eaec..9c4c0d3dcc 100644
--- a/frameworks/projects/spark/defaults.css
+++ b/frameworks/projects/spark/defaults.css
@@ -50,6 +50,12 @@ ButtonBar
skinClass: ClassReference("spark.skins.spark.ButtonBarSkin");
}
+BusyIndicator
+{
+ skinClass: ClassReference("spark.skins.spark.BusyIndicatorSkin");
+ rotationInterval: 30; /* Must be multiples of 30 */
+}
+
Callout
{
backgroundColor: #ffffff;
diff --git a/frameworks/projects/spark/src/SparkClasses.as b/frameworks/projects/spark/src/SparkClasses.as
index 0aa207f69d..ac6cd00952 100644
--- a/frameworks/projects/spark/src/SparkClasses.as
+++ b/frameworks/projects/spark/src/SparkClasses.as
@@ -54,6 +54,7 @@ import spark.skins.spark.BorderContainerSkin; BorderContainerSkin;
import spark.skins.spark.ButtonSkin; ButtonSkin;
import spark.skins.spark.DefaultButtonSkin; DefaultButtonSkin;
import spark.skins.spark.ButtonBarSkin; ButtonBarSkin;
+import spark.skins.spark.BusyIndicatorSkin; BusyIndicatorSkin;
import spark.skins.spark.ButtonBarFirstButtonSkin; ButtonBarFirstButtonSkin;
import spark.skins.spark.ButtonBarMiddleButtonSkin; ButtonBarMiddleButtonSkin;
import spark.skins.spark.ButtonBarLastButtonSkin; ButtonBarLastButtonSkin;
diff --git a/frameworks/projects/spark/src/spark/components/BusyIndicator.as b/frameworks/projects/spark/src/spark/components/BusyIndicator.as
index c47c9cf263..f9893d8467 100644
--- a/frameworks/projects/spark/src/spark/components/BusyIndicator.as
+++ b/frameworks/projects/spark/src/spark/components/BusyIndicator.as
@@ -19,33 +19,20 @@
package spark.components
{
-
-import flash.display.CapsStyle;
-import flash.display.Graphics;
-import flash.display.LineScaleMode;
-import flash.display.Shape;
-import flash.display.Sprite;
-import flash.events.Event;
-import flash.events.TimerEvent;
-import flash.geom.Matrix;
-import flash.geom.Matrix3D;
-import flash.geom.Point;
-import flash.geom.Transform;
-import flash.geom.Vector3D;
-import flash.utils.Timer;
-
-import mx.core.DesignLayer;
-import mx.core.DPIClassification;
-import mx.core.FlexGlobals;
-import mx.core.IUIComponent;
-import mx.core.IVisualElement;
-import mx.core.UIComponent;
-import mx.core.mx_internal;
-import mx.events.FlexEvent;
-import mx.events.PropertyChangeEvent;
-import mx.geom.TransformOffsets;
-
-use namespace mx_internal;
+ import flash.events.Event;
+
+ import mx.core.DesignLayer;
+ 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;
+
+ import spark.components.supportClasses.SkinnableComponent;
+
+ [SkinState("rotatingState")]
+ [SkinState("notRotatingState")]
//--------------------------------------
// Styles
@@ -83,8 +70,10 @@ use namespace mx_internal;
/**
* The BusyIndicator defines a component to display when a long-running
- * operation is in progress. This component creates a spinner with twelve spokes.
- * The color of the spokes is controlled by the value of the symbolColor style.
+ * operation is in progress.
+ * For Web, Desktop and iOS, a spinner with twelve spoke is drawn.
+ * For Android, a circle is drawn that rotates.
+ * The color of the circle or spokes is controlled by the value of the symbolColor style.
* The transparency of this component can be modified using the alpha property,
* but the alpha value of each spoke cannot be modified.
*
@@ -102,10 +91,12 @@ use namespace mx_internal;
*
The BusyIndicator has the following default characteristics: