| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // 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 mx.containers |
| { |
| |
| import flash.display.DisplayObject; |
| import flash.events.FocusEvent; |
| import flash.events.KeyboardEvent; |
| |
| import mx.controls.Button; |
| import mx.controls.TabBar; |
| import mx.core.Container; |
| import mx.core.EdgeMetrics; |
| import mx.core.IFlexDisplayObject; |
| import mx.core.IInvalidating; |
| import mx.core.IProgrammaticSkin; |
| import mx.core.IUIComponent; |
| import mx.core.UIComponent; |
| import mx.core.mx_internal; |
| import mx.managers.IFocusManagerComponent; |
| import mx.styles.StyleProxy; |
| |
| use namespace mx_internal; |
| |
| //-------------------------------------- |
| // Styles |
| //-------------------------------------- |
| |
| // The fill related styles are applied to the children |
| // of the TabNavigator, ie: the TabBar |
| include "../styles/metadata/FillStyles.as" |
| |
| // The focus styles are applied to the TabNavigator itself. |
| include "../styles/metadata/FocusStyles.as" |
| |
| /** |
| * Name of CSS style declaration that specifies styles for the first tab. |
| * If this is unspecified, the default value |
| * of the <code>tabStyleName</code> style property is used. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="firstTabStyleName", type="String", inherit="no")] |
| |
| /** |
| * Horizontal positioning of tabs at the top of this TabNavigator container. |
| * The possible values are <code>"left"</code>, <code>"center"</code>, |
| * and <code>"right"</code>. |
| * The default value is <code>"left"</code>. |
| * |
| * <p>If the value is <code>"left"</code>, the left edge of the first tab |
| * is aligned with the left edge of the TabNavigator container. |
| * If the value is <code>"right"</code>, the right edge of the last tab |
| * is aligned with the right edge of the TabNavigator container. |
| * If the value is <code>"center"</code>, the tabs are centered on the top |
| * of the TabNavigator container.</p> |
| * |
| * <p>To see a difference between the alignments, |
| * the total width of all the tabs must be less than |
| * the width of the TabNavigator container.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="horizontalAlign", type="String", enumeration="left,center,right", inherit="no")] |
| |
| /** |
| * Separation between tabs, in pixels. |
| * The default value is -1, so that the borders of adjacent tabs overlap. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="horizontalGap", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * Name of CSS style declaration that specifies styles for the last tab. |
| * If this is unspecified, the default value |
| * of the <code>tabStyleName</code> style property is used. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="lastTabStyleName", type="String", inherit="no")] |
| |
| /** |
| * Name of CSS style declaration that specifies styles for the text |
| * of the selected tab. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="selectedTabTextStyleName", type="String", inherit="no")] |
| |
| /** |
| * Height of each tab, in pixels. |
| * The default value is <code>undefined</code>. |
| * When this property is <code>undefined</code>, the height of each tab is |
| * determined by the font styles applied to this TabNavigator container. |
| * If you set this property, the specified value overrides this calculation. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tabHeight", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * Name of CSS style declaration that specifies styles for the tabs. |
| * |
| * @default undefined |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tabStyleName", type="String", inherit="no")] |
| |
| /** |
| * Width of each tab, in pixels. |
| * The default value is <code>undefined</code>. |
| * When this property is <code>undefined</code>, the width of each tab is |
| * determined by the width of its label text, using the font styles applied |
| * to this TabNavigator container. |
| * If the total width of the tabs would be greater than the width of the |
| * TabNavigator container, the calculated tab width is decreased, but |
| * only to a minimum of 30 pixels. |
| * If you set this property, the specified value overrides this calculation. |
| * |
| * <p>The label text on a tab is truncated if it does not fit in the tab. |
| * If a tab label is truncated, a tooltip with the full label text is |
| * displayed when a user rolls the mouse over the tab.</p> |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tabWidth", type="Number", format="Length", inherit="no")] |
| |
| /** |
| * The horizontal offset, in pixels, of the tab bar from the left edge |
| * of the TabNavigator container. |
| * A positive value moves the tab bar to the right. A negative |
| * value move the tab bar to the left. |
| * |
| * @default 0 |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| [Style(name="tabOffset", type="Number", format="Length", inherit="no")] |
| |
| //-------------------------------------- |
| // Excluded APIs |
| //-------------------------------------- |
| |
| [Exclude(name="defaultButton", kind="property")] |
| [Exclude(name="horizontalLineScrollSize", kind="property")] |
| [Exclude(name="horizontalPageScrollSize", kind="property")] |
| [Exclude(name="horizontalScrollBar", kind="property")] |
| [Exclude(name="horizontalScrollPolicy", kind="property")] |
| [Exclude(name="horizontalScrollPosition", kind="property")] |
| [Exclude(name="maxHorizontalScrollPosition", kind="property")] |
| [Exclude(name="maxVerticalScrollPosition", kind="property")] |
| [Exclude(name="verticalLineScrollSize", kind="property")] |
| [Exclude(name="verticalPageScrollSize", kind="property")] |
| [Exclude(name="verticalScrollBar", kind="property")] |
| [Exclude(name="verticalScrollPolicy", kind="property")] |
| [Exclude(name="verticalScrollPosition", kind="property")] |
| |
| [Exclude(name="scroll", kind="event")] |
| |
| [Exclude(name="fillAlphas", kind="style")] |
| [Exclude(name="fillColors", kind="style")] |
| [Exclude(name="horizontalScrollBarStyleName", kind="style")] |
| [Exclude(name="verticalScrollBarStyleName", kind="style")] |
| |
| //-------------------------------------- |
| // Other metadata |
| //-------------------------------------- |
| |
| [IconFile("TabNavigator.png")] |
| |
| /** |
| * The MX TabNavigator container extends the MX ViewStack container by including |
| * a TabBar container for navigating between its child containers. |
| * |
| * <p><b>Note:</b> The direct children of an MX navigator container must be |
| * MX containers, either MX layout or MX navigator containers, |
| * or the Spark NavigatorContent container. |
| * You cannot directly nest a control or a Spark container |
| * other than the Spark NavigatorContent container within a navigator; |
| * they must be children of an child MX container.</p> |
| * |
| * <p>Like a ViewStack container, a TabNavigator container has a collection |
| * of child containers, in which only one child at a time is visible. |
| * Flex automatically creates a TabBar container at the top of the |
| * TabNavigator container, with a tab corresponding to each child container. |
| * Each tab can have its own label and icon. |
| * When the user clicks a tab, the corresponding child container becomes |
| * visible as the selected child of the TabNavigator container.</p> |
| * |
| * <p>When you change the currently visible child container, |
| * you can use the <code>hideEffect</code> property of the container being |
| * hidden and the <code>showEffect</code> property of the newly visible child |
| * container to apply an effect to the child containers. |
| * The TabNavigator container waits for the <code>hideEffect</code> of the |
| * child container being hidden to complete before it reveals the new child |
| * container. |
| * You can interrupt a currently playing effect if you change the |
| * <code>selectedIndex</code> property of the TabNavigator container |
| * while an effect is playing. </p> |
| * |
| * <p>To define the appearance of tabs in a TabNavigator, you can define style properties in a |
| * Tab type selector, as the following example shows:</p> |
| * <pre> |
| * <fx:Style> |
| * @namespace mx "library://ns.adobe.com/flex/mx" |
| * mx|Tab { |
| * fillColors: #006699, #cccc66; |
| * upSkin: ClassReference("CustomSkinClass"); |
| * overSkin: ClassReference("CustomSkinClass"); |
| * downSkin: ClassReference("CustomSkinClass"); |
| * } |
| * </fx:Style> |
| * </pre> |
| * |
| * <p>The Tab type selector defines values on the hidden mx.controls.tabBarClasses.Tab |
| * class. The default values for the Tab type selector are defined in the |
| * defaults.css file.</p> |
| * |
| * <p>You can also define the styles in a class selector that you specify using |
| * the <code>tabStyleName</code> style property; for example:</p> |
| * <pre> |
| * <fx:Style> |
| * @namespace mx "library://ns.adobe.com/flex/mx" |
| * mx|TabNavigator { |
| * tabStyleName:myTabStyle; |
| * } |
| * |
| * .myTabStyle { |
| * fillColors: #006699, #cccc66; |
| * upSkin: ClassReference("CustomSkinClass"); |
| * overSkin: ClassReference("CustomSkinClass"); |
| * downSkin: ClassReference("CustomSkinClass"); |
| * } |
| * </fx:Style> |
| * </pre> |
| * |
| * <p>A TabNavigator container has the following default sizing characteristics:</p> |
| * <table class="innertable"> |
| * <tr> |
| * <th>Characteristic</th> |
| * <th>Description</th> |
| * </tr> |
| * <tr> |
| * <td>Default size</td> |
| * <td>The default or explicit width and height of the first active child |
| * plus the tabs, at their default or explicit heights and widths. |
| * Default tab height is determined by the font, style, and skin applied |
| * to the TabNavigator container.</td> |
| * </tr> |
| * <tr> |
| * <td>Container resizing rules</td> |
| * <td>By default, TabNavigator containers are only sized once to fit the size |
| * of the first child container. They do not resize when you navigate to |
| * other child containers. To force TabNavigator containers to resize when |
| * you navigate to a different child container, set the resizeToContent |
| * property to true.</td> |
| * </tr> |
| * <tr> |
| * <td>Child layout rules</td> |
| * <td>If the child is larger than the TabNavigator container, it is clipped. If |
| * the child is smaller than the TabNavigator container, it is aligned to |
| * the upper-left corner of the TabNavigator container.</td> |
| * </tr> |
| * <tr> |
| * <td>Default padding</td> |
| * <td>0 pixels for the top, bottom, left, and right values.</td> |
| * </tr> |
| * </table> |
| * |
| * @mxml |
| * |
| * <p>The <code><mx:TabNavigator></code> tag inherits all of the |
| * tag attributes of its superclass, |
| * and adds the following tag attributes:</p> |
| * |
| * <pre> |
| * <mx:TabNavigator |
| * <b>Styles</b> |
| * firstTabStyleName="<i>Value of the</i> <code>tabStyleName</code> <i>property</i>" |
| * focusAlpha="0.4" |
| * focusRoundedCorners="tl tr bl br" |
| * horizontalAlign="left|center|right" |
| * horizontalGap="-1" |
| * lastTabStyleName="<i>Value of the</i> <code>tabStyleName</code> <i>property</i>" |
| * selectedTabTextStyleName="undefined" |
| * tabHeight="undefined" |
| * tabOffset="0" |
| * tabStyleName="<i>Name of CSS style declaration that specifies styles for the tabs</i>" |
| * tabWidth="undefined" |
| * > |
| * ... |
| * <i>child tags</i> |
| * ... |
| * </mx:TabNavigator> |
| * </pre> |
| * |
| * @includeExample examples/TabNavigatorExample.mxml |
| * |
| * @see mx.containers.ViewStack |
| * @see mx.controls.TabBar |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public class TabNavigator extends ViewStack implements IFocusManagerComponent |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class constants |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private static const MIN_TAB_WIDTH:Number = 30; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function TabNavigator() |
| { |
| super(); |
| |
| // Most views can't take focus, but a TabNavigator can. |
| // Container.init() has set tabEnabled false, so we |
| // have to set it back to true. |
| tabEnabled = true; |
| tabFocusEnabled = true; |
| hasFocusableChildren = true; |
| |
| historyManagementEnabled = true; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // baselinePosition |
| //---------------------------------- |
| |
| /** |
| * @private |
| * The baselinePosition of a TabNavigator is calculated |
| * for the label of the first tab. |
| * If there are no children, a child is temporarily added |
| * to do the computation. |
| */ |
| override public function get baselinePosition():Number |
| { |
| if (!validateBaselinePosition()) |
| return NaN; |
| |
| var isEmpty:Boolean = numChildren == 0; |
| if (isEmpty) |
| { |
| var child0:Container = new Container(); |
| addChild(child0); |
| validateNow(); |
| } |
| |
| var tab0:Button = getTabAt(0); |
| var result:Number = tabBar.y + tab0.y + tab0.baselinePosition; |
| |
| if (isEmpty) |
| { |
| removeChildAt(0); |
| validateNow(); |
| } |
| |
| return result; |
| } |
| |
| //---------------------------------- |
| // contentHeight |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function get contentHeight():Number |
| { |
| var vm:EdgeMetrics = viewMetricsAndPadding; |
| |
| var vmTop:Number = vm.top; |
| var vmBottom:Number = vm.bottom; |
| |
| if (isNaN(vmTop)) |
| vmTop = 0; |
| if (isNaN(vmBottom)) |
| vmBottom = 0; |
| |
| return unscaledHeight - tabBarHeight - vmTop - vmBottom; |
| } |
| |
| //---------------------------------- |
| // contentY |
| //---------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function get contentY():Number |
| { |
| var paddingTop:Number = getStyle("paddingTop"); |
| |
| if (isNaN(paddingTop)) |
| paddingTop = 0; |
| |
| return tabBarHeight + paddingTop; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Properties |
| // |
| //-------------------------------------------------------------------------- |
| |
| //---------------------------------- |
| // tabBarHeight |
| //---------------------------------- |
| |
| /** |
| * A reference to the TabBar inside this TabNavigator. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected var tabBar:TabBar; |
| |
| //---------------------------------- |
| // tabBarHeight |
| //---------------------------------- |
| |
| /** |
| * @private |
| * Height of the tab. |
| */ |
| private function get tabBarHeight():Number |
| { |
| var tabHeight:Number = getStyle("tabHeight"); |
| |
| if (isNaN(tabHeight)) |
| tabHeight = tabBar.getExplicitOrMeasuredHeight(); |
| |
| return tabHeight - borderMetrics.top; |
| } |
| |
| //---------------------------------- |
| // tabBarStyleFilters |
| //---------------------------------- |
| |
| /** |
| * The set of styles to pass from the TabNavigator to the tabBar. |
| * @see mx.styles.StyleProxy |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| protected function get tabBarStyleFilters():Object |
| { |
| return _tabBarStyleFilters; |
| } |
| |
| private static var _tabBarStyleFilters:Object = |
| { |
| "firstTabStyleName" : "firstTabStyleName", |
| "horizontalAlign" : "horizontalAlign", |
| "horizontalGap" : "horizontalGap", |
| "lastTabStyleName" : "lastTabStyleName", |
| "selectedTabTextStyleName" : "selectedTabTextStyleName", |
| "tabStyleName" : "tabStyleName", |
| "tabWidth" : "tabWidth", |
| "verticalAlign" : "verticalAlign", |
| "verticalGap" : "verticalGap" |
| }; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods: UIComponent |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function createChildren():void |
| { |
| super.createChildren(); |
| |
| if (!tabBar) |
| { |
| tabBar = new TabBar(); |
| tabBar.name = "tabBar"; |
| tabBar.focusEnabled = false; |
| tabBar.styleName = new StyleProxy(this, tabBarStyleFilters); |
| rawChildren.addChild(tabBar); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function commitProperties():void |
| { |
| super.commitProperties(); |
| |
| // Things get a bit tricky here... we need to |
| // wait until our children have been instantiated |
| // before we can attach the tab bar to us. |
| if (tabBar && tabBar.dataProvider != this && |
| numChildren > 0 && getChildAt(0)) |
| { |
| tabBar.dataProvider = this; |
| } |
| } |
| |
| /** |
| * Calculates the default sizes and mininum and maximum values of this |
| * TabNavigator container. |
| * See the <code>UIComponent.measure()</code> method for more information |
| * about the <code>measure()</code> method. |
| * |
| * <p>The TabNavigator container uses the same measurement logic as the |
| * <code>ViewStack</code> container, with two modifications: |
| * First, it increases the value of the |
| * <code>measuredHeight</code> and |
| * <code>measuredMinHeight</code> properties to accomodate the tabs. |
| * Second, it increases the value of the |
| * <code>measuredWidth</code> property if necessary |
| * to ensure that each tab can be at least 30 pixels wide.</p> |
| * |
| * @see mx.core.UIComponent#measure() |
| * @see mx.containers.ViewStack#measure() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function measure():void |
| { |
| // Only measure once. Thereafter, we'll just use cached values. |
| // We need to copy the cached values into the measured fields |
| // again to handle the case where scaleX or scaleY is not 1.0. |
| // When the TabNavigator is zoomed, code in UIComponent.measureSizes |
| // scales the measuredWidth/Height values every time that |
| // measureSizes is called. (bug 100749) |
| |
| // This must be done before the call to super.measure(), otherwise |
| // we don't get the first measurement correct. |
| if (vsPreferredWidth && !resizeToContent) |
| { |
| measuredMinWidth = vsMinWidth; |
| measuredMinHeight = vsMinHeight; |
| measuredWidth = vsPreferredWidth; |
| measuredHeight = vsPreferredHeight; |
| return; |
| } |
| |
| super.measure(); |
| |
| var addedHeight:Number = tabBarHeight; |
| measuredMinHeight += addedHeight; |
| measuredHeight += addedHeight; |
| |
| // Make sure there is at least enough room |
| // to draw all tabs at their minimum size. |
| var tabWidth:Number = getStyle("tabWidth"); |
| if (isNaN(tabWidth)) |
| tabWidth = 0; |
| |
| var minTabBarWidth:Number = |
| numChildren * Math.max(tabWidth, MIN_TAB_WIDTH); |
| |
| // Add view metrics. |
| var vm:EdgeMetrics = viewMetrics; |
| minTabBarWidth += (vm.left + vm.right); |
| |
| // Add horizontal gaps. |
| if (numChildren > 1) |
| minTabBarWidth += (getStyle("horizontalGap") * (numChildren - 1)); |
| |
| if (measuredWidth < minTabBarWidth) |
| measuredWidth = minTabBarWidth; |
| |
| // If we're called before instantiateSelectedChild, then bail. |
| // We'll be called again later (instantiateSelectedChild calls |
| // invalidateSize), and we don't want to load values into the |
| // cache until we're fully initialized. (bug 102639) |
| if (selectedChild && selectedChild.deferredContentCreated == false) |
| return; |
| |
| // Don't remember sizes if we don't have any children |
| if (numChildren == 0) |
| return; |
| |
| vsMinWidth = measuredMinWidth; |
| vsMinHeight = measuredMinHeight; |
| vsPreferredWidth = measuredWidth; |
| vsPreferredHeight = measuredHeight; |
| } |
| |
| /** |
| * Responds to size changes by setting the positions and sizes |
| * of this container's tabs and children. |
| * |
| * For more information about the <code>updateDisplayList()</code> method, |
| * see the <code>UIComponent.updateDisplayList()</code> method. |
| * |
| * <p>A TabNavigator container positions its TabBar container at the top. |
| * The width of the TabBar is set to the width of the |
| * TabNavigator, and the height of the TabBar is set |
| * based on the <code>tabHeight</code> property.</p> |
| * |
| * <p>A TabNavigator container positions and sizes its child containers |
| * underneath the TabBar, using the same logic as in |
| * ViewStack container.</p> |
| * |
| * @param unscaledWidth Specifies the width of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleX</code> property of the component. |
| * |
| * @param unscaledHeight Specifies the height of the component, in pixels, |
| * in the component's coordinates, regardless of the value of the |
| * <code>scaleY</code> property of the component. |
| * |
| * @see mx.core.UIComponent#updateDisplayList() |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| override protected function updateDisplayList(unscaledWidth:Number, |
| unscaledHeight:Number):void |
| { |
| super.updateDisplayList(unscaledWidth, unscaledHeight); |
| |
| var bm:EdgeMetrics = borderMetrics; |
| var vm:EdgeMetrics = viewMetrics; |
| var w:Number = unscaledWidth - vm.left - vm.right; |
| |
| var th:Number = tabBarHeight + bm.top; |
| var pw:Number = tabBar.getExplicitOrMeasuredWidth(); |
| tabBar.setActualSize(Math.min(w, pw), th); |
| var leftOffset:Number = getStyle("tabOffset"); |
| |
| switch (getStyle("horizontalAlign")) |
| { |
| case "left": |
| tabBar.move(0 + leftOffset, tabBar.y); |
| break; |
| case "right": |
| tabBar.move(unscaledWidth - tabBar.width + leftOffset, tabBar.y); |
| break; |
| case "center": |
| tabBar.move((unscaledWidth - tabBar.width) / 2 + leftOffset, tabBar.y); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| override public function drawFocus(isFocused:Boolean):void |
| { |
| // Superclass sets up standard focus glow. |
| super.drawFocus(isFocused); |
| |
| if (!parent) |
| return; |
| |
| // Clip the glow so it doesn't include the tabs |
| var focusObj:DisplayObject = IUIComponent(parent).focusPane; |
| if (isFocused && !isEffectStarted) |
| { |
| // Normally the focus skin is in front of the object. For TabNavigator |
| // we want it behind. |
| if (focusObj) |
| { |
| if (parent is Container) |
| { |
| var n:int = Container(parent).rawChildren.numChildren; |
| var fci:int = Container(parent).firstChildIndex; |
| // make sure we don't set it past the last index. This happens |
| // if all content children are in a contentpane |
| Container(parent).rawChildren.setChildIndex( |
| focusObj, Math.max(0, (fci == n) ? n - 1 : fci)); |
| } |
| else if (parent is UIComponent) |
| { |
| UIComponent(parent).$setChildIndex(focusObj, 0); |
| } |
| else |
| { |
| parent.setChildIndex(focusObj, 0); |
| } |
| } |
| } |
| else |
| { |
| if (focusObj) |
| { |
| // Move the focus skin back in front of the children, where it |
| // was before we drew focus. |
| if (parent is Container) |
| { |
| Container(parent).rawChildren.setChildIndex( |
| focusObj, Container(parent).rawChildren.numChildren - 1); |
| } |
| else if (parent is UIComponent) |
| { |
| UIComponent(parent).$setChildIndex(focusObj, parent.numChildren - 1); |
| } |
| else |
| { |
| parent.setChildIndex(focusObj, parent.numChildren - 1); |
| } |
| } |
| } |
| |
| tabBar.drawFocus(isFocused); |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function adjustFocusRect( |
| object:DisplayObject = null):void |
| { |
| // Superclass does most of the work |
| super.adjustFocusRect(object); |
| |
| // Adjust the focus rect so it is below the tabs |
| var focusObj:IFlexDisplayObject = IFlexDisplayObject(getFocusObject()); |
| |
| if (focusObj) |
| { |
| focusObj.setActualSize(focusObj.width, focusObj.height - tabBarHeight); |
| focusObj.move(focusObj.x, focusObj.y + tabBarHeight); |
| |
| if (focusObj is IInvalidating) |
| IInvalidating(focusObj).validateNow(); |
| |
| else if (focusObj is IProgrammaticSkin) |
| IProgrammaticSkin(focusObj).validateNow(); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden methods: Container |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function layoutChrome(unscaledWidth:Number, |
| unscaledHeight:Number):void |
| { |
| super.layoutChrome(unscaledWidth, unscaledHeight); |
| |
| // Move our border so it leaves room for the tabs |
| if (border) |
| { |
| var borderOffset:Number = tabBarHeight; |
| border.setActualSize(unscaledWidth, unscaledHeight - borderOffset); |
| border.move(0, borderOffset); |
| } |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Returns the tab of the navigator's TabBar control at the specified |
| * index. |
| * |
| * @param index Index in the navigator's TabBar control. |
| * |
| * @return The tab at the specified index. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function getTabAt(index:int):Button |
| { |
| return Button(tabBar.getChildAt(index)); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Overridden event handlers: UIComponent |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| override protected function focusInHandler(event:FocusEvent):void |
| { |
| super.focusInHandler(event); |
| |
| // When the TabNavigator has focus, the Focus Manager |
| // should not treat the Enter key as a click on |
| // the default pushbutton. |
| if (event.target == this) |
| focusManager.defaultButtonEnabled = false; |
| } |
| |
| /** |
| * @private |
| */ |
| override protected function focusOutHandler(event:FocusEvent):void |
| { |
| super.focusOutHandler(event); |
| |
| if (focusManager && event.target == this) |
| focusManager.defaultButtonEnabled = true; |
| } |
| |
| import flash.ui.Keyboard; |
| |
| /** |
| * @private |
| */ |
| override protected function keyDownHandler(event:KeyboardEvent):void |
| { |
| if (focusManager.getFocus() == this) |
| { |
| // Redispatch the event from the TabBar so that it can handle it. |
| tabBar.dispatchEvent(event); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| mx_internal function getTabBar():TabBar |
| { |
| return tabBar; |
| } |
| |
| } |
| |
| } |