jesterxl

Flex 4.6 mobile ActionBar skin

Dec 30th, 2011
850
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. //  ADOBE SYSTEMS INCORPORATED
  4. //  Copyright 2010 Adobe Systems Incorporated
  5. //  All Rights Reserved.
  6. //
  7. //  NOTICE: Adobe permits you to use, modify, and distribute this file
  8. //  in accordance with the terms of the license agreement accompanying it.
  9. //
  10. ////////////////////////////////////////////////////////////////////////////////
  11.  
  12. package spark.skins.ios
  13. {
  14. import flash.display.CapsStyle;
  15. import flash.display.GradientType;
  16. import flash.display.JointStyle;
  17. import flash.display.LineScaleMode;
  18. import flash.events.Event;
  19. import flash.text.TextFormatAlign;
  20.  
  21. import mx.core.DPIClassification;
  22. import mx.core.mx_internal;
  23. import mx.utils.ColorUtil;
  24.  
  25. import spark.components.ActionBar;
  26. import spark.components.Group;
  27. import spark.components.supportClasses.StyleableTextField;
  28. import spark.core.SpriteVisualElement;
  29. import spark.layouts.HorizontalAlign;
  30. import spark.layouts.HorizontalLayout;
  31. import spark.layouts.VerticalAlign;
  32. import spark.skins.mobile.ActionBarSkin;
  33. import spark.skins.mobile.supportClasses.MobileSkin;
  34.  
  35. use namespace mx_internal;
  36.  
  37. /**
  38.  *  The default skin class for the Spark ActionBar component in mobile
  39.  *  applications.
  40.  *  
  41.  *  @see spark.components.ActionBar
  42.  *  @see spark.skins.mobile.NavigationButtonSkin
  43.  *  @see spark.skins.mobile.NavigationBackButtonSkin
  44.  *  @see spark.skins.mobile.ActionButtonSkin
  45.  *  @see spark.skins.mobile.ActionRoundedButtonSkin
  46.  *  
  47.  *  @langversion 3.0
  48.  *  @playerversion Flash 10
  49.  *  @playerversion AIR 2.5
  50.  *  @productversion Flex 4.5
  51.  */
  52. public class ActionBarSkin extends MobileSkin
  53. {
  54.    
  55.     //--------------------------------------------------------------------------
  56.     //
  57.     //  Constructor
  58.     //
  59.     //--------------------------------------------------------------------------
  60.    
  61.     /**
  62.      *  Constructor.
  63.      *  
  64.      *  @langversion 3.0
  65.      *  @playerversion Flash 10
  66.      *  @playerversion AIR 2.5
  67.      *  @productversion Flex 4.5
  68.      */
  69.     public function ActionBarSkin()
  70.     {
  71.         super();
  72.        
  73.         switch (applicationDPI)
  74.         {
  75.             case DPIClassification.DPI_320:
  76.             {
  77.                 layoutContentGroupHeight = 88;
  78.                 layoutTitleGroupHorizontalPadding = 26;
  79.                 borderWeight = 2;
  80.                
  81.                 break;
  82.             }
  83.             case DPIClassification.DPI_240:
  84.             {
  85.                 layoutContentGroupHeight = 66;
  86.                 layoutTitleGroupHorizontalPadding = 20;
  87.                 borderWeight = 1;
  88.                
  89.                 break;
  90.             }
  91.             default:
  92.             {
  93.                 // default DPI_160
  94.                 layoutContentGroupHeight = 44;
  95.                 layoutTitleGroupHorizontalPadding = 13;
  96.                 borderWeight = 1;
  97.                
  98.                 break;
  99.             }
  100.         }
  101.     }
  102.    
  103.     //--------------------------------------------------------------------------
  104.     //
  105.     //  Layout variables
  106.     //
  107.     //--------------------------------------------------------------------------
  108.    
  109.     protected var layoutContentGroupHeight:uint;
  110.    
  111.     protected var layoutTitleGroupHorizontalPadding:uint;
  112.    
  113.     protected var borderWeight:uint;
  114.    
  115.     //--------------------------------------------------------------------------
  116.     //
  117.     //  Variables
  118.     //
  119.     //--------------------------------------------------------------------------
  120.    
  121.     /**
  122.      *  @copy spark.skins.spark.ApplicationSkin#hostComponent
  123.      */
  124.     public var hostComponent:ActionBar;
  125.    
  126.     private var _navigationVisible:Boolean = false;
  127.    
  128.     private var _titleContentVisible:Boolean = false;
  129.    
  130.     private var _actionVisible:Boolean = false;
  131.    
  132.     private var colorized:Boolean = false;
  133.    
  134.     //--------------------------------------------------------------------------
  135.     //
  136.     //  Skin parts
  137.     //
  138.     //--------------------------------------------------------------------------
  139.    
  140.     public var navigationGroup:Group;
  141.    
  142.     public var titleGroup:Group;
  143.    
  144.     public var actionGroup:Group;
  145.    
  146.     /**
  147.      *  Wraps a StyleableTextField in a UIComponent to be compatible with
  148.      *  ViewTransition effects.
  149.      */
  150.     public var titleDisplay:TitleDisplayComponent;
  151.    
  152.     //--------------------------------------------------------------------------
  153.     //
  154.     //  Overridden methods
  155.     //
  156.     //--------------------------------------------------------------------------
  157.    
  158.     /**
  159.      *  @private
  160.      */
  161.     override protected function createChildren():void
  162.     {
  163.         navigationGroup = new Group();
  164.         var hLayout:HorizontalLayout = new HorizontalLayout();
  165.         hLayout.horizontalAlign = HorizontalAlign.LEFT;
  166.         hLayout.verticalAlign = VerticalAlign.MIDDLE;
  167.         hLayout.gap = 0;
  168.         hLayout.paddingLeft = hLayout.paddingTop = hLayout.paddingRight =
  169.             hLayout.paddingBottom = 0;
  170.         navigationGroup.layout = hLayout;
  171.         navigationGroup.id = "navigationGroup";
  172.        
  173.         titleGroup = new Group();
  174.         hLayout = new HorizontalLayout();
  175.         hLayout.horizontalAlign = HorizontalAlign.LEFT;
  176.         hLayout.verticalAlign = VerticalAlign.MIDDLE;
  177.         hLayout.gap = 0;
  178.         hLayout.paddingLeft = hLayout.paddingRight = layoutTitleGroupHorizontalPadding;
  179.         hLayout.paddingTop = hLayout.paddingBottom = 0;
  180.         titleGroup.layout = hLayout;
  181.         titleGroup.id = "titleGroup";
  182.        
  183.         actionGroup = new Group();
  184.         hLayout = new HorizontalLayout();
  185.         hLayout.horizontalAlign = HorizontalAlign.RIGHT;
  186.         hLayout.verticalAlign = VerticalAlign.MIDDLE;
  187.         hLayout.gap = 0;
  188.         hLayout.paddingLeft = hLayout.paddingTop = hLayout.paddingRight =
  189.             hLayout.paddingBottom = 0;
  190.         actionGroup.layout = hLayout;
  191.         actionGroup.id = "actionGroup";
  192.        
  193.         titleDisplay = new TitleDisplayComponent();
  194.         titleDisplay.id = "titleDisplay";
  195.        
  196.         addChild(navigationGroup);
  197.         addChild(titleGroup);
  198.         addChild(actionGroup);
  199.         addChild(titleDisplay);
  200.     }
  201.    
  202.     /**
  203.      *  @private
  204.      */
  205.     override protected function measure():void
  206.     {
  207.         var titleWidth:Number = 0;
  208.         var titleHeight:Number = 0;
  209.        
  210.         if (_titleContentVisible)
  211.         {
  212.             titleWidth = titleGroup.getPreferredBoundsWidth();
  213.             titleHeight = titleGroup.getPreferredBoundsHeight();
  214.         }
  215.         else
  216.         {
  217.             // use titleLayout for paddingLeft and paddingRight
  218.             var layoutObject:Object = hostComponent.titleLayout;
  219.             titleWidth = ((layoutObject.paddingLeft) ? Number(layoutObject.paddingLeft) : 0)
  220.                 + ((layoutObject.paddingRight) ? Number(layoutObject.paddingRight) : 0)
  221.                 + titleDisplay.getPreferredBoundsWidth();
  222.            
  223.             titleHeight = titleDisplay.getPreferredBoundsHeight();
  224.         }
  225.        
  226.         measuredWidth =
  227.             getStyle("paddingLeft")
  228.             + navigationGroup.getPreferredBoundsWidth()
  229.             + titleWidth
  230.             + actionGroup.getPreferredBoundsWidth()
  231.             + getStyle("paddingRight");
  232.        
  233.         // measuredHeight is contentGroupHeight, 2x border on top and bottom
  234.         measuredHeight =
  235.             getStyle("paddingTop")
  236.             + Math.max(layoutContentGroupHeight,
  237.                 navigationGroup.getPreferredBoundsHeight(),
  238.                 actionGroup.getPreferredBoundsHeight(),
  239.                 titleHeight)
  240.             + getStyle("paddingBottom");
  241.     }
  242.    
  243.     /**
  244.      *  @private
  245.      */
  246.     override protected function commitCurrentState():void
  247.     {
  248.         super.commitCurrentState();
  249.        
  250.         _titleContentVisible = currentState.indexOf("titleContent") >= 0;
  251.         _navigationVisible = currentState.indexOf("Navigation") >= 0;
  252.         _actionVisible = currentState.indexOf("Action") >= 0;
  253.        
  254.         invalidateSize();
  255.         invalidateDisplayList();
  256.     }
  257.    
  258.     /**
  259.      *  @private
  260.      */
  261.     override public function styleChanged(styleProp:String):void
  262.     {
  263.         super.styleChanged(styleProp);
  264.        
  265.         if (styleProp == "textAlign")
  266.         {
  267.             var titleAlign:String = getStyle("textAlign");
  268.            
  269.             if (titleAlign == "center")
  270.             {
  271.                 // If the title align is set to center, the alignment is set to LEFT
  272.                 // so that the skin can manually center the component in layoutContents
  273.                 titleDisplay.setStyle("textAlign", TextFormatAlign.LEFT);
  274.             }
  275.             else
  276.             {
  277.                 titleDisplay.setStyle("textAlign", titleAlign);
  278.             }
  279.         }
  280.     }
  281.    
  282.     /**
  283.      *  @private
  284.      */
  285.     override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
  286.     {
  287.         super.layoutContents(unscaledWidth, unscaledHeight);
  288.        
  289.         var navigationGroupWidth:Number = 0;
  290.        
  291.         var paddingLeft:Number   = getStyle("paddingLeft");
  292.         var paddingRight:Number  = getStyle("paddingRight");
  293.         var paddingTop:Number    = getStyle("paddingTop");
  294.         var paddingBottom:Number = getStyle("paddingBottom");
  295.        
  296.         var titleCompX:Number = paddingLeft;
  297.         var titleCompWidth:Number = 0;
  298.         var titleHeight:Number = 0;
  299.         var titleCompY:Number = 0;
  300.        
  301.         var actionGroupX:Number = unscaledWidth;
  302.         var actionGroupWidth:Number = 0;
  303.        
  304.         // remove top and bottom padding from content group height
  305.         var contentGroupsHeight:Number = Math.max(0, unscaledHeight - paddingTop - paddingBottom);
  306.        
  307.         // position groups, overlap of navigation and action groups is allowed
  308.         // when overlap occurs, titleDisplay/titleGroup is not visible
  309.         if (_navigationVisible)
  310.         {
  311.             navigationGroupWidth = navigationGroup.getPreferredBoundsWidth();
  312.             titleCompX += navigationGroupWidth;
  313.            
  314.             setElementSize(navigationGroup, navigationGroupWidth, contentGroupsHeight);
  315.             setElementPosition(navigationGroup, paddingLeft, paddingTop);
  316.         }
  317.        
  318.         if (_actionVisible)
  319.         {
  320.             // actionGroup x position can be negative
  321.             actionGroupWidth = actionGroup.getPreferredBoundsWidth();
  322.             actionGroupX = unscaledWidth - actionGroupWidth - paddingRight;
  323.            
  324.             setElementSize(actionGroup, actionGroupWidth, contentGroupsHeight);
  325.             setElementPosition(actionGroup, actionGroupX, paddingTop);
  326.         }
  327.        
  328.         // titleGroup or titleDisplay is given remaining width after navigation
  329.         // and action groups preferred widths
  330.         titleCompWidth = unscaledWidth - navigationGroupWidth - actionGroupWidth
  331.             - paddingLeft - paddingRight;
  332.        
  333.         if (titleCompWidth <= 0)
  334.         {
  335.             titleDisplay.visible = false;
  336.             titleGroup.visible = false;
  337.         }
  338.         else if (_titleContentVisible)
  339.         {
  340.             titleDisplay.visible = false;
  341.             titleGroup.visible = true;
  342.            
  343.             // use titleGroup for titleContent
  344.             setElementSize(titleGroup, titleCompWidth, contentGroupsHeight);
  345.             setElementPosition(titleGroup, titleCompX, paddingTop);
  346.         }
  347.         else
  348.         {
  349.             // use titleDisplay for title text label
  350.             titleGroup.visible = false;
  351.            
  352.             // use titleLayout for paddingLeft and paddingRight
  353.             var layoutObject:Object = hostComponent.titleLayout;
  354.             var titlePaddingLeft:Number = (layoutObject.paddingLeft) ? Number(layoutObject.paddingLeft) : 0;
  355.             var titlePaddingRight:Number = (layoutObject.paddingRight) ? Number(layoutObject.paddingRight) : 0;
  356.            
  357.             titleHeight = titleDisplay.getExplicitOrMeasuredHeight();
  358.             titleCompY = Math.round((contentGroupsHeight - titleHeight)/2) + paddingTop;
  359.            
  360.             // align titleDisplay to the absolute center
  361.             var titleAlign:String = getStyle("titleAlign");
  362.            
  363.             // check for available width after padding
  364.             if ((titleCompWidth - titlePaddingLeft - titlePaddingRight) <= 0)
  365.             {
  366.                 titleCompX = 0;
  367.                 titleCompWidth = 0;
  368.             }
  369.             else if (titleAlign == "center")
  370.             {
  371.                 // use LEFT instead of CENTER
  372.                 titleCompWidth = titleDisplay.getExplicitOrMeasuredWidth();
  373.                
  374.                 // use x position of titleDisplay to implement CENTER
  375.                 titleCompX = Math.round((unscaledWidth - titleCompWidth) / 2);
  376.                
  377.                 var navigationOverlap:Number = navigationGroupWidth + titlePaddingLeft - titleCompX;
  378.                 var actionOverlap:Number = (titleCompX + titleCompWidth + titlePaddingRight) - actionGroupX;
  379.                
  380.                 // shrink and/or move titleDisplay width if there is any
  381.                 // overlap after centering
  382.                 if ((navigationOverlap > 0) && (actionOverlap > 0))
  383.                 {
  384.                     // remaining width
  385.                     titleCompX = navigationGroupWidth + titlePaddingLeft;
  386.                     titleCompWidth = unscaledWidth - navigationGroupWidth - actionGroupWidth - titlePaddingLeft - titlePaddingRight;
  387.                 }
  388.                 else if ((navigationOverlap > 0) || (actionOverlap > 0))
  389.                 {
  390.                     if (navigationOverlap > 0)
  391.                     {
  392.                         // nudge to the right
  393.                         titleCompX += navigationOverlap;
  394.                     }
  395.                     else if (actionOverlap > 0)
  396.                     {
  397.                         // nudge to the left
  398.                         titleCompX -= actionOverlap;
  399.                        
  400.                         // force left padding
  401.                         if (titleCompX < (navigationGroupWidth + titlePaddingLeft))
  402.                             titleCompX = navigationGroupWidth + titlePaddingLeft;
  403.                     }
  404.                    
  405.                     // recompute action overlap and force right padding
  406.                     actionOverlap = (titleCompX + titleCompWidth + titlePaddingRight) - actionGroupX;
  407.                    
  408.                     if (actionOverlap > 0)
  409.                         titleCompWidth -= actionOverlap;
  410.                 }
  411.             }
  412.             else
  413.             {
  414.                 // implement padding by adjusting width and position
  415.                 titleCompX += titlePaddingLeft;
  416.                 titleCompWidth = titleCompWidth - titlePaddingLeft - titlePaddingRight;
  417.             }
  418.            
  419.             // check for negative width
  420.             titleCompWidth = (titleCompWidth < 0) ? 0 : titleCompWidth;
  421.            
  422.             setElementSize(titleDisplay, titleCompWidth, titleDisplay.realTextHeight);
  423.             setElementPosition(titleDisplay, titleCompX, titleCompY);
  424.            
  425.             titleDisplay.visible = true;
  426.         }
  427.     }
  428.    
  429.     override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
  430.     {
  431.         super.drawBackground(unscaledWidth, unscaledHeight);
  432.        
  433.         var chromeColor:uint = getStyle("chromeColor");
  434.         var backgroundAlphaValue:Number = getStyle("backgroundAlpha");
  435.         var colors:Array = [];
  436.        
  437.         // apply alpha to chromeColor fill only
  438.         var backgroundAlphas:Array = [backgroundAlphaValue, backgroundAlphaValue, backgroundAlphaValue, backgroundAlphaValue];
  439.        
  440.         // exclude top and bottom 1px borders
  441.         colorMatrix.createGradientBox(unscaledWidth, unscaledHeight, Math.PI / 2, 0, 0);
  442.        
  443.         colors[0] = ColorUtil.adjustBrightness2(chromeColor, 40);
  444.         colors[1] = ColorUtil.adjustBrightness2(chromeColor, 20);
  445.         colors[2] = chromeColor;
  446.         colors[3] = chromeColor;
  447.        
  448.         // glossy fill
  449.         graphics.beginGradientFill(GradientType.LINEAR, colors, backgroundAlphas, ThemeConstants.CHROME_COLOR_RATIOS, colorMatrix);
  450.         graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
  451.         graphics.endFill();
  452.        
  453.         // top border light
  454.         var borderInset:uint = borderWeight / 2;
  455.         graphics.lineStyle(borderWeight, 0xFFFFFF, 0.3, false, LineScaleMode.NORMAL, CapsStyle.NONE, JointStyle.MITER);
  456.         graphics.moveTo(0, borderInset);
  457.         graphics.lineTo(unscaledWidth, borderInset);
  458.        
  459.         // bottom border dark
  460.         graphics.lineStyle(borderWeight, 0, 0.6, false, LineScaleMode.NORMAL, CapsStyle.NONE, JointStyle.MITER);
  461.         graphics.moveTo(0, unscaledHeight - borderInset);
  462.         graphics.lineTo(unscaledWidth, unscaledHeight - borderInset)
  463.     }
  464.    
  465. }
  466. }
  467. import flash.events.Event;
  468.  
  469. import mx.core.UIComponent;
  470. import mx.core.mx_internal;
  471. import mx.events.FlexEvent;
  472.  
  473. import spark.components.supportClasses.StyleableTextField;
  474. import spark.core.IDisplayText;
  475.  
  476. use namespace mx_internal;
  477.  
  478. /**
  479.  *  @private
  480.  *  Component that holds StyleableTextFields to produce a drop shadow effect.
  481.  *  Combines label and shadow into a single component to allow transitions to
  482.  *  target them both.
  483.  */
  484. class TitleDisplayComponent extends UIComponent implements IDisplayText
  485. {
  486.     private var titleDisplay:StyleableTextField;
  487.     private var titleDisplayShadow:StyleableTextField;
  488.     private var title:String;
  489.     private var titleChanged:Boolean;
  490.     private var _realTextHeight:Number;
  491.    
  492.     public function TitleDisplayComponent()
  493.     {
  494.         super();
  495.         title = "";
  496.     }
  497.    
  498.     override public function get baselinePosition():Number
  499.     {
  500.         return titleDisplay.baselinePosition;
  501.     }
  502.    
  503.     /**
  504.      *  @private
  505.      */
  506.     override protected function createChildren():void
  507.     {
  508.         super.createChildren();
  509.        
  510.         titleDisplay = StyleableTextField(createInFontContext(StyleableTextField));
  511.         titleDisplay.styleName = this;
  512.         titleDisplay.editable = false;
  513.         titleDisplay.selectable = false;
  514.         titleDisplay.multiline = false;
  515.         titleDisplay.wordWrap = false;
  516.         titleDisplay.addEventListener(FlexEvent.VALUE_COMMIT,
  517.             titleDisplay_valueCommitHandler);
  518.        
  519.         titleDisplayShadow =
  520.             StyleableTextField(createInFontContext(StyleableTextField));
  521.         titleDisplayShadow.styleName = this;
  522.         titleDisplayShadow.colorName = "textShadowColor";
  523.         titleDisplayShadow.editable = false;
  524.         titleDisplayShadow.selectable = false;
  525.         titleDisplayShadow.multiline = false;
  526.         titleDisplayShadow.wordWrap = false;
  527.        
  528.         addChild(titleDisplayShadow);
  529.         addChild(titleDisplay);
  530.     }
  531.    
  532.     /**
  533.      *  @private
  534.      */
  535.     override protected function commitProperties():void
  536.     {
  537.         super.commitProperties();
  538.        
  539.         if (titleChanged)
  540.         {
  541.             titleDisplay.text = title;
  542.            
  543.             invalidateSize();
  544.             invalidateDisplayList();
  545.            
  546.             titleChanged = false;
  547.         }
  548.     }
  549.    
  550.     /**
  551.      *  @private
  552.      */
  553.     override protected function measure():void
  554.     {
  555.         var textWidth:Number = 0;
  556.         var textHeight:Number = 0;
  557.        
  558.         // reset text if it was truncated before.
  559.         if (titleDisplay.isTruncated)
  560.             titleDisplay.text = title;
  561.        
  562.         measuredWidth = titleDisplay.getPreferredBoundsWidth();
  563.        
  564.         // tightTextHeight
  565.         measuredHeight = titleDisplay.getPreferredBoundsHeight();
  566.        
  567.         // real measured height plus shadow
  568.         // used for sizing the UIComponent wrapper to include the descent
  569.         // this allows transitions to capture all visible text
  570.         _realTextHeight = titleDisplay.measuredTextSize.y + 1;
  571.     }
  572.    
  573.     /**
  574.      *  @private
  575.      */
  576.     override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
  577.     {
  578.         super.updateDisplayList(unscaledWidth, unscaledHeight);
  579.        
  580.         // reset text if it was truncated before.
  581.         if (titleDisplay.isTruncated)
  582.             titleDisplay.text = title;
  583.         titleDisplay.commitStyles();
  584.        
  585.         titleDisplay.setLayoutBoundsPosition(0, 0);
  586.         titleDisplay.setLayoutBoundsSize(unscaledWidth, unscaledHeight);
  587.        
  588.         // now truncate the text
  589.         titleDisplay.truncateToFit();
  590.        
  591.         titleDisplayShadow.commitStyles();
  592.         titleDisplayShadow.setLayoutBoundsPosition(0, -1);
  593.         titleDisplayShadow.setLayoutBoundsSize(unscaledWidth, unscaledHeight);
  594.        
  595.         titleDisplayShadow.alpha = getStyle("textShadowAlpha");
  596.        
  597.         // if labelDisplay is truncated, then push it down here as well.
  598.         // otherwise, it would have gotten pushed in the labelDisplay_valueCommitHandler()
  599.         if (titleDisplay.isTruncated)
  600.             titleDisplayShadow.text = titleDisplay.text;
  601.     }
  602.    
  603.     /**
  604.      *  @private
  605.      */
  606.     private function titleDisplay_valueCommitHandler(event:Event):void
  607.     {
  608.         titleDisplayShadow.text = titleDisplay.text;
  609.     }
  610.    
  611.     public function get text():String
  612.     {
  613.         return title;
  614.     }
  615.    
  616.     public function set text(value:String):void
  617.     {
  618.         title = value;
  619.         titleChanged = true;
  620.        
  621.         invalidateProperties();
  622.     }
  623.    
  624.     public function get isTruncated():Boolean
  625.     {
  626.         return titleDisplay.isTruncated;
  627.     }
  628.    
  629.     public function get realTextHeight():Number
  630.     {
  631.         return _realTextHeight;
  632.     }
  633. }
Advertisement
Add Comment
Please, Sign In to add comment