1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2003-2007 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 mx.containers 13{ 14 15import flash.display.DisplayObject; 16import flash.events.Event; 17import flash.events.FocusEvent; 18import flash.events.KeyboardEvent; 19import mx.controls.Button; 20import mx.controls.TabBar; 21import mx.core.Container; 22import mx.core.EdgeMetrics; 23import mx.core.FlexVersion; 24import mx.core.IFlexDisplayObject; 25import mx.core.IInvalidating; 26import mx.core.IProgrammaticSkin; 27import mx.core.IUIComponent; 28import mx.core.mx_internal; 29import mx.events.ItemClickEvent; 30import mx.managers.IFocusManagerComponent; 31import mx.styles.StyleProxy; 32 33use namespace mx_internal; 34 35//-------------------------------------- 36// Styles 37//-------------------------------------- 38 39// The fill related styles are applied to the children 40// of the TabNavigator, ie: the TabBar 41include "../styles/metadata/FillStyles.as" 42 43// The focus styles are applied to the TabNavigator itself. 44include "../styles/metadata/FocusStyles.as" 45 46/** 47 * Name of CSS style declaration that specifies styles for the first tab. 48 * If this is unspecified, the default value 49 * of the <code>tabStyleName</code> style property is used. 50 */ 51[Style(name="firstTabStyleName", type="String", inherit="no")] 52 53/** 54 * Horizontal positioning of tabs at the top of this TabNavigator container. 55 * The possible values are <code>"left"</code>, <code>"center"</code>, 56 * and <code>"right"</code>. 57 * The default value is <code>"left"</code>. 58 * 59 * <p>If the value is <code>"left"</code>, the left edge of the first tab 60 * is aligned with the left edge of the TabNavigator container. 61 * If the value is <code>"right"</code>, the right edge of the last tab 62 * is aligned with the right edge of the TabNavigator container. 63 * If the value is <code>"center"</code>, the tabs are centered on the top 64 * of the TabNavigator container.</p> 65 * 66 * <p>To see a difference between the alignments, 67 * the total width of all the tabs must be less than 68 * the width of the TabNavigator container.</p> 69 */ 70[Style(name="horizontalAlign", type="String", enumeration="left,center,right", inherit="no")] 71 72/** 73 * Separation between tabs, in pixels. 74 * The default value is -1, so that the borders of adjacent tabs overlap. 75 */ 76[Style(name="horizontalGap", type="Number", format="Length", inherit="no")] 77 78/** 79 * Name of CSS style declaration that specifies styles for the last tab. 80 * If this is unspecified, the default value 81 * of the <code>tabStyleName</code> style property is used. 82 */ 83[Style(name="lastTabStyleName", type="String", inherit="no")] 84 85/** 86 * Name of CSS style declaration that specifies styles for the text 87 * of the selected tab. 88 */ 89[Style(name="selectedTabTextStyleName", type="String", inherit="no")] 90 91/** 92 * Height of each tab, in pixels. 93 * The default value is <code>undefined</code>. 94 * When this property is <code>undefined</code>, the height of each tab is 95 * determined by the font styles applied to this TabNavigator container. 96 * If you set this property, the specified value overrides this calculation. 97 */ 98[Style(name="tabHeight", type="Number", format="Length", inherit="no")] 99 100/** 101 * Name of CSS style declaration that specifies styles for the tabs. 102 * 103 * @default undefined 104 */ 105[Style(name="tabStyleName", type="String", inherit="no")] 106 107/** 108 * Width of each tab, in pixels. 109 * The default value is <code>undefined</code>. 110 * When this property is <code>undefined</code>, the width of each tab is 111 * determined by the width of its label text, using the font styles applied 112 * to this TabNavigator container. 113 * If the total width of the tabs would be greater than the width of the 114 * TabNavigator container, the calculated tab width is decreased, but 115 * only to a minimum of 30 pixels. 116 * If you set this property, the specified value overrides this calculation. 117 * 118 * <p>The label text on a tab is truncated if it does not fit in the tab. 119 * If a tab label is truncated, a tooltip with the full label text is 120 * displayed when a user rolls the mouse over the tab.</p> 121 */ 122[Style(name="tabWidth", type="Number", format="Length", inherit="no")] 123 124/** 125 * The horizontal offset, in pixels, of the tab bar from the left edge 126 * of the TabNavigator container. 127 * A positive value moves the tab bar to the right. A negative 128 * value move the tab bar to the left. 129 * 130 * @default 0 131 */ 132[Style(name="tabOffset", type="Number", format="Length", inherit="no")] 133 134//-------------------------------------- 135// Excluded APIs 136//-------------------------------------- 137 138[Exclude(name="defaultButton", kind="property")] 139[Exclude(name="horizontalLineScrollSize", kind="property")] 140[Exclude(name="horizontalPageScrollSize", kind="property")] 141[Exclude(name="horizontalScrollBar", kind="property")] 142[Exclude(name="horizontalScrollPolicy", kind="property")] 143[Exclude(name="horizontalScrollPosition", kind="property")] 144[Exclude(name="maxHorizontalScrollPosition", kind="property")] 145[Exclude(name="maxVerticalScrollPosition", kind="property")] 146[Exclude(name="verticalLineScrollSize", kind="property")] 147[Exclude(name="verticalPageScrollSize", kind="property")] 148[Exclude(name="verticalScrollBar", kind="property")] 149[Exclude(name="verticalScrollPolicy", kind="property")] 150[Exclude(name="verticalScrollPosition", kind="property")] 151 152[Exclude(name="scroll", kind="event")] 153 154[Exclude(name="fillAlphas", kind="style")] 155[Exclude(name="fillColors", kind="style")] 156[Exclude(name="horizontalScrollBarStyleName", kind="style")] 157[Exclude(name="verticalScrollBarStyleName", kind="style")] 158 159//-------------------------------------- 160// Other metadata 161//-------------------------------------- 162 163[IconFile("TabNavigator.png")] 164 165/** 166 * The TabNavigator container extends the ViewStack container by including 167 * a TabBar container for navigating between its child containers. 168 * 169 * <p>Like a ViewStack container, a TabNavigator container has a collection 170 * of child containers, in which only one child at a time is visible. 171 * Flex automatically creates a TabBar container at the top of the 172 * TabNavigator container, with a tab corresponding to each child container. 173 * Each tab can have its own label and icon. 174 * When the user clicks a tab, the corresponding child container becomes 175 * visible as the selected child of the TabNavigator container.</p> 176 * 177 * <p>When you change the currently visible child container, 178 * you can use the <code>hideEffect</code> property of the container being 179 * hidden and the <code>showEffect</code> property of the newly visible child 180 * container to apply an effect to the child containers. 181 * The TabNavigator container waits for the <code>hideEffect</code> of the 182 * child container being hidden to complete before it reveals the new child 183 * container. 184 * You can interrupt a currently playing effect if you change the 185 * <code>selectedIndex</code> property of the TabNavigator container 186 * while an effect is playing. </p> 187 * 188 * <p>To define the appearance of tabs in a TabNavigator, you can define style properties in a 189 * Tab type selector, as the following example shows:</p> 190 * <pre> 191 * <mx:Style> 192 * Tab { 193 * fillColors: #006699, #cccc66; 194 * upSkin: ClassReference("CustomSkinClass"); 195 * overSkin: ClassReference("CustomSkinClass"); 196 * downSkin: ClassReference("CustomSkinClass"); 197 * } 198 * </mx:Style> 199 * </pre> 200 * 201 * <p>The Tab type selector defines values on the hidden mx.controls.tabBarClasses.Tab 202 * class. The default values for the Tab type selector are defined in the 203 * defaults.css file.</p> 204 * 205 * <p>You can also define the styles in a class selector that you specify using 206 * the <code>tabStyleName</code> style property; for example:</p> 207 * <pre> 208 * <mx:Style> 209 * TabNavigator { 210 * tabStyleName:myTabStyle; 211 * } 212 * 213 * .myTabStyle { 214 * fillColors: #006699, #cccc66; 215 * upSkin: ClassReference("CustomSkinClass"); 216 * overSkin: ClassReference("CustomSkinClass"); 217 * downSkin: ClassReference("CustomSkinClass"); 218 * } 219 * </mx:Style> 220 * </pre> 221 * 222 * <p>A TabNavigator container has the following default sizing characteristics:</p> 223 * <table class="innertable"> 224 * <tr> 225 * <th>Characteristic</th> 226 * <th>Description</th> 227 * </tr> 228 * <tr> 229 * <td>Default size</td> 230 * <td>The default or explicit width and height of the first active child 231 * plus the tabs, at their default or explicit heights and widths. 232 * Default tab height is determined by the font, style, and skin applied 233 * to the TabNavigator container.</td> 234 * </tr> 235 * <tr> 236 * <td>Container resizing rules</td> 237 * <td>By default, TabNavigator containers are only sized once to fit the size 238 * of the first child container. They do not resize when you navigate to 239 * other child containers. To force TabNavigator containers to resize when 240 * you navigate to a different child container, set the resizeToContent 241 * property to true.</td> 242 * </tr> 243 * <tr> 244 * <td>Child layout rules</td> 245 * <td>If the child is larger than the TabNavigator container, it is clipped. If 246 * the child is smaller than the TabNavigator container, it is aligned to 247 * the upper-left corner of the TabNavigator container.</td> 248 * </tr> 249 * <tr> 250 * <td>Default padding</td> 251 * <td>0 pixels for the top, bottom, left, and right values.</td> 252 * </tr> 253 * </table> 254 * 255 * @mxml 256 * 257 * <p>The <code><mx:TabNavigator></code> tag inherits all of the 258 * tag attributes of its superclass, 259 * and adds the following tag attributes:</p> 260 * 261 * <pre> 262 * <mx:TabNavigator 263 * <b>Styles</b> 264 * fillAlphas="[0.60, 0.40, 0.75, 0.65]" 265 * fillColors="[0xFFFFFF, 0xCCCCCC, 0xFFFFFF, 0xEEEEEE]" 266 * firstTabStyleName="<i>Value of the</i> <code>tabStyleName</code> <i>property</i>" 267 * focusAlpha="0.4" 268 * focusRoundedCorners="tl tr bl br" 269 * horizontalAlign="left|center|right" 270 * horizontalGap="-1" 271 * lastTabStyleName="<i>Value of the</i> <code>tabStyleName</code> <i>property</i>" 272 * selectedTabTextStyleName="undefined" 273 * tabHeight="undefined" 274 * tabOffset="0" 275 * tabStyleName="<i>Name of CSS style declaration that specifies styles for the tabs</i>" 276 * tabWidth="undefined" 277 * > 278 * ... 279 * <i>child tags</i> 280 * ... 281 * </mx:TabNavigator> 282 * </pre> 283 * 284 * @includeExample examples/TabNavigatorExample.mxml 285 * 286 * @see mx.containers.ViewStack 287 * @see mx.controls.TabBar 288 */ 289public class TabNavigator extends ViewStack implements IFocusManagerComponent 290{ 291 include "../core/Version.as"; 292 293 //-------------------------------------------------------------------------- 294 // 295 // Class constants 296 // 297 //-------------------------------------------------------------------------- 298 299 /** 300 * @private 301 */ 302 private static const MIN_TAB_WIDTH:Number = 30; 303 304 //-------------------------------------------------------------------------- 305 // 306 // Constructor 307 // 308 //-------------------------------------------------------------------------- 309 310 /** 311 * Constructor. 312 */ 313 public function TabNavigator() 314 { 315 super(); 316 317 // Most views can't take focus, but a TabNavigator can. 318 // Container.init() has set tabEnabled false, so we 319 // have to set it back to true. 320 tabEnabled = true; 321 322 historyManagementEnabled = true; 323 } 324 325 //-------------------------------------------------------------------------- 326 // 327 // Overridden properties 328 // 329 //-------------------------------------------------------------------------- 330 331 //---------------------------------- 332 // baselinePosition 333 //---------------------------------- 334 335 /** 336 * @private 337 * The baselinePosition of a TabNavigator is calculated 338 * for the label of the first tab. 339 * If there are no children, a child is temporarily added 340 * to do the computation. 341 */ 342 override public function get baselinePosition():Number 343 { 344 if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_3_0) 345 return super.baselinePosition; 346 347 if (!validateBaselinePosition()) 348 return NaN; 349 350 var isEmpty:Boolean = numChildren == 0; 351 if (isEmpty) 352 { 353 var child0:Container = new Container(); 354 addChild(child0); 355 validateNow(); 356 } 357 358 var tab0:Button = getTabAt(0); 359 var result:Number = tabBar.y + tab0.y + tab0.baselinePosition; 360 361 if (isEmpty) 362 { 363 removeChildAt(0); 364 validateNow(); 365 } 366 367 return result; 368 } 369 370 //---------------------------------- 371 // contentHeight 372 //---------------------------------- 373 374 /** 375 * @private 376 */ 377 override protected function get contentHeight():Number 378 { 379 var vm:EdgeMetrics = viewMetricsAndPadding; 380 381 var vmTop:Number = vm.top; 382 var vmBottom:Number = vm.bottom; 383 384 if (isNaN(vmTop)) 385 vmTop = 0; 386 if (isNaN(vmBottom)) 387 vmBottom = 0; 388 389 return unscaledHeight - tabBarHeight - vmTop - vmBottom; 390 } 391 392 //---------------------------------- 393 // contentY 394 //---------------------------------- 395 396 /** 397 * @private 398 */ 399 override protected function get contentY():Number 400 { 401 var paddingTop:Number = getStyle("paddingTop"); 402 403 if (isNaN(paddingTop)) 404 paddingTop = 0; 405 406 return tabBarHeight + paddingTop; 407 } 408 409 //-------------------------------------------------------------------------- 410 // 411 // Properties 412 // 413 //-------------------------------------------------------------------------- 414 415 //---------------------------------- 416 // tabBarHeight 417 //---------------------------------- 418 419 /** 420 * A reference to the TabBar inside this TabNavigator. 421 */ 422 protected var tabBar:TabBar; 423 424 //---------------------------------- 425 // tabBarHeight 426 //---------------------------------- 427 428 /** 429 * @private 430 * Height of the tab. 431 */ 432 private function get tabBarHeight():Number 433 { 434 var tabHeight:Number = getStyle("tabHeight"); 435 436 if (isNaN(tabHeight)) 437 tabHeight = tabBar.getExplicitOrMeasuredHeight(); 438 439 return tabHeight - borderMetrics.top; 440 } 441 442 //---------------------------------- 443 // tabBarStyleFilters 444 //---------------------------------- 445 446 /** 447 * The set of styles to pass from the TabNavigator to the tabBar. 448 * @see mx.styles.StyleProxy 449 * @review 450 */ 451 protected function get tabBarStyleFilters():Object 452 { 453 return _tabBarStyleFilters; 454 } 455 456 private static var _tabBarStyleFilters:Object = 457 { 458 "firstTabStyleName" : "firstTabStyleName", 459 "horizontalAlign" : "horizontalAlign", 460 "horizontalGap" : "horizontalGap", 461 "lastTabStyleName" : "lastTabStyleName", 462 "selectedTabTextStyleName" : "selectedTabTextStyleName", 463 "tabStyleName" : "tabStyleName", 464 "tabWidth" : "tabWidth", 465 "verticalAlign" : "verticalAlign", 466 "verticalGap" : "verticalGap" 467 }; 468 469 //-------------------------------------------------------------------------- 470 // 471 // Overridden methods: UIComponent 472 // 473 //-------------------------------------------------------------------------- 474 475 /** 476 * @private 477 */ 478 override protected function createChildren():void 479 { 480 super.createChildren(); 481 482 if (!tabBar) 483 { 484 tabBar = new TabBar(); 485 tabBar.name = "tabBar"; 486 tabBar.focusEnabled = false; 487 tabBar.styleName = new StyleProxy(this, tabBarStyleFilters); 488 rawChildren.addChild(tabBar); 489 490 if (FlexVersion.compatibilityVersion < FlexVersion.VERSION_3_0) 491 { 492 tabBar.setStyle("paddingTop", 0); 493 tabBar.setStyle("paddingBottom", 0); 494 tabBar.setStyle("borderStyle", "none"); 495 } 496 } 497 } 498 499 /** 500 * @private 501 */ 502 override protected function commitProperties():void 503 { 504 super.commitProperties(); 505 506 // Things get a bit tricky here... we need to 507 // wait until our children have been instantiated 508 // before we can attach the tab bar to us. 509 if (tabBar && tabBar.dataProvider != this && 510 numChildren > 0 && getChildAt(0)) 511 { 512 tabBar.dataProvider = this; 513 } 514 } 515 516 /** 517 * Calculates the default sizes and mininum and maximum values of this 518 * TabNavigator container. 519 * See the <code>UIComponent.measure()</code> method for more information 520 * about the <code>measure()</code> method. 521 * 522 * <p>The TabNavigator container uses the same measurement logic as the 523 * <code>ViewStack</code> container, with two modifications: 524 * First, it increases the value of the 525 * <code>measuredHeight</code> and 526 * <code>measuredMinHeight</code> properties to accomodate the tabs. 527 * Second, it increases the value of the 528 * <code>measuredWidth</code> property if necessary 529 * to ensure that each tab can be at least 30 pixels wide.</p> 530 * 531 * @see mx.core.UIComponent#measure() 532 * @see mx.containers.ViewStack#measure() 533 */ 534 override protected function measure():void 535 { 536 // Only measure once. Thereafter, we'll just use cached values. 537 // We need to copy the cached values into the measured fields 538 // again to handle the case where scaleX or scaleY is not 1.0. 539 // When the TabNavigator is zoomed, code in UIComponent.measureSizes 540 // scales the measuredWidth/Height values every time that 541 // measureSizes is called. (bug 100749) 542 543 // This must be done before the call to super.measure(), otherwise 544 // we don't get the first measurement correct. 545 if (vsPreferredWidth && !resizeToContent) 546 { 547 measuredMinWidth = vsMinWidth; 548 measuredMinHeight = vsMinHeight; 549 measuredWidth = vsPreferredWidth; 550 measuredHeight = vsPreferredHeight; 551 return; 552 } 553 554 super.measure(); 555 556 var addedHeight:Number = tabBarHeight; 557 measuredMinHeight += addedHeight; 558 measuredHeight += addedHeight; 559 560 // Make sure there is at least enough room 561 // to draw all tabs at their minimum size. 562 var tabWidth:Number = getStyle("tabWidth"); 563 if (isNaN(tabWidth)) 564 tabWidth = 0; 565 566 var minTabBarWidth:Number = 567 numChildren * Math.max(tabWidth, MIN_TAB_WIDTH); 568 569 // Add view metrics. 570 var vm:EdgeMetrics = viewMetrics; 571 minTabBarWidth += (vm.left + vm.right); 572 573 // Add horizontal gaps. 574 if (numChildren > 1) 575 minTabBarWidth += (getStyle("horizontalGap") * (numChildren - 1)); 576 577 if (measuredWidth < minTabBarWidth) 578 measuredWidth = minTabBarWidth; 579 580 // If we're called before instantiateSelectedChild, then bail. 581 // We'll be called again later (instantiateSelectedChild calls 582 // invalidateSize), and we don't want to load values into the 583 // cache until we're fully initialized. (bug 102639) 584 if (selectedChild && Container(selectedChild).numChildrenCreated == -1) 585 return; 586 587 // Don't remember sizes if we don't have any children 588 if (numChildren == 0) 589 return; 590 591 vsMinWidth = measuredMinWidth; 592 vsMinHeight = measuredMinHeight; 593 vsPreferredWidth = measuredWidth; 594 vsPreferredHeight = measuredHeight; 595 } 596 597 /** 598 * Responds to size changes by setting the positions and sizes 599 * of this container's tabs and children. 600 * 601 * For more information about the <code>updateDisplayList()</code> method, 602 * see the <code>UIComponent.updateDisplayList()</code> method. 603 * 604 * <p>A TabNavigator container positions its TabBar container at the top. 605 * The width of the TabBar is set to the width of the 606 * TabNavigator, and the height of the TabBar is set 607 * based on the <code>tabHeight</code> property.</p> 608 * 609 * <p>A TabNavigator container positions and sizes its child containers 610 * underneath the TabBar, using the same logic as in 611 * ViewStack container.</p> 612 * 613 * @param unscaledWidth Specifies the width of the component, in pixels, 614 * in the component's coordinates, regardless of the value of the 615 * <code>scaleX</code> property of the component. 616 * 617 * @param unscaledHeight Specifies the height of the component, in pixels, 618 * in the component's coordinates, regardless of the value of the 619 * <code>scaleY</code> property of the component. 620 * 621 * @see mx.core.UIComponent#updateDisplayList() 622 */ 623 override protected function updateDisplayList(unscaledWidth:Number, 624 unscaledHeight:Number):void 625 { 626 super.updateDisplayList(unscaledWidth, unscaledHeight); 627 628 var bm:EdgeMetrics = borderMetrics; 629 var vm:EdgeMetrics = viewMetrics; 630 var w:Number = unscaledWidth - vm.left - vm.right; 631 632 var th:Number = tabBarHeight + bm.top; 633 var pw:Number = tabBar.getExplicitOrMeasuredWidth(); 634 tabBar.setActualSize(Math.min(w, pw), th); 635 var leftOffset:Number = getStyle("tabOffset"); 636 637 switch (getStyle("horizontalAlign")) 638 { 639 case "left": 640 tabBar.move(0 + leftOffset, tabBar.y); 641 break; 642 case "right": 643 tabBar.move(unscaledWidth - tabBar.width + leftOffset, tabBar.y); 644 break; 645 case "center": 646 tabBar.move((unscaledWidth - tabBar.width) / 2 + leftOffset, tabBar.y); 647 } 648 } 649 650 /** 651 * @private 652 */ 653 override public function drawFocus(isFocused:Boolean):void 654 { 655 // Superclass sets up standard focus glow. 656 super.drawFocus(isFocused); 657 658 if (!parent) 659 return; 660 661 // Clip the glow so it doesn't include the tabs 662 var focusObj:DisplayObject = IUIComponent(parent).focusPane; 663 if (isFocused && !isEffectStarted) 664 { 665 // Normally the focus skin is in front of the object. For TabNavigator 666 // we want it behind. 667 if (focusObj) 668 { 669 if (parent is Container) 670 { 671 var n:int = Container(parent).rawChildren.numChildren; 672 var fci:int = Container(parent).firstChildIndex; 673 // make sure we don't set it past the last index. This happens 674 // if all content children are in a contentpane 675 Container(parent).rawChildren.setChildIndex( 676 focusObj, Math.max(0, (fci == n) ? n - 1 : fci)); 677 } 678 else 679 { 680 parent.setChildIndex(focusObj, 0); 681 } 682 } 683 } 684 else 685 { 686 if (focusObj) 687 { 688 // Move the focus skin back in front of the children, where it 689 // was before we drew focus. 690 if (parent is Container) 691 { 692 Container(parent).rawChildren.setChildIndex( 693 focusObj, Container(parent).rawChildren.numChildren - 1); 694 } 695 else 696 { 697 parent.setChildIndex(focusObj, parent.numChildren - 1); 698 } 699 } 700 } 701 702 tabBar.drawFocus(isFocused); 703 } 704 705 /** 706 * @private 707 */ 708 override protected function adjustFocusRect( 709 object:DisplayObject = null):void 710 { 711 // Superclass does most of the work 712 super.adjustFocusRect(object); 713 714 // Adjust the focus rect so it is below the tabs 715 var focusObj:IFlexDisplayObject = IFlexDisplayObject(getFocusObject()); 716 717 if (focusObj) 718 { 719 focusObj.setActualSize(focusObj.width, focusObj.height - tabBarHeight); 720 focusObj.move(focusObj.x, focusObj.y + tabBarHeight); 721 722 if (focusObj is IInvalidating) 723 IInvalidating(focusObj).validateNow(); 724 725 else if (focusObj is IProgrammaticSkin) 726 IProgrammaticSkin(focusObj).validateNow(); 727 } 728 } 729 730 //-------------------------------------------------------------------------- 731 // 732 // Overridden methods: Container 733 // 734 //-------------------------------------------------------------------------- 735 736 /** 737 * @private 738 */ 739 override protected function layoutChrome(unscaledWidth:Number, 740 unscaledHeight:Number):void 741 { 742 super.layoutChrome(unscaledWidth, unscaledHeight); 743 744 // Move our border so it leaves room for the tabs 745 if (border) 746 { 747 var borderOffset:Number = tabBarHeight; 748 border.setActualSize(unscaledWidth, unscaledHeight - borderOffset); 749 border.move(0, borderOffset); 750 } 751 } 752 753 //-------------------------------------------------------------------------- 754 // 755 // Methods 756 // 757 //-------------------------------------------------------------------------- 758 759 /** 760 * Returns the tab of the navigator's TabBar control at the specified 761 * index. 762 * 763 * @param index Index in the navigator's TabBar control. 764 * 765 * @return The tab at the specified index. 766 */ 767 public function getTabAt(index:int):Button 768 { 769 return Button(tabBar.getChildAt(index)); 770 } 771 772 //-------------------------------------------------------------------------- 773 // 774 // Overridden event handlers: UIComponent 775 // 776 //-------------------------------------------------------------------------- 777 778 /** 779 * @private 780 */ 781 override protected function focusInHandler(event:FocusEvent):void 782 { 783 super.focusInHandler(event); 784 785 // When the TabNavigator has focus, the Focus Manager 786 // should not treat the Enter key as a click on 787 // the default pushbutton. 788 if (event.target == this) 789 focusManager.defaultButtonEnabled = false; 790 } 791 792 /** 793 * @private 794 */ 795 override protected function focusOutHandler(event:FocusEvent):void 796 { 797 super.focusOutHandler(event); 798 799 if (focusManager && event.target == this) 800 focusManager.defaultButtonEnabled = true; 801 } 802 803 import flash.ui.Keyboard; 804 805 /** 806 * @private 807 */ 808 override protected function keyDownHandler(event:KeyboardEvent):void 809 { 810 if (focusManager.getFocus() == this) 811 { 812 // Redispatch the event from the TabBar so that it can handle it. 813 tabBar.dispatchEvent(event); 814 } 815 } 816 817 /** 818 * @private 819 */ 820 mx_internal function getTabBar():TabBar 821 { 822 return tabBar; 823 } 824 825} 826 827} 828