1////////////////////////////////////////////////////////////////////////////////
2//
3//  ADOBE SYSTEMS INCORPORATED
4//  Copyright 2011 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
12package spark.skins.mobile
13{
14
15import flash.display.Graphics;
16
17import mx.core.DPIClassification;
18import mx.core.mx_internal;
19
20import spark.core.SpriteVisualElement;
21import spark.skins.mobile160.assets.CalloutContentBackground;
22import spark.skins.mobile240.assets.CalloutContentBackground;
23import spark.skins.mobile320.assets.CalloutContentBackground;
24
25use namespace mx_internal;
26
27/**
28 *  The ActionScript-based skin for view navigators inside a callout.
29 *  This skin lays out the action bar and content
30 *  group in a vertical fashion, where the action bar is on top.
31 *  Unlike the default skin, overlay modes are not supported.
32 *
33 *  @langversion 3.0
34 *  @playerversion AIR 3
35 *  @productversion Flex 4.6
36 */
37public class CalloutViewNavigatorSkin extends ViewNavigatorSkin
38{
39    //--------------------------------------------------------------------------
40    //
41    //  Constructor
42    //
43    //--------------------------------------------------------------------------
44
45    /**
46     *  Constructor.
47     *
48     *  @langversion 3.0
49     *  @playerversion AIR 3
50     *  @productversion Flex 4.6
51     */
52    public function CalloutViewNavigatorSkin()
53    {
54        super();
55
56        switch (applicationDPI)
57        {
58            case DPIClassification.DPI_320:
59            {
60                contentBackgroundClass = spark.skins.mobile320.assets.CalloutContentBackground;
61                contentCornerRadius = 10;
62                gap = 16;
63                break;
64            }
65            case DPIClassification.DPI_240:
66            {
67                contentBackgroundClass = spark.skins.mobile240.assets.CalloutContentBackground;
68                contentCornerRadius = 7;
69                gap = 12;
70                break;
71            }
72            default:
73            {
74                // default DPI_160
75                contentBackgroundClass = spark.skins.mobile160.assets.CalloutContentBackground;
76                contentCornerRadius = 5;
77                gap = 8;
78                break;
79            }
80        }
81    }
82
83    //--------------------------------------------------------------------------
84    //
85    //  Layout variables
86    //
87    //--------------------------------------------------------------------------
88
89    mx_internal var gap:Number;
90
91    //--------------------------------------------------------------------------
92    //
93    //  Variables
94    //
95    //--------------------------------------------------------------------------
96
97    mx_internal var contentBackgroundClass:Class;
98
99    mx_internal var contentBackgroundGraphic:SpriteVisualElement;
100
101    mx_internal var contentCornerRadius:Number;
102
103    private var contentMask:SpriteVisualElement;
104
105    //--------------------------------------------------------------------------
106    //
107    //  Overridden methods
108    //
109    //--------------------------------------------------------------------------
110
111    /**
112     *  @private
113     */
114    override protected function createChildren():void
115    {
116        super.createChildren();
117
118        // mask the ViewNavigator contentGroup
119        contentMask = new SpriteVisualElement();
120        contentGroup.mask = contentMask;
121
122        // contentBackground shadow is layered above the contentGroup
123        contentBackgroundGraphic = new contentBackgroundClass() as SpriteVisualElement;
124        addChild(contentBackgroundGraphic);
125    }
126
127    /**
128     *  @private
129     */
130    override protected function measure():void
131    {
132        super.measure();
133
134        measuredWidth = Math.max(actionBar.getPreferredBoundsWidth(),
135            contentGroup.getPreferredBoundsWidth());
136        measuredHeight = actionBar.getPreferredBoundsHeight()
137            + contentGroup.getPreferredBoundsHeight()
138            + gap;
139    }
140
141    /**
142     *  @private
143     */
144    override protected function commitCurrentState():void
145    {
146        super.commitCurrentState();
147
148        // Force a layout pass on the components
149        invalidateProperties();
150        invalidateSize();
151        invalidateDisplayList();
152    }
153
154    /**
155     *  @private
156     */
157    override protected function layoutContents(unscaledWidth:Number, unscaledHeight:Number):void
158    {
159        // omit super call
160
161        var actionBarHeight:Number = 0;
162
163        // The action bar is always placed at 0,0 and stretches the entire
164        // width of the navigator
165        if (actionBar.includeInLayout)
166        {
167            actionBarHeight = Math.min(actionBar.getPreferredBoundsHeight(), unscaledHeight);
168            setElementSize(actionBar, unscaledWidth, actionBarHeight);
169            setElementPosition(actionBar, 0, 0);
170            actionBarHeight = actionBar.getLayoutBoundsHeight();
171        }
172
173        // If the hostComponent is in overlay mode, the contentGroup extends
174        // the entire bounds of the navigator and the alpha for the action
175        // bar changes
176        // If this changes, also update validateEstimatedSizesOfChild
177        var contentGroupHeight:Number = 0;
178
179        if (contentGroup.includeInLayout)
180        {
181            contentGroupHeight = Math.max(unscaledHeight - actionBarHeight - gap, 0);
182
183            setElementSize(contentGroup, unscaledWidth, contentGroupHeight);
184            setElementPosition(contentGroup, 0, actionBarHeight + gap);
185
186            setElementSize(contentBackgroundGraphic, unscaledWidth, contentGroupHeight);
187            setElementPosition(contentBackgroundGraphic, 0, actionBarHeight + gap);
188        }
189
190        setElementSize(contentMask, unscaledWidth, contentGroupHeight);
191        setElementPosition(contentBackgroundGraphic, 0, actionBarHeight + gap);
192    }
193
194    /**
195     *  @private
196     */
197    override protected function drawBackground(unscaledWidth:Number, unscaledHeight:Number):void
198    {
199        super.drawBackground(unscaledWidth, unscaledHeight);
200
201        // draw the contentBackgroundColor
202        // the shading and highlight are drawn in FXG
203        var contentEllipseSize:Number = contentCornerRadius * 2;
204        var contentBackgroundAlpha:Number = getStyle("contentBackgroundAlpha");
205        var contentWidth:Number = contentGroup.getLayoutBoundsWidth();
206        var contentHeight:Number = contentGroup.getLayoutBoundsHeight();
207
208        graphics.beginFill(getStyle("contentBackgroundColor"),
209            contentBackgroundAlpha);
210        graphics.drawRoundRect(contentBackgroundGraphic.getLayoutBoundsX(),
211            contentBackgroundGraphic.getLayoutBoundsY(),
212            contentWidth,
213            contentHeight,
214            contentEllipseSize,
215            contentEllipseSize);
216        graphics.endFill();
217
218        if (contentMask)
219        {
220            // content mask in contentGroup coordinate space
221            var maskGraphics:Graphics = contentMask.graphics;
222            maskGraphics.clear();
223            maskGraphics.beginFill(0, 1);
224            maskGraphics.drawRoundRect(0, 0, contentWidth, contentHeight,
225                contentEllipseSize, contentEllipseSize);
226            maskGraphics.endFill();
227        }
228
229        contentBackgroundGraphic.alpha = contentBackgroundAlpha;
230    }
231}
232}