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
12package spark.components.supportClasses
13{
14import flash.desktop.NativeApplication;
15import flash.display.Graphics;
16import flash.display.InteractiveObject;
17import flash.display.Sprite;
18import flash.display.StageOrientation;
19import flash.events.Event;
20import flash.events.InvokeEvent;
21import flash.events.KeyboardEvent;
22import flash.events.MouseEvent;
23import flash.events.StageOrientationEvent;
24import flash.net.registerClassAlias;
25import flash.system.Capabilities;
26import flash.ui.Keyboard;
27
28import mx.core.IFactory;
29import mx.core.mx_internal;
30import mx.events.FlexEvent;
31import mx.events.FlexMouseEvent;
32import mx.events.ResizeEvent;
33import mx.managers.SystemManager;
34
35import spark.components.Application;
36import spark.components.View;
37import spark.components.ViewMenu;
38import spark.components.ViewMenuItem;
39import spark.events.PopUpEvent;
40import spark.managers.IPersistenceManager;
41import spark.managers.PersistenceManager;
42
43use namespace mx_internal;
44
45//--------------------------------------
46//  Events
47//--------------------------------------
48
49/**
50 *  Dispatched before the application attempts
51 *  to restore its previously saved state when the application is being
52 *  launched.
53 *  Calling <code>preventDefault</code> on this event
54 *  prevents the application state from being restored.
55 *
56 *  @eventType mx.events.FlexEvent.NAVIGATOR_STATE_LOADING
57 *
58 *  @langversion 3.0
59 *  @playerversion AIR 2.5
60 *  @productversion Flex 4.5
61 */
62[Event(name="navigatorStateLoading", type="mx.events.FlexEvent")]
63
64/**
65 *  Dispatched before the application attempts
66 *  to persist its state when the application being suspended or exited.
67 *  Calling <code>preventDefault</code> on this event prevents the
68 *  application state from being saved.
69 *
70 *  @eventType mx.events.FlexEvent.NAVIGATOR_STATE_SAVING
71 *
72 *  @langversion 3.0
73 *  @playerversion AIR 2.5
74 *  @productversion Flex 4.5
75 */
76[Event(name="navigatorStateSaving", type="mx.events.FlexEvent")]
77
78//--------------------------------------
79//  Excluded APIs
80//--------------------------------------
81[Exclude(name="controlBarContent", kind="property")]
82[Exclude(name="controlBarGroup", kind="property")]
83[Exclude(name="controlBarLayout", kind="property")]
84[Exclude(name="controlBarVisible", kind="property")]
85[Exclude(name="layout", kind="property")]
86[Exclude(name="preloaderChromeColor", kind="property")]
87[Exclude(name="backgroundAlpha", kind="style")]
88
89/**
90 *  The ViewNavigatorApplicationBase class is the base class used for all
91 *  view-based application types.
92 *  This class provides the basic infrastructure for providing
93 *  access to the device application menu, hardware keys, orientation status
94 *  and application session persistence.
95 *
96 *  @mxml <p>The <code>&lt;s:ViewNavigatorApplicationBase&gt;</code> tag inherits
97 *  all of the tag attributes of its superclass and adds the following tag attributes:</p>
98 *
99 *  <pre>
100 *  &lt;s:ViewNavigatorApplicationBase
101 *    <strong>Properties</strong>
102 *    persistNavigatorState="false"
103 *    viewMenuOpen="false"
104 *  /&gt;
105 *  </pre>
106 *
107 *  @see spark.components.ViewNavigatorApplication
108 *  @see spark.components.TabbedViewNavigatorApplication
109 *
110 *  @langversion 3.0
111 *  @playerversion AIR 2.5
112 *  @productversion Flex 4.5
113 */
114public class ViewNavigatorApplicationBase extends Application
115{
116    //--------------------------------------------------------------------------
117    //
118    //  Constructor
119    //
120    //--------------------------------------------------------------------------
121
122    /**
123     *  Constructor
124     *
125     *  @langversion 3.0
126     *  @playerversion AIR 2.5
127     *  @productversion Flex 4.5
128     */
129    public function ViewNavigatorApplicationBase()
130    {
131        super();
132    }
133
134    //--------------------------------------------------------------------------
135    //
136    //  Skin Parts
137    //
138    //--------------------------------------------------------------------------
139
140    [SkinPart(required="false")]
141    /**
142     *  Dynamic skin part that defines the ViewMenu used to display the
143     *  view menu when the menu button is pressed. The default skin uses
144     *  a factory that generates an ViewMenu instance.
145     */
146    public var viewMenu:IFactory;
147
148    //--------------------------------------------------------------------------
149    //
150    //  Variables
151    //
152    //--------------------------------------------------------------------------
153
154    /**
155     *  @private
156     *  Provides access to the active view of the current navigator. This was
157     *  added to provide the ViewMenu access to the active view's viewMenuItems
158     *  property.
159     */
160    mx_internal function get activeView():View
161    {
162        return null;
163    }
164
165    /**
166     *  @private
167     *  This flag indicates when a user has called preventDefault on the
168     *  KeyboardEvent dispatched when the back key is pressed.
169     */
170    private var backKeyEventPreventDefaulted:Boolean = false;
171
172    /**
173     *  @private
174     */
175    private var currentViewMenu:ViewMenu;
176
177    /**
178     *  @private
179     *  This property is used to determine whether the application should
180     *  exit when the back key is pressed.
181     *
182     *  @langversion 3.0
183     *  @playerversion AIR 2.5
184     *  @productversion Flex 4.5
185     */
186    mx_internal function get exitApplicationOnBackKey():Boolean
187    {
188        return true;
189    }
190
191    /**
192     *  @private
193     */
194    private var lastFocus:InteractiveObject;
195
196    /**
197     *  @private
198     *  This flag indicates when a user has called preventDefault on the
199     *  KeyboardEvent dispatched when the menu key is pressed.
200     */
201    private var menuKeyEventPreventDefaulted:Boolean = false;
202
203    /**
204     *  @private
205     */
206    private var mouseShield:Sprite;
207
208    //--------------------------------------------------------------------------
209    //
210    //  Properties
211    //
212    //--------------------------------------------------------------------------
213
214    //----------------------------------
215    //  persistenceManager
216    //----------------------------------
217    private var _persistenceManager:IPersistenceManager;
218
219    /**
220     *  The PersistenceManager object for the application.
221     *  The persistence manager is automatically created on demand
222     *  when accessed for the first time.
223     *  Override the <code>createPersistenceManager()</code>
224     *  method to change the type of persistence manager that is created.
225     *
226     *  <p>The persistence manager automatically saves and restores
227     *  the current view navigator's view stack if the
228     *  <code>persistNavigatorState</code> flag is set to <code>true</code>.
229     *  Data stored in the persistence manager is automatically flushed to disk
230     *  when the application is suspended or exited.</p>
231     *
232     *  <p>The default implementation of the persistence manager uses
233     *  a shared object as it's backing data store.
234     *  All information that is saved to this object must adhere to flash
235     *  AMF rules for object encoding.
236     *  This means that custom classes must be registered through the use
237     *  of <code>flash.net.registerClassAlias</code></p>
238     *
239     *  <p>The default value is an instance of spark.core.managers.PersistenceManager.</p>
240     *
241     *  @see spark.managers.PersistenceManager
242     *
243     *  @langversion 3.0
244     *  @playerversion AIR 2.5
245     *  @productversion Flex 4.5
246     */
247    public function get persistenceManager():IPersistenceManager
248    {
249        if (!_persistenceManager)
250            initializePersistenceManager();
251
252        return _persistenceManager;
253    }
254
255    //----------------------------------
256    //  persistNavigatorState
257    //----------------------------------
258
259    private var _persistNavigatorState:Boolean = false;
260    private var _persistenceInitialized:Boolean = false;
261
262    /**
263     *  Toggles the application session caching feature for the application.
264     *  When enabled, the application automatically saves the current
265     *  view navigator's view stack
266     *  and navigation history to the persistence manager.
267     *  When the application is relaunched, this data is automatically read from
268     *  the persistence store and applied to the application's navigator.
269     *
270     *  <p>When enabled, the application version will be added to the persistence object.
271     *  You can access this information by using the persistence manager's
272     *  <code>getProperty()</code> method and ask for the <code>versionNumber</code> key.</p>
273     *
274     *  <p>When the persistence object is being created, the application dispatches
275     *  a cancelable <code>FlexEvent.NAVIGATOR_STATE_SAVING</code> event when the process
276     *  begins.
277     *  If you cancel the <code>NAVIGATOR_STATE_SAVING</code> event,
278     *  the persistence object is not created.
279     *  Similarly, when this information is being restored to the application, a cancelable
280     *  <code>FlexEvent.NAVIGATOR_STATE_LOADING</code> event is dispatched.
281     *  Canceling the <code>NAVIGATOR_STATE_LOADING</code> event prevents the navigation
282     *  data from being restored.</p>
283     *
284     *  <p>The <code>persistNavigatorState</code> flag must be set to <code>true</code> before
285     *  the application initializes itself for the navigator's state to be automatically
286     *  restored.</p>
287     *
288     *  @default false
289     *
290     *  @langversion 3.0
291     *  @playerversion AIR 2.5
292     *  @productversion Flex 4.5
293     */
294    public function get persistNavigatorState():Boolean
295    {
296        return _persistNavigatorState;
297    }
298
299    /**
300     * @private
301     */
302    public function set persistNavigatorState(value:Boolean):void
303    {
304        _persistNavigatorState = value;
305
306        // If this flag is set to true at runtime, we will need to initialize
307        // the persistence manager if it hasn't been already
308        if (initialized && _persistNavigatorState && !_persistenceInitialized)
309            initializePersistenceManager();
310    }
311
312    //----------------------------------
313    //  viewMenuOpen
314    //----------------------------------
315
316    /**
317     *  Opens the view menu if set to <code>true</code>,
318     *  and closes it if set to <code>false</code>.
319     *
320     *  @default false
321     *
322     *  @langversion 3.0
323     *  @playerversion AIR 2.5
324     *  @productversion Flex 4.5
325     */
326    public function get viewMenuOpen():Boolean
327    {
328        return currentViewMenu && currentViewMenu.isOpen;
329    }
330
331    /**
332     *  @private
333     */
334    public function set viewMenuOpen(value:Boolean):void
335    {
336        if (value == viewMenuOpen)
337            return;
338
339        if (!viewMenu || !activeView.viewMenuItems || activeView.viewMenuItems.length == 0)
340            return;
341
342        if (value)
343            openViewMenu();
344        else
345            closeViewMenu();
346    }
347
348    //--------------------------------------------------------------------------
349    //
350    //  Methods
351    //
352    //--------------------------------------------------------------------------
353
354    /**
355     *  This method is called when the application is invoked by the
356     *  operating system in response to
357     *  an <code>InvokeEvent.INVOKEevent</code> event.
358     *
359     *  @param event The InvokeEvent object.
360     *
361     *  @langversion 3.0
362     *  @playerversion AIR 2.5
363     *  @productversion Flex 4.5
364     */
365    protected function invokeHandler(event:InvokeEvent):void
366    {
367        addDeactivateListeners();
368    }
369
370
371    /**
372     *  @private
373     *  Adds the deactivate handlers when the application is reactivated.
374     */
375    private function activateHandler(event:Event):void
376    {
377        addDeactivateListeners();
378    }
379
380    /**
381     *  Called when the application is exiting or being
382     *  sent to the background by the operating system.
383     *  If <code>persistNavigatorState</code> is <code>true</code>,
384     *  then the application begins the state saving process.
385     *
386     *  @param event The event object for the NAVIGATOR_STATE_SAVING event.
387     *
388     *  @langversion 3.0
389     *  @playerversion AIR 2.5
390     *  @productversion Flex 4.5
391     */
392    protected function deactivateHandler(event:Event):void
393    {
394        // When the deactiveHandler is called, the application is being
395        // suspended or exited.  Remove the deactivate listeners so that
396        // we don't persist data multiple times in the case a deactivate
397        // and exiting event are received in the same sequence
398        removeDeactivateListeners();
399
400        // Check if the application state should be persisted
401        if (persistNavigatorState)
402        {
403            // Dispatch event for saving persistence data
404            var eventCanceled:Boolean = false;
405            if (hasEventListener(FlexEvent.NAVIGATOR_STATE_SAVING))
406                eventCanceled = !dispatchEvent(new FlexEvent(FlexEvent.NAVIGATOR_STATE_SAVING,
407                                                                false, true));
408
409            if (!eventCanceled)
410            {
411                saveNavigatorState();
412            }
413        }
414
415        // Always flush the persistence manager to disk if it exists
416        if (_persistenceManager)
417        {
418            persistenceManager.save();
419        }
420    }
421
422    /**
423     *  Called when the application's hardware back key is pressed
424     *  by the user.
425     *
426     *  @param event The event object generated by the key press.
427     *
428     *  @langversion 3.0
429     *  @playerversion AIR 2.5
430     *  @productversion Flex 4.5
431     */
432    protected function backKeyUpHandler(event:KeyboardEvent):void
433    {
434    }
435
436    /**
437     *  Called when the menu key is pressed.
438     *  By default, this method opens or closes the ViewMenu object.
439     *
440     *  @param event The KeyboardEvent object associated with the
441     *  menu key being pressed.
442     *
443     *  @see spark.components.ViewMenu
444     *
445     *  @langversion 3.0
446     *  @playerversion AIR 2.5
447     *  @productversion Flex 4.5
448     */
449    protected function menuKeyUpHandler(event:KeyboardEvent):void
450    {
451        if (activeView && !activeView.menuKeyHandledByView())
452            viewMenuOpen = !viewMenuOpen;
453    }
454
455    /**
456     *  Creates the persistence manager for the application.
457     *  This method is called automatically when the persistence manager is
458     *  accessed for the first time, or if the <code>persistNavigatorState</code> property
459     *  is set to <code>true</code> on the application.
460     *
461     *  @return An IPersistenceManager manager object.
462     *
463     *  @langversion 3.0
464     *  @playerversion AIR 2.5
465     *  @productversion Flex 4.5
466     */
467    protected function createPersistenceManager():IPersistenceManager
468    {
469        return new PersistenceManager();
470    }
471
472    /**
473     *  Responsible for persisting the application state to the persistence manager.
474     *  This method is called automatically when <code>persistNavigatorState</code>
475     *  is set to <code>true</code>.
476     *  By default, this method saves the application version in the
477     *  <code>versionNumber</code> key of the PersistenceManager object.
478     *
479     *  <p>This method is only called if the <code>FlexEvent.NAVIGATOR_STATE_SAVING</code>
480     *  event is not canceled.</p>
481     *
482     *  @langversion 3.0
483     *  @playerversion AIR 2.5
484     *  @productversion Flex 4.5
485     */
486    protected function saveNavigatorState():void
487    {
488        // Save version number of application
489        var appDescriptor:XML = NativeApplication.nativeApplication.applicationDescriptor;
490        var ns:Namespace = appDescriptor.namespace();
491
492        persistenceManager.setProperty("versionNumber",
493                                        appDescriptor.ns::versionNumber.toString());
494    }
495
496    /**
497     *  Responsible for restoring the application's state when the
498     *  <code>persistNavigatorState</code> property is set to <code>true</code>.
499     *
500     *  <p>This method is only called if the <code>FlexEvent.NAVIGATOR_STATE_LOADING</code>
501     *  event is not canceled.</p>
502     *
503     *  @langversion 3.0
504     *  @playerversion AIR 2.5
505     *  @productversion Flex 4.5
506     */
507    protected function loadNavigatorState():void
508    {
509    }
510
511    //--------------------------------------------------------------------------
512    //
513    //  Private Methods
514    //
515    //--------------------------------------------------------------------------
516
517    /**
518     *  @private
519     *
520     *  @langversion 3.0
521     *  @playerversion AIR 2.5
522     *  @productversion Flex 4.5
523     */
524    private function addApplicationListeners():void
525    {
526		// Listen for keyboard events at a lower priority so that developers
527		// can cancel the default behavior
528        systemManager.stage.addEventListener(KeyboardEvent.KEY_DOWN, deviceKeyDownHandler, false, -1);
529        systemManager.stage.addEventListener(KeyboardEvent.KEY_UP, deviceKeyUpHandler, false, -1);
530        systemManager.stage.addEventListener(StageOrientationEvent.ORIENTATION_CHANGE, orientationChangeHandler);
531        NativeApplication.nativeApplication.addEventListener(InvokeEvent.INVOKE, invokeHandler);
532        NativeApplication.nativeApplication.addEventListener(Event.ACTIVATE, activateHandler);
533    }
534
535    /**
536     *  @private
537     *  Adds listeners for the deactivate event.
538     */
539    private function addDeactivateListeners():void
540    {
541        // The application listens for deactivate and exiting events to determine when
542        // the persistenceManager should save its state to disk.  When the application
543        // is being simulated in ADL on desktop, we don't want to listen for deactivate
544        // because that event is dispatched whenever the window loses focus.  This
545        // could cause persistence to run when a developer doesn't expect it to.
546        // So the DEACTIVATE event is ignored on desktop machines.
547        var os:String = Capabilities.os;
548
549        // TODO (chiedozi): If the framework ever supports Windows Mobile, we'll need to update this check.
550        var runningOnDesktop:Boolean = (os.indexOf("Windows") != -1 || os.indexOf("Mac OS") != -1);
551        if (!runningOnDesktop)
552            NativeApplication.nativeApplication.addEventListener(Event.DEACTIVATE, deactivateHandler);
553
554        NativeApplication.nativeApplication.addEventListener(Event.EXITING, deactivateHandler);
555    }
556
557    /**
558     *  @private
559     *  Remove listeners for the deactivate and exiting events.
560     */
561    private function removeDeactivateListeners():void
562    {
563        var os:String = Capabilities.os;
564
565        // TODO (chiedozi): If the framework ever supports Windows Mobile, we'll need to update this check.
566        var runningOnDesktop:Boolean = (os.indexOf("Windows") != -1 || os.indexOf("Mac OS") != -1);
567        if (!runningOnDesktop)
568            NativeApplication.nativeApplication.removeEventListener(Event.DEACTIVATE, deactivateHandler);
569
570        NativeApplication.nativeApplication.removeEventListener(Event.EXITING, deactivateHandler);
571    }
572
573    /**
574     *  @private
575     *  The key model employeed by ViewNavigatorApplication is to listen for the down
576     *  event but run the back key handling logic on up.  The reasoning for this
577     *  is that the down event is dispatched multiple times while the user
578     *  presses it down.  But the desired back logic should only happen once.
579     *  So when a down event is received, the application only tracks if it has been
580     *  canceled by the developer.
581     *
582     *  It is still necessary to listen to the down key because the application
583     *  needs to cancel the device's default back logic at this stage.  For example,
584     *  on android, when the back key is pressed, the default behavior is to
585     *  suspend the application and return to the home screen.  This functionality
586     *  can only be canceled when the down event is received.
587     */
588    private function deviceKeyDownHandler(event:KeyboardEvent):void
589    {
590        var key:uint = event.keyCode;
591
592        // We want to prevent the default down behavior for back key if
593        // the navigator has a view to pop back to
594        if (key == Keyboard.BACK)
595        {
596            backKeyEventPreventDefaulted = event.isDefaultPrevented();
597
598            if (!exitApplicationOnBackKey)
599                event.preventDefault();
600        }
601        else if (key == Keyboard.MENU)
602        {
603            menuKeyEventPreventDefaulted = event.isDefaultPrevented();
604        }
605    }
606
607    /**
608     *  @private
609     */
610    private function deviceKeyUpHandler(event:KeyboardEvent):void
611    {
612        var key:uint = event.keyCode;
613
614        // If preventDefault() wasn't called on the initial keyDown event
615        // and the application thinks it can cancel the native back behavior,
616        // call the backKeyHandler() method.  Otherwise, the runtime will
617        // handle the back key function.
618
619        // The backKeyEventPreventDefaulted key is always set in the
620        // deviceKeyDownHandler method and so doesn't need to be reset.
621        if (key == Keyboard.BACK && !backKeyEventPreventDefaulted && !exitApplicationOnBackKey)
622            backKeyUpHandler(event);
623        else if (key == Keyboard.MENU && !menuKeyEventPreventDefaulted)
624            menuKeyUpHandler(event);
625    }
626
627    /**
628     *  @private
629     */
630    private function orientationChangeHandler(event:StageOrientationEvent):void
631    {
632        if (currentViewMenu)
633        {
634            // Update size, the position stays at (0,0)
635            currentViewMenu.width = getLayoutBoundsWidth();
636            currentViewMenu.height = getLayoutBoundsHeight();
637        }
638    }
639
640    /**
641     *  @private
642     */
643    private function viewMenu_clickHandler(event:MouseEvent):void
644    {
645        if (event.target is ViewMenuItem)
646            viewMenuOpen = false;
647    }
648
649    /**
650     *  @private
651     */
652    private function viewMenu_mouseDownOutsideHandler(event:FlexMouseEvent):void
653    {
654        viewMenuOpen = false;
655    }
656
657    /**
658     *  @private
659     */
660    private function openViewMenu():void
661    {
662        if (!currentViewMenu)
663        {
664            currentViewMenu = ViewMenu(viewMenu.newInstance());
665            currentViewMenu.items = activeView.viewMenuItems;
666
667            // Remember the focus, we'll restore it when the menu closes
668            lastFocus = getFocus();
669
670            // If the softKeyboard is open, close it first
671            if (isSoftKeyboardActive)
672            {
673                systemManager.stage.focus = null;
674            }
675
676            // Size the menu as big as the app
677            currentViewMenu.width = getLayoutBoundsWidth();
678            currentViewMenu.height = getLayoutBoundsHeight();
679
680            currentViewMenu.setFocus();
681
682            currentViewMenu.addEventListener(MouseEvent.CLICK, viewMenu_clickHandler);
683            currentViewMenu.addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, viewMenu_mouseDownOutsideHandler);
684            currentViewMenu.addEventListener(PopUpEvent.CLOSE, viewMenuClose_handler);
685            currentViewMenu.addEventListener(PopUpEvent.OPEN, viewMenuOpen_handler);
686            addEventListener(ResizeEvent.RESIZE, resizeHandler);
687        }
688
689
690        // Block interaction with the rest of the application
691        attachMouseShield();
692        currentViewMenu.open(this, false /*modal*/);
693    }
694
695    /**
696     *  @private
697     */
698    private function closeViewMenu():void
699    {
700        if (currentViewMenu)
701        {
702            currentViewMenu.close();
703            removeMouseShield();
704        }
705    }
706
707    /**
708     *  @private
709     */
710    private function viewMenuOpen_handler(event:PopUpEvent):void
711    {
712        // Private event for testing
713        if (activeView.hasEventListener("viewMenuOpen"))
714            activeView.dispatchEvent(new Event("viewMenuOpen"));
715    }
716
717    /**
718     *  @private
719     */
720    private function viewMenuClose_handler(event:PopUpEvent):void
721    {
722        currentViewMenu.removeEventListener(PopUpEvent.OPEN, viewMenuOpen_handler);
723        currentViewMenu.removeEventListener(PopUpEvent.CLOSE, viewMenuClose_handler);
724        currentViewMenu.removeEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE, viewMenu_mouseDownOutsideHandler);
725        currentViewMenu.removeEventListener(MouseEvent.CLICK, viewMenu_clickHandler);
726        removeEventListener(ResizeEvent.RESIZE, resizeHandler);
727
728        // Private event for testing
729        if (activeView.hasEventListener("viewMenuClose"))
730            activeView.dispatchEvent(new Event("viewMenuClose"));
731
732        // Clear the caret and validate properties to put back the viewMenu items
733        // in their default state so that next time we open the menu we don't
734        // see an item in a stale "caret" state.
735        currentViewMenu.caretIndex = -1;
736        currentViewMenu.validateProperties();
737
738        currentViewMenu.items = null;
739        currentViewMenu = null;
740
741        // Restore focus
742        systemManager.stage.focus = lastFocus;
743    }
744
745    private function resizeHandler(event:ResizeEvent):void
746    {
747        // Size the menu as big as the app
748        currentViewMenu.width = getLayoutBoundsWidth();
749        currentViewMenu.height = getLayoutBoundsHeight();
750        currentViewMenu.invalidateSkinState();
751    }
752
753    /**
754     *  @private
755     *  Attaches a mouseShield to prevent interaction with the rest of the
756     *  application while the menu is open
757     */
758    mx_internal function attachMouseShield():void
759    {
760        if (skin)
761        {
762            mouseShield = new Sprite();
763
764            var g:Graphics = mouseShield.graphics;
765            g.beginFill(0,0);
766            g.drawRect(0,0,getLayoutBoundsWidth(), getLayoutBoundsHeight());
767            g.endFill();
768
769            skin.addChild(mouseShield);
770        }
771    }
772
773    /**
774     *  @private
775     *  Removes the mouseShield
776     */
777    mx_internal function removeMouseShield():void
778    {
779        if (mouseShield && skin)
780        {
781            skin.removeChild(mouseShield);
782            mouseShield = null;
783        }
784    }
785
786    //--------------------------------------------------------------------------
787    //
788    //  Overridden methods: UIComponent
789    //
790    //--------------------------------------------------------------------------
791
792    /**
793     *  @private
794     */
795    override public function initialize():void
796    {
797        super.initialize();
798
799        addApplicationListeners();
800
801        if (persistNavigatorState)
802        {
803            initializePersistenceManager();
804
805            // Dispatch event for loading persistence data
806            var eventDispatched:Boolean = true;
807            if (hasEventListener(FlexEvent.NAVIGATOR_STATE_LOADING))
808                eventDispatched = dispatchEvent(new FlexEvent(FlexEvent.NAVIGATOR_STATE_LOADING,
809                                                false, true));
810
811            if (eventDispatched)
812            {
813                loadNavigatorState();
814            }
815        }
816    }
817
818
819    //--------------------------------------------------------------------------
820    //
821    //  Private Methods
822    //
823    //--------------------------------------------------------------------------
824
825    /**
826     *  @private
827     *  Method initializes the persistence manager by registering the class
828     *  aliases and loading the shared object.  This method is automatically
829     *  called by the persistNavigatorState setter.
830     */
831    private function initializePersistenceManager():void
832    {
833        // Initialize and load the persisted data.
834        _persistenceManager = createPersistenceManager();
835        _persistenceManager.load();
836
837        _persistenceInitialized = true;
838    }
839}
840}
841
842
843
844
845
846
847
848