////////////////////////////////////////////////////////////////////////////////
//
// 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.components
{
import flash.desktop.NativeApplication;
import flash.events.Event;
import flash.events.InvokeEvent;
import flash.events.KeyboardEvent;
import mx.core.IVisualElement;
import mx.core.mx_internal;
import mx.events.FlexEvent;
import spark.components.supportClasses.ViewNavigatorApplicationBase;
import spark.components.supportClasses.ViewNavigatorBase;
use namespace mx_internal;
[DefaultProperty("navigators")]
/**
* The TabbedViewNavigatorApplication container defines an application
* with multiple sections.
* The TabbedViewNavigatorApplication container automatically creates
* a TabbedMobileNavigator container.
* The TabbedViewNavigator container creates the TabBar control to
* support navigation among the sections of the application.
*
*
The only allowable child of the TabbedViewNavigatorApplication
* container is ViewNavigator.
* Define one ViewNavigator for each section of the application.
*
* The TabbedViewNavigatorApplication container has the following
* default characteristics:
*
*
* Characteristic |
* Description |
*
*
* Default size |
* 100% high and 100% wide to take up all available screen space. |
*
*
* Child layout |
* Defined by the individual View containers
* that make up the views of the application. |
*
*
* Scroll bars |
* None. If you do add scroll bars, users can scroll the entire application.
* That includes the ActionBar and TabBar area of the application.
* Because you typically do not want those areas of the view to scroll,
* add scroll bars to the individual View containers of the application,
* rather than to the application container itself. |
*
*
* Default skin class |
* spark.skins.mobile.TabbedViewNavigatorApplicationSkin |
*
*
*
* @mxml
*
* The <s:TabbedViewNavigatorApplication>
tag inherits all of the tag
* attributes of its superclass and adds the following tag attributes:
*
*
* <s:TabbedViewNavigatorApplication
* Properties
* navigators="null"
*
* />
*
*
* @see spark.components.TabbedViewNavigator
* @see spark.components.TabBar
* @see spark.skins.mobile.TabbedViewNavigatorApplicationSkin
* @includeExample examples/TabbedViewNavigatorApplicationExample.mxml -noswf
*
* @langversion 3.0
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public class TabbedViewNavigatorApplication extends ViewNavigatorApplicationBase
{
//--------------------------------------------------------------------------
//
// Skin Parts
//
//--------------------------------------------------------------------------
[Bindable]
[SkinPart(required="false")]
/**
* The main tabbedNavigator for the application.
*
* @langversion 3.0
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var tabbedNavigator:TabbedViewNavigator;
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @langversion 3.0
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function TabbedViewNavigatorApplication()
{
super();
NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, activateHandler);
}
//--------------------------------------------------------------------------
//
// Variables
//
//--------------------------------------------------------------------------
/**
* @private
*/
private var navigatorProperties:Object = {};
//----------------------------------
// activeView
//----------------------------------
/**
* @private
*/
override mx_internal function get activeView():View
{
if (tabbedNavigator)
return tabbedNavigator.activeView;
return null;
}
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// exitApplicationOnBackKey
//----------------------------------
/**
* @private
*/
override mx_internal function get exitApplicationOnBackKey():Boolean
{
if (tabbedNavigator)
return tabbedNavigator.exitApplicationOnBackKey;
return super.exitApplicationOnBackKey;
}
//----------------------------------
// navigators
//----------------------------------
/**
* @copy TabbedViewNavigator#navigators
*
* @default null
*
* @langversion 3.0
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function get navigators():Vector.
{
if (tabbedNavigator)
return tabbedNavigator.navigators;
else
return navigatorProperties.navigators;
}
/**
* @private
*/
public function set navigators(value:Vector.):void
{
if (tabbedNavigator)
tabbedNavigator.navigators = value;
else
navigatorProperties.navigators = value;
}
//--------------------------------------------------------------------------
//
// Private Methods
//
//--------------------------------------------------------------------------
/**
* @private
* Activates the current view of the application if one exists. This
* method doesn't do anything at initial launch because the activate
* event isn't dispatched when the application is first launched. Only
* the invoke event is.
*/
private function activateHandler(event:Event):void
{
// Activate the top most view of the navigator if it exists. Note that
// in some launch situations, this will occur before the stage has properly
// resized itself. The orientation state of the view will be manually
// updated when the stage RESIZE event is received. See invokeHandler
// and stage_resizeHandler.
if (tabbedNavigator && tabbedNavigator.activeView)
{
// Set the stage focus to the navigator's active view
tabbedNavigator.updateFocus();
if (!tabbedNavigator.activeView.isActive)
tabbedNavigator.activeView.setActive(true);
}
}
//--------------------------------------------------------------------------
//
// Overridden Methods: ViewNavigatorApplicationBase
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function invokeHandler(event:InvokeEvent):void
{
super.invokeHandler(event);
// If the navigator and view are created, this means that the application
// is restoring its state after being suspended by the operating system.
// In this case, the activeView is currently deactivated and it orientation
// state could potentially be wrong. Wait for the next stage resize event
// so that the runtime has a chance to discover its orientation and then
// properly update and activate the view
if (tabbedNavigator)
{
if (tabbedNavigator.activeView)
systemManager.stage.addEventListener(Event.RESIZE, stage_resizeHandler, false, 0, true);
// Set the stage focus to the navigator's active view
tabbedNavigator.updateFocus();
}
}
/**
* @private
* This method is called on the first resize event after an application
* has been invoked after being suspended in the background.
*/
private function stage_resizeHandler(event:Event):void
{
systemManager.stage.removeEventListener(Event.RESIZE, stage_resizeHandler);
// Update the orientaion state of the view because at this
// point the runtime doesn't dispatch stage orientation events.
activeView.updateOrientationState();
}
/**
* @private
*/
override protected function deactivateHandler(event:Event):void
{
if (tabbedNavigator && tabbedNavigator.activeView)
tabbedNavigator.activeView.setActive(false);
// super is called after so that the active view can get the
// viewDeactive event before the persistence process begins.
super.deactivateHandler(event);
}
/**
* @private
*/
override protected function backKeyUpHandler(event:KeyboardEvent):void
{
super.backKeyUpHandler(event);
if (viewMenuOpen)
viewMenuOpen = false;
else if (tabbedNavigator)
tabbedNavigator.backKeyUpHandler();
}
/**
* @private
*/
override protected function saveNavigatorState():void
{
super.saveNavigatorState();
if (navigators.length > 0)
persistenceManager.setProperty("navigatorState", tabbedNavigator.saveViewData());
}
/**
* @private
*/
override protected function loadNavigatorState():void
{
super.loadNavigatorState();
var savedState:Object = persistenceManager.getProperty("navigatorState");
if (savedState)
tabbedNavigator.loadViewData(savedState);
}
//--------------------------------------------------------------------------
//
// Overridden methods: SkinnableContainer
//
//--------------------------------------------------------------------------
/**
* @private
* Since this class doesn't have and children and serves as proxy for
* TabbedViewNavigator, we consider our deferredContent created as
* long as we have a valid tabbedNavigator skinPart. This allows the
* states includeIn and excludeFrom mechanism from working with this
* component's provided MXML.
*/
override public function get deferredContentCreated():Boolean
{
if (tabbedNavigator)
return true;
return false;
}
//--------------------------------------------------------------------------
//
// Overridden methods: UIComponent
//
//--------------------------------------------------------------------------
/**
* @private
*/
override protected function partAdded(partName:String, instance:Object):void
{
super.partAdded(partName, instance);
if (instance == tabbedNavigator)
{
if (navigatorProperties.navigators !== undefined)
{
tabbedNavigator.navigators = navigatorProperties.navigators;
}
// We consider our content created when the tabbedNavigator
// skinPart is added. This allows states to know when all deferred content
// has been created.
if (hasEventListener(FlexEvent.CONTENT_CREATION_COMPLETE))
dispatchEvent(new FlexEvent(FlexEvent.CONTENT_CREATION_COMPLETE));
// Set the stage focus to the navigator
systemManager.stage.focus = tabbedNavigator;
}
}
//--------------------------------------------------------------------------
//
// Overridden methods: IVisualElementContainer
//
//--------------------------------------------------------------------------
/**
* TabbedViewNavigatorApplication proxies the IVisualElementContainer
* interface to its tabbedNavigator skinPart.
*/
/**
* @private
*/
override public function get numElements():int
{
if (tabbedNavigator)
return tabbedNavigator.numElements;
return 0;
}
/**
* @private
*/
override public function getElementAt(index:int):IVisualElement
{
if (tabbedNavigator)
return tabbedNavigator.getElementAt(index);
return null;
}
//----------------------------------
// Visual Element addition
//----------------------------------
/**
* @private
*/
override public function addElement(element:IVisualElement):IVisualElement
{
if (tabbedNavigator)
return tabbedNavigator.addElement(element);
// TODO (chiedozi): Consider throwing an exception in this case
return null;
}
/**
* @private
*/
override public function addElementAt(element:IVisualElement, index:int):IVisualElement
{
if (tabbedNavigator)
return tabbedNavigator.addElementAt(element, index);
// TODO (chiedozi): Consider throwing an exception in this case
return null;
}
//----------------------------------
// Visual Element removal
//----------------------------------
/**
* @private
*/
override public function removeElement(element:IVisualElement):IVisualElement
{
if (tabbedNavigator)
return tabbedNavigator.removeElement(element);
// TODO (chiedozi): Consider throwing an exception in this case
return null;
}
/**
* @private
*/
override public function removeElementAt(index:int):IVisualElement
{
if (tabbedNavigator)
return tabbedNavigator.removeElementAt(index);
// TODO (chiedozi): Consider throwing an exception in this case
return null;
}
/**
* @private
*/
override public function removeAllElements():void
{
if (tabbedNavigator)
return tabbedNavigator.removeAllElements();
}
//----------------------------------
// Visual Element index
//----------------------------------
/**
* @private
*/
override public function getElementIndex(element:IVisualElement):int
{
if (tabbedNavigator)
return tabbedNavigator.getElementIndex(element);
throw ArgumentError(resourceManager.getString("components", "elementNotFoundInGroup", [element]));
}
/**
* @private
*/
override public function setElementIndex(element:IVisualElement, index:int):void
{
if (tabbedNavigator)
tabbedNavigator.setElementIndex(element, index);
throw ArgumentError(resourceManager.getString("components", "elementNotFoundInGroup", [element]));
}
//----------------------------------
// Visual Element swapping
//----------------------------------
/**
* @private
*/
override public function swapElements(element1:IVisualElement, element2:IVisualElement):void
{
if (tabbedNavigator)
tabbedNavigator.swapElements(element1, element2);
throw ArgumentError(resourceManager.getString("components", "elementNotFoundInGroup", [element1]));
}
/**
* @private
*/
override public function swapElementsAt(index1:int, index2:int):void
{
if (tabbedNavigator)
tabbedNavigator.swapElementsAt(index1, index2);
throw new RangeError(resourceManager.getString("components", "indexOutOfRange", [index1]));
}
}
}