blob: 2b5ff09ee68a4104fc30fda70954afd560367f6d [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.BlendMode;
import flash.display.DisplayObject;
import flash.display.GradientType;
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import mx.core.DPIClassification;
import mx.core.IVisualElement;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.utils.ColorUtil;
import spark.components.ToggleSwitch;
import spark.components.supportClasses.StyleableTextField;
import spark.core.SpriteVisualElement;
import spark.skins.mobile.supportClasses.MobileSkin;
import spark.skins.mobile120.assets.ToggleSwitch_contentShadow;
import spark.skins.mobile160.assets.ToggleSwitch_contentShadow;
import spark.skins.mobile240.assets.ToggleSwitch_contentShadow;
import spark.skins.mobile320.assets.ToggleSwitch_contentShadow;
import spark.skins.mobile480.assets.ToggleSwitch_contentShadow;
import spark.skins.mobile640.assets.ToggleSwitch_contentShadow;
use namespace mx_internal;
/**
* ActionScript-based skin for the ToggleSwitch control.
* The colors of the component can
* be customized using styles. This class is responsible for most of the
* graphics drawing, with some additional fxg assets.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*
* @see spark.components.ToggleSwitch
*/
public class ToggleSwitchSkin extends MobileSkin
{
//----------------------------------------------------------------------------------------------
//
// Constructor
//
//----------------------------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
**/
public function ToggleSwitchSkin()
{
super();
switch(applicationDPI)
{
case DPIClassification.DPI_640:
{
layoutThumbWidth = 94;
layoutThumbHeight = 56;
layoutStrokeWeight = 2;
layoutBorderSize = 2;
layoutTextShadowOffset = -2;
layoutInnerPadding = 14;
layoutOuterPadding = 22;
slidingContentOverlayClass = spark.skins.mobile320.assets.ToggleSwitch_contentShadow;
break;
}
case DPIClassification.DPI_480:
{
// Note provisional may need changes
layoutThumbWidth = 140;
layoutThumbHeight = 84;
layoutStrokeWeight = 2;
layoutBorderSize = 2;
layoutTextShadowOffset = -2;
layoutInnerPadding = 20;
layoutOuterPadding = 34;
slidingContentOverlayClass = spark.skins.mobile480.assets.ToggleSwitch_contentShadow;
break;
}
case DPIClassification.DPI_320:
{
layoutThumbWidth = 94;
layoutThumbHeight = 56;
layoutStrokeWeight = 2;
layoutBorderSize = 2;
layoutTextShadowOffset = -2;
layoutInnerPadding = 14;
layoutOuterPadding = 22;
slidingContentOverlayClass = spark.skins.mobile320.assets.ToggleSwitch_contentShadow;
break;
}
case DPIClassification.DPI_240:
{
layoutThumbWidth = 70;
layoutThumbHeight = 42;
layoutStrokeWeight = 2;
layoutBorderSize = 1;
layoutTextShadowOffset = -1;
layoutInnerPadding = 10;
layoutOuterPadding = 17;
slidingContentOverlayClass = spark.skins.mobile240.assets.ToggleSwitch_contentShadow;
break;
}
case DPIClassification.DPI_120:
{
layoutThumbWidth = 35;
layoutThumbHeight = 21;
layoutStrokeWeight = 2;
layoutBorderSize = 1;
layoutTextShadowOffset = -1;
layoutInnerPadding = 5;
layoutOuterPadding = 9;
slidingContentOverlayClass = spark.skins.mobile120.assets.ToggleSwitch_contentShadow;
break;
}
default:
{
layoutThumbWidth = 47;
layoutThumbHeight = 28;
layoutStrokeWeight = 1;
layoutBorderSize = 1;
layoutTextShadowOffset = -1;
layoutInnerPadding = 7;
layoutOuterPadding = 11;
slidingContentOverlayClass = spark.skins.mobile160.assets.ToggleSwitch_contentShadow;
break;
}
}
layoutCornerEllipseSize = layoutThumbHeight;
selectedLabel = resourceManager.getString("components","toggleSwitchSelectedLabel");
unselectedLabel = resourceManager.getString("components","toggleSwitchUnselectedLabel");
}
//----------------------------------------------------------------------------------------------
//
// Variables
//
//----------------------------------------------------------------------------------------------
/**
* The width to draw the thumb skin part.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutThumbWidth:Number;
/**
* The height to draw the thumb skin part.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutThumbHeight:Number;
/**
* The corner radius of the thumb and track.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutCornerEllipseSize:Number;
/**
* The stroke weight outlining the graphics of the skin.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutStrokeWeight:Number;
/**
* The size of the border surrounding the component.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutBorderSize:Number;
/**
* The padding between the labels and the thumb.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutInnerPadding:Number;
/**
* The padding between the labels and the edge of the track.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutOuterPadding:Number;
/**
* The offset between a label and its shadow.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
protected var layoutTextShadowOffset:Number;
/**
* The label for the selected side of the component.
* Exposed for styling purposes only.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
public var selectedLabelDisplay:LabelDisplayComponent;
/**
* The label for the unselected side of the component.
* Exposed for styling purposes only.
*
* @langversion 3.0
* @playerversion AIR 3
* @productversion Flex 4.6
*/
public var unselectedLabelDisplay:LabelDisplayComponent;
/**
* The content clipped by the track that slides to match the thumb's
* position.
* Contents include a background and the (un)selected labels.
* The sliding content is stacked, from back to front, as background,
* shadow, foreground.
*/
private var slidingContentBackground:SpriteVisualElement;
private var slidingContentForeground:UIComponent;
private var slidingContentOverlayClass:Class;
private var slidingContentOverlay:DisplayObject;
/**
* The contents inside the skin, not including the outline
* stroke
*/
private var contents:UIComponent;
/**
* The thumb erase overlay erases pixels behind the thumb. The thumb
* content contains the thumb graphics, and sits above the overlay.
*/
private var thumbEraseOverlay:Sprite;
private var thumbContent:Sprite;
//----------------------------------------------------------------------------------------------
//
// 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;
//----------------------------------------------------------------------------------------------
//
// Overridden properties
//
//----------------------------------------------------------------------------------------------
//----------------------------------
// currentState
//----------------------------------
/**
* @private
*/
override public function set currentState(value:String):void
{
var isDown:Boolean = currentState && currentState.indexOf("down") >=0;
super.currentState = value;
if (isDown != currentState.indexOf("down") >= 0)
{
invalidateDisplayList();
}
}
//----------------------------------------------------------------------------------------------
//
// Properties
//
//----------------------------------------------------------------------------------------------
//----------------------------------
// hostComponent
//----------------------------------
private var _hostComponent:ToggleSwitch;
/**
* @copy spark.skins.spark.ApplicationSkin#hostComponent
*/
public function get hostComponent():ToggleSwitch
{
return _hostComponent;
}
/**
* @private
*/
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;
}
//----------------------------------------------------------------------------------------------
//
// Overridden Methods
//
//----------------------------------------------------------------------------------------------
/**
* @private
* Redraw the graphics of the skin as necessary
*/
override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
{
super.drawBackground(unscaledWidth, unscaledHeight);
// calculate skin dimensions - outer stroke
var calculatedContentWidth:Number = Math.max(unscaledWidth - 2 * layoutBorderSize,
getElementPreferredWidth(thumb));
var calculatedContentHeight:Number = Math.max(unscaledHeight - 2 * layoutBorderSize,
getElementPreferredHeight(thumb));
drawSlidingContent(calculatedContentWidth, calculatedContentHeight);
drawTrack(calculatedContentWidth, calculatedContentHeight);
drawThumb(calculatedContentWidth, calculatedContentHeight);
drawMask(calculatedContentWidth, calculatedContentHeight);
// simulate outer stroke using a larger filled rounded rect
graphics.beginFill(0xffffff, 0.3);
graphics.drawRoundRect(0, (calculatedContentHeight - layoutThumbHeight) / 2,
calculatedContentWidth + 2 * layoutBorderSize,
layoutThumbHeight + 2 * layoutBorderSize,
layoutCornerEllipseSize + layoutBorderSize);
graphics.endFill();
}
/**
* @private
* Resize and reposition as necessary
*/
override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
{
super.layoutContents(unscaledWidth, unscaledHeight);
// calculate skin dimensions - outer stroke
var calculatedContentWidth:Number = Math.max(unscaledWidth - 2 * layoutBorderSize,
getElementPreferredWidth(thumb));
var calculatedContentHeight:Number = Math.max(unscaledHeight - 2 * layoutBorderSize,
getElementPreferredHeight(thumb));
setElementSize(contents, calculatedContentWidth, layoutThumbHeight);
setElementPosition(contents, layoutBorderSize,
layoutBorderSize + (calculatedContentHeight - layoutThumbHeight) / 2);
layoutTrack(calculatedContentWidth, layoutThumbHeight);
layoutThumb(calculatedContentWidth, layoutThumbHeight);
// Sliding content must be positioned after the track & thumb have been sized
layoutSlidingContent(calculatedContentWidth, layoutThumbHeight);
layoutMask(calculatedContentWidth, layoutThumbHeight);
}
/**
* @private
*/
override protected function measure():void
{
// The skin must be at least as large as the thumb + outer stroke
measuredMinWidth = layoutThumbWidth + 2 * layoutBorderSize;
measuredMinHeight = layoutThumbWidth + 2 * layoutBorderSize;
// The preferred size will display all label text
var labelWidth:Number = Math.max(getElementPreferredWidth(selectedLabelDisplay),
getElementPreferredWidth(unselectedLabelDisplay));
measuredWidth = layoutThumbWidth + labelWidth + layoutInnerPadding +
layoutOuterPadding + 2 * layoutBorderSize;
measuredHeight = layoutThumbHeight + 2 * layoutBorderSize;
}
/**
* @private
*/
override protected function commitCurrentState():void
{
if (currentState && currentState.indexOf("disabled") >= 0)
{
alpha = 0.5;
selectedLabelDisplay.showShadow(false);
unselectedLabelDisplay.showShadow(false);
}
else
{
alpha = 1.0;
selectedLabelDisplay.showShadow(true);
unselectedLabelDisplay.showShadow(true);
}
}
/**
* @private
*/
override protected function createChildren():void
{
super.createChildren();
contents = new UIComponent();
contents.blendMode = BlendMode.LAYER;
addChild(contents);
// SlidingContent: background, overlay, labels
slidingContentBackground = new SpriteVisualElement();
contents.addChild(slidingContentBackground);
slidingContentOverlay = new slidingContentOverlayClass();
contents.addChild(slidingContentOverlay);
slidingContentForeground = new UIComponent();
contents.addChild(slidingContentForeground);
selectedLabelDisplay = new LabelDisplayComponent();
selectedLabelDisplay.id = "selectedLabelDisplay";
selectedLabelDisplay.text = selectedLabel;
selectedLabelDisplay.shadowYOffset = layoutTextShadowOffset;
slidingContentForeground.addChild(selectedLabelDisplay);
unselectedLabelDisplay = new LabelDisplayComponent();
unselectedLabelDisplay.id = "unselectedLabelDisplay";
unselectedLabelDisplay.text = unselectedLabel;
unselectedLabelDisplay.shadowYOffset = layoutTextShadowOffset;
slidingContentForeground.addChild(unselectedLabelDisplay);
// Track
track = new SpriteVisualElement();
contents.addChild(SpriteVisualElement(track));
// Thumb
thumb = new SpriteVisualElement();
contents.addChild(SpriteVisualElement(thumb));
thumbEraseOverlay = new Sprite();
thumbEraseOverlay.blendMode = BlendMode.ERASE;
SpriteVisualElement(thumb).addChild(thumbEraseOverlay);
thumbContent = new Sprite();
SpriteVisualElement(thumb).addChild(thumbContent);
// Content clipping mask
var contentMask:Sprite = new SpriteVisualElement();
contents.mask = contentMask;
contents.addChild(contentMask);
}
//----------------------------------------------------------------------------------------------
//
// Methods
//
//----------------------------------------------------------------------------------------------
/**
* Draw the sliding content background
* SlidingContent's x origin matches the thumb's x origin, meaning some of
* the background is drawn to the left, and some to the right.
*/
private function drawSlidingContent(skinWidth:Number, skinHeight:Number):void
{
slidingContentBackground.graphics.clear();
// selected side of the sliding content
slidingContentBackground.graphics.beginFill(getStyle("accentColor"));
slidingContentBackground.graphics.drawRect(layoutThumbWidth - skinWidth, 0, skinWidth - layoutThumbWidth / 2,
layoutThumbHeight);
slidingContentBackground.graphics.endFill();
// unselected side of the sliding content
slidingContentBackground.graphics.beginFill(ColorUtil.adjustBrightness2(getStyle("chromeColor"), -25));
slidingContentBackground.graphics.drawRect(layoutThumbWidth / 2, 0, skinWidth - layoutThumbWidth / 2,
layoutThumbHeight);
slidingContentBackground.graphics.endFill();
}
/**
* Lay out SlidingContent and its children. Because we only need the x,y
* coordinate of SlidingContent, we can ignore its size.
* The origin of SlidingContent overlaps the origin of the thumb, and the
* positioning is handled by thumbPositionChanged_handler.
*/
private function layoutSlidingContent(skinWidth:Number, skinHeight:Number):void
{
var visibleTrackWidth:Number = skinWidth - layoutThumbWidth;
var labelWidth:Number = visibleTrackWidth - layoutInnerPadding - layoutOuterPadding;
setElementSize(selectedLabelDisplay, labelWidth, layoutThumbHeight);
setElementPosition(selectedLabelDisplay, -visibleTrackWidth + layoutOuterPadding, 0);
setElementSize(unselectedLabelDisplay, labelWidth, layoutThumbHeight);
setElementPosition(unselectedLabelDisplay, layoutThumbWidth + layoutInnerPadding, 0);
setElementSize(slidingContentOverlay, skinWidth, layoutThumbHeight);
setElementPosition(slidingContentOverlay, 0, (skinHeight - layoutThumbHeight) / 2);
moveSlidingContent();
}
/**
* Draw the track and its shadow
*/
private function drawTrack(skinWidth:Number, skinHeight:Number):void
{
var graphics:Graphics = SpriteVisualElement(track).graphics;
graphics.clear();
graphics.lineStyle(layoutStrokeWeight, 0, .3);
graphics.drawRoundRect(layoutStrokeWeight / 2, layoutStrokeWeight / 2,
skinWidth - layoutStrokeWeight,
(layoutThumbHeight - layoutStrokeWeight), (layoutCornerEllipseSize - layoutStrokeWeight / 2));
graphics.lineStyle();
}
/**
* Resize and reposition the track
*/
private function layoutTrack(skinWidth:Number, skinHeight:Number):void
{
setElementSize(track, skinWidth, layoutThumbHeight);
setElementPosition(track, 0, (skinHeight - layoutThumbHeight) / 2);
}
/**
* Draw the thumb. The thumb has an outer border, inner gradient, and
* inner highlight stroke.
*/
private function drawThumb(skinWidth:Number, skinHeight:Number):void
{
var graphics:Graphics = thumbContent.graphics;
var colors:Array = [];
var alphas:Array = [];
var ratios:Array = [];
var baseColor:Number = getStyle("chromeColor");
if (currentState && currentState.indexOf("down") >= 0)
baseColor = ColorUtil.adjustBrightness(baseColor, -60);
graphics.clear();
// Thumb outline
colors[0] = ColorUtil.adjustBrightness2(baseColor, -70);
colors[1] = ColorUtil.adjustBrightness2(baseColor, -55);
alphas[0] = 1;
alphas[1] = 1;
ratios[0] = 0;
ratios[1] = 255;
colorMatrix.createGradientBox(layoutThumbWidth, layoutThumbHeight, Math.PI / 2);
graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, colorMatrix);
graphics.drawRoundRect(0, 0, layoutThumbWidth, layoutThumbHeight, layoutCornerEllipseSize);
graphics.endFill();
// Base gradient fill, one stroke weight inside outline
colors[0] = ColorUtil.adjustBrightness2(baseColor, -30);
colors[1] = baseColor;
colors[2] = ColorUtil.adjustBrightness2(baseColor, 20);
alphas[2] = 1;
ratios[0] = 0;
ratios[1] = .7 * 255;
ratios[2] = 255;
colorMatrix.createGradientBox(layoutThumbWidth - layoutStrokeWeight * 2,
layoutThumbHeight - layoutStrokeWeight * 2, Math.PI / 2);
graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, colorMatrix);
graphics.drawRoundRect(layoutStrokeWeight, layoutStrokeWeight,
layoutThumbWidth - layoutStrokeWeight * 2,
layoutThumbHeight - layoutStrokeWeight * 2, layoutCornerEllipseSize - layoutStrokeWeight * 2);
graphics.endFill();
// Thumb highlight, one stroke weight inside outline
colors[0] = 0xffffff;
colors[1] = 0xffffff;
colors[2] = 0x0;
alphas[0] = .9;
alphas[1] = 0;
alphas[2] = .2;
ratios[0] = .33 * 255;
ratios[1] = .5 * 255;
ratios[2] = 255;
colorMatrix.createGradientBox(layoutThumbWidth - layoutStrokeWeight * 3,
layoutThumbHeight - layoutStrokeWeight * 3, Math.PI / 2);
graphics.lineStyle(layoutStrokeWeight);
graphics.lineGradientStyle(GradientType.LINEAR, colors, alphas, ratios, colorMatrix);
graphics.drawRoundRect(layoutStrokeWeight * 1.5, layoutStrokeWeight * 1.5,
layoutThumbWidth - layoutStrokeWeight * 3, layoutThumbHeight - layoutStrokeWeight * 3,
layoutCornerEllipseSize - layoutStrokeWeight * 3);
graphics.lineStyle();
// Redraw the erase overlay as a silhouette of the thumb
thumbEraseOverlay.graphics.clear();
thumbEraseOverlay.graphics.beginFill(0);
thumbEraseOverlay.graphics.drawRoundRect(0, 0, layoutThumbWidth, layoutThumbHeight, layoutCornerEllipseSize);
thumbEraseOverlay.graphics.endFill();
}
/**
* Resize the thumb. Its position is handled by the component.
*/
private function layoutThumb(skinWidth:Number, skinHeight:Number):void
{
setElementSize(thumb, layoutThumbWidth, layoutThumbHeight);
}
/**
* Draw the clipping mask for the component. This is roughly the
* same as the track area.
*/
private function drawMask(skinWidth:Number, skinHeight:Number):void
{
var graphics:Graphics = SpriteVisualElement(contents.mask).graphics;
graphics.clear();
graphics.beginFill(0x0);
graphics.drawRoundRect(0, 0, skinWidth, layoutThumbHeight, layoutCornerEllipseSize);
graphics.endFill();
}
/**
* Resize and reposition the clipping mask
*/
private function layoutMask(skinWidth:Number, skinHeight:Number):void
{
setElementSize(contents.mask, skinWidth, layoutThumbHeight);
setElementPosition(contents.mask, 0, (skinHeight - layoutThumbHeight) / 2);
}
/**
* Move the sliding content to line up with thumbPosition.
* This version assumes the thumb and track share the same coordinate system.
*/
private function moveSlidingContent():void
{
if (!hostComponent)
return;
var x:Number = (track.getLayoutBoundsWidth() - thumb.getLayoutBoundsWidth()) *
hostComponent.thumbPosition + track.getLayoutBoundsX();
var y:Number = thumb.getLayoutBoundsY();
setElementPosition(slidingContentBackground, x, y);
setElementPosition(slidingContentForeground, x, y);
}
//----------------------------------------------------------------------------------------------
//
// Event handlers
//
//----------------------------------------------------------------------------------------------
/**
* When the thumb position changes, reposition the sliding content.
*/
private function thumbPositionChanged_handler(event:Event):void
{
moveSlidingContent();
}
}
}
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;
}
}