You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by bi...@apache.org on 2014/11/04 20:16:08 UTC
[18/22] git commit: [flex-examples] [refs/heads/develop] - added in
Android Skins
added in Android Skins
Signed-off-by: OmPrakash Muppirala <bi...@gmail.com>
Project: http://git-wip-us.apache.org/repos/asf/flex-examples/repo
Commit: http://git-wip-us.apache.org/repos/asf/flex-examples/commit/539852e9
Tree: http://git-wip-us.apache.org/repos/asf/flex-examples/tree/539852e9
Diff: http://git-wip-us.apache.org/repos/asf/flex-examples/diff/539852e9
Branch: refs/heads/develop
Commit: 539852e984111a284dfda239de6f2d26e42b2e5e
Parents: 1f0cce9
Author: nasha001 <na...@DM-DT-NASH.hartford.gov>
Authored: Tue Nov 4 13:00:50 2014 -0500
Committer: OmPrakash Muppirala <bi...@gmail.com>
Committed: Tue Nov 4 11:07:41 2014 -0800
----------------------------------------------------------------------
tourdeflexmobile/slideoff.png | Bin 15894 -> 0 bytes
.../src/spark/skins/android4/ActionBarSkin.as | 725 +++++++++++++++
.../skins/android4/ButtonBarFirstButtonSkin.as | 93 ++
.../skins/android4/ButtonBarMiddleButtonSkin.as | 95 ++
.../src/spark/skins/android4/ButtonBarSkin.as | 166 ++++
.../src/spark/skins/android4/ButtonSkin.as | 397 +++++++++
.../src/spark/skins/android4/CalloutSkin.as | 825 +++++++++++++++++
.../src/spark/skins/android4/CheckBoxSkin.as | 268 ++++++
.../src/spark/skins/android4/DateSpinnerSkin.as | 153 ++++
.../src/spark/skins/android4/HScrollBarSkin.as | 205 +++++
.../spark/skins/android4/HScrollBarThumbSkin.as | 169 ++++
.../src/spark/skins/android4/HSliderSkin.as | 293 ++++++
.../spark/skins/android4/HSliderThumbSkin.as | 333 +++++++
.../spark/skins/android4/HSliderTrackSkin.as | 227 +++++
.../src/spark/skins/android4/ListSkin.as | 204 +++++
.../android4/MobileGridHeaderButtonBarSkin.as | 90 ++
.../src/spark/skins/android4/MobileGridSkin.as | 159 ++++
.../src/spark/skins/android4/RadioButtonSkin.as | 253 ++++++
.../android4/ScrollingStageTextAreaSkin.as | 53 ++
.../android4/ScrollingStageTextInputSkin.as | 54 ++
.../skins/android4/SpinnerListContainerSkin.as | 327 +++++++
.../skins/android4/SpinnerListScrollerSkin.mxml | 94 ++
.../src/spark/skins/android4/SpinnerListSkin.as | 293 ++++++
.../skins/android4/SplitViewNavigatorSkin.as | 157 ++++
.../spark/skins/android4/StageTextAreaSkin.as | 185 ++++
.../spark/skins/android4/StageTextInputSkin.as | 130 +++
.../android4/TabbedViewNavigatorTabBarSkin.as | 122 +++
.../skins/android4/TextAreaHScrollBarSkin.as | 105 +++
.../android4/TextAreaHScrollBarThumbSkin.as | 116 +++
.../src/spark/skins/android4/TextAreaSkin.as | 892 +++++++++++++++++++
.../skins/android4/TextAreaVScrollBarSkin.as | 105 +++
.../android4/TextAreaVScrollBarThumbSkin.as | 117 +++
.../src/spark/skins/android4/TextInputSkin.as | 375 ++++++++
.../spark/skins/android4/ToggleSwitchSkin.as | 506 +++++++++++
.../android4/TransparentActionButtonSkin.as | 108 +++
.../android4/TransparentNavigationButtonSkin.as | 109 +++
.../src/spark/skins/android4/VScrollBarSkin.as | 207 +++++
.../spark/skins/android4/VScrollBarThumbSkin.as | 178 ++++
.../spark/skins/android4/ViewMenuItemSkin.as | 238 +++++
.../src/spark/skins/android4/ViewMenuSkin.mxml | 184 ++++
.../android4/assets/ActionBarBackground.fxg | 55 ++
.../skins/android4/assets/BusyIndicator.fxg | 64 ++
.../assets/ButtonBarFirstButton_down.fxg | 34 +
.../ButtonBarFirstButton_selectedDown.fxg | 39 +
.../assets/ButtonBarFirstButton_selectedUp.fxg | 34 +
.../android4/assets/ButtonBarFirstButton_up.fxg | 29 +
.../assets/ButtonBarMiddleButton_down.fxg | 70 ++
.../ButtonBarMiddleButton_selectedDown.fxg | 75 ++
.../assets/ButtonBarMiddleButton_selectedUp.fxg | 70 ++
.../assets/ButtonBarMiddleButton_up.fxg | 65 ++
.../spark/skins/android4/assets/Button_down.fxg | 73 ++
.../spark/skins/android4/assets/Button_up.fxg | 60 ++
.../assets/CalloutContentBackground.fxg | 51 ++
.../skins/android4/assets/CheckBox_down.fxg | 34 +
.../android4/assets/CheckBox_downSelected.fxg | 35 +
.../assets/CheckBox_downSymbolSelected.fxg | 29 +
.../spark/skins/android4/assets/CheckBox_up.fxg | 31 +
.../android4/assets/CheckBox_upSelected.fxg | 29 +
.../assets/CheckBox_upSymbolSelected.fxg | 33 +
.../android4/assets/HSliderThumb_normal.fxg | 34 +
.../android4/assets/HSliderThumb_pressed.fxg | 39 +
.../skins/android4/assets/HSliderTrack.fxg | 29 +
.../android4/assets/HSliderTrack_filled.fxg | 29 +
.../skins/android4/assets/RadioButton_down.fxg | 34 +
.../assets/RadioButton_downSymbolSelected.fxg | 29 +
.../skins/android4/assets/RadioButton_up.fxg | 29 +
.../assets/RadioButton_upSymbolSelected.fxg | 36 +
.../assets/SpinnerListContainerBackground.fxg | 48 +
.../SpinnerListContainerSelectionIndicator.fxg | 45 +
.../assets/SpinnerListContainerShadow.fxg | 40 +
.../skins/android4/assets/TextInput_border.fxg | 34 +
.../assets/TextInput_border_Rectangle.fxg | 28 +
.../assets/TextInput_border_Rectangle_focus.fxg | 28 +
.../android4/assets/TextInput_border_focus.fxg | 34 +
.../android4/assets/ToggleSwitchBackground.fxg | 29 +
.../android4/assets/ToggleSwitchThumb_off.fxg | 40 +
.../android4/assets/ToggleSwitchThumb_on.fxg | 40 +
.../assets/TransparentActionButton_down.fxg | 69 ++
.../assets/TransparentActionButton_up.fxg | 59 ++
.../assets/TransparentNavigationButton_down.fxg | 69 ++
.../assets/TransparentNavigationButton_up.fxg | 59 ++
.../skins/android4/assets/ViewMenuItem_down.fxg | 36 +
.../android4/assets/ViewMenuItem_showsCaret.fxg | 36 +
.../skins/android4/assets/ViewMenuItem_up.fxg | 35 +
.../skins/android4/assets/fonts/Roboto-Bold.ttf | Bin 0 -> 84924 bytes
.../android4/assets/fonts/Roboto-Regular.ttf | Bin 0 -> 84564 bytes
.../android4/supportClasses/CalloutArrow.as | 457 ++++++++++
.../supportClasses/StageTextSkinBase.as | 402 +++++++++
.../android4/supportClasses/TextSkinBase.as | 213 +++++
89 files changed, 12280 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/slideoff.png
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/slideoff.png b/tourdeflexmobile/slideoff.png
deleted file mode 100644
index 538d0f8..0000000
Binary files a/tourdeflexmobile/slideoff.png and /dev/null differ
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/ActionBarSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/ActionBarSkin.as b/tourdeflexmobile/src/spark/skins/android4/ActionBarSkin.as
new file mode 100644
index 0000000..f1ef220
--- /dev/null
+++ b/tourdeflexmobile/src/spark/skins/android4/ActionBarSkin.as
@@ -0,0 +1,725 @@
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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;
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/ButtonBarFirstButtonSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/ButtonBarFirstButtonSkin.as b/tourdeflexmobile/src/spark/skins/android4/ButtonBarFirstButtonSkin.as
new file mode 100644
index 0000000..4b8cbba
--- /dev/null
+++ b/tourdeflexmobile/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
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/ButtonBarMiddleButtonSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/ButtonBarMiddleButtonSkin.as b/tourdeflexmobile/src/spark/skins/android4/ButtonBarMiddleButtonSkin.as
new file mode 100644
index 0000000..c6206d0
--- /dev/null
+++ b/tourdeflexmobile/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
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/ButtonBarSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/ButtonBarSkin.as b/tourdeflexmobile/src/spark/skins/android4/ButtonBarSkin.as
new file mode 100644
index 0000000..4b194fd
--- /dev/null
+++ b/tourdeflexmobile/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
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/ButtonSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/ButtonSkin.as b/tourdeflexmobile/src/spark/skins/android4/ButtonSkin.as
new file mode 100644
index 0000000..43fb108
--- /dev/null
+++ b/tourdeflexmobile/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
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/CalloutSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/CalloutSkin.as b/tourdeflexmobile/src/spark/skins/android4/CalloutSkin.as
new file mode 100644
index 0000000..22f04f5
--- /dev/null
+++ b/tourdeflexmobile/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.
+ *
+ * <p>The <code>contentGroup</code> lies above a <code>backgroundColor</code> fill
+ * which frames the <code>contentGroup</code>. The position and size of the frame
+ * adjust based on the host component <code>arrowDirection</code>, leaving
+ * space for the <code>arrow</code> to appear on the outside edge of the
+ * frame.</p>
+ *
+ * <p>The <code>arrow</code> skin part is not positioned by the skin. Instead,
+ * the Callout component positions the arrow relative to the owner in
+ * <code>updateSkinDisplayList()</code>. This method assumes that Callout skin
+ * and the <code>arrow</code> use the same coordinate space.</p>
+ *
+ * @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 <code>backgroundColor</code> frame.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var dropShadowVisible:Boolean = true;
+
+ /**
+ * Enables a vertical linear gradient in the <code>backgroundColor</code> 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 <code>contentBackgroundColor</code> 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
+ * <code>contentGroup</code>. The instance of this class is sized to match the
+ * <code>contentGroup</code>.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var contentBackgroundInsetClass:Class;
+
+ /**
+ * Corner radius of the <code>backgroundColor</code> "frame".
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var backgroundCornerRadius:Number;
+
+ /**
+ * The thickness of the <code>backgroundColor</code> "frame" that surrounds the
+ * <code>contentGroup</code>.
+ *
+ * @langversion 3.0
+ * @playerversion AIR 3
+ * @productversion Flex 4.6
+ */
+ protected var frameThickness:Number;
+
+ /**
+ * Color of the border stroke around the <code>backgroundColor</code> "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 <code>backgroundColor</code>
+ * "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));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/flex-examples/blob/539852e9/tourdeflexmobile/src/spark/skins/android4/CheckBoxSkin.as
----------------------------------------------------------------------
diff --git a/tourdeflexmobile/src/spark/skins/android4/CheckBoxSkin.as b/tourdeflexmobile/src/spark/skins/android4/CheckBoxSkin.as
new file mode 100644
index 0000000..f091205
--- /dev/null
+++ b/tourdeflexmobile/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 <code>chromeColor</code> 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