blob: 22a0f4f68bfdd344c1a5c1c4cb7816ca19f87fd4 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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.DisplayObject;
import flash.display.GradientType;
import mx.core.DPIClassification;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import mx.utils.ColorUtil;
import spark.components.supportClasses.StyleableTextField;
import spark.skins.mobile.supportClasses.ButtonSkinBase;
import spark.skins.mobile120.assets.Button_down;
import spark.skins.mobile120.assets.Button_up;
import spark.skins.mobile160.assets.Button_down;
import spark.skins.mobile160.assets.Button_up;
import spark.skins.mobile240.assets.Button_down;
import spark.skins.mobile240.assets.Button_up;
import spark.skins.mobile320.assets.Button_down;
import spark.skins.mobile320.assets.Button_up;
import spark.skins.mobile480.assets.Button_down;
import spark.skins.mobile480.assets.Button_up;
import spark.skins.mobile640.assets.Button_down;
import spark.skins.mobile640.assets.Button_up;
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();
switch (applicationDPI)
{
case DPIClassification.DPI_640:
{
upBorderSkin = spark.skins.mobile640.assets.Button_up;
downBorderSkin = spark.skins.mobile640.assets.Button_down;
layoutGap = 20;
layoutCornerEllipseSize = 40;
layoutPaddingLeft = 40;
layoutPaddingRight = 40;
layoutPaddingTop = 40;
layoutPaddingBottom = 40;
layoutBorderSize = 2;
measuredDefaultWidth = 128;
measuredDefaultHeight = 172;
break;
}
case DPIClassification.DPI_480:
{
// Note provisional may need changes
upBorderSkin = spark.skins.mobile480.assets.Button_up;
downBorderSkin = spark.skins.mobile480.assets.Button_down;
layoutGap = 14;
layoutCornerEllipseSize = 30;
layoutPaddingLeft = 30;
layoutPaddingRight = 30;
layoutPaddingTop = 30;
layoutPaddingBottom = 30;
layoutBorderSize = 2;
measuredDefaultWidth = 96;
measuredDefaultHeight = 130;
break;
}
case DPIClassification.DPI_320:
{
upBorderSkin = spark.skins.mobile320.assets.Button_up;
downBorderSkin = spark.skins.mobile320.assets.Button_down;
layoutGap = 10;
layoutCornerEllipseSize = 20;
layoutPaddingLeft = 20;
layoutPaddingRight = 20;
layoutPaddingTop = 20;
layoutPaddingBottom = 20;
layoutBorderSize = 2;
measuredDefaultWidth = 64;
measuredDefaultHeight = 86;
break;
}
case DPIClassification.DPI_240:
{
upBorderSkin = spark.skins.mobile240.assets.Button_up;
downBorderSkin = spark.skins.mobile240.assets.Button_down;
layoutGap = 7;
layoutCornerEllipseSize = 15;
layoutPaddingLeft = 15;
layoutPaddingRight = 15;
layoutPaddingTop = 15;
layoutPaddingBottom = 15;
layoutBorderSize = 1;
measuredDefaultWidth = 48;
measuredDefaultHeight = 65;
break;
}
case DPIClassification.DPI_120:
{
upBorderSkin = spark.skins.mobile120.assets.Button_up;
downBorderSkin = spark.skins.mobile120.assets.Button_down;
layoutGap = 4;
layoutCornerEllipseSize = 8;
layoutPaddingLeft = 8;
layoutPaddingRight = 8;
layoutPaddingTop = 8;
layoutPaddingBottom = 8;
layoutBorderSize = 1;
measuredDefaultWidth = 24;
measuredDefaultHeight = 33;
break;
}
default:
{
// default DPI_160
upBorderSkin = spark.skins.mobile160.assets.Button_up;
downBorderSkin = spark.skins.mobile160.assets.Button_down;
layoutGap = 5;
layoutCornerEllipseSize = 10;
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);
}
override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
{
super.drawBackground(unscaledWidth, unscaledHeight);
var chromeColor:uint = getStyle(fillColorStyleName);
// In the down state, the fill shadow is defined in the FXG asset
if (currentState == "down")
{
graphics.beginFill(chromeColor);
}
else
{
var colors:Array = [];
colorMatrix.createGradientBox(unscaledWidth, unscaledHeight, Math.PI / 2, 0, 0);
colors[0] = ColorUtil.adjustBrightness2(chromeColor, 70);
colors[1] = chromeColor;
graphics.beginGradientFill(GradientType.LINEAR, colors, CHROME_COLOR_ALPHAS, CHROME_COLOR_RATIOS, colorMatrix);
}
// inset chrome color by BORDER_SIZE
// bottom line is a shadow
graphics.drawRoundRect(layoutBorderSize, layoutBorderSize,
unscaledWidth - (layoutBorderSize * 2),
unscaledHeight - (layoutBorderSize * 2),
layoutCornerEllipseSize, layoutCornerEllipseSize);
graphics.endFill();
}
/**
* 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;
}
}
}