예제 #1
0
        async Task <bool> PopToNavigationState(NavigationState state)
        {
            int index = navigationStateStack.FindIndex((ns) => ns == state);

            if (index == -1)
            {
                return(false);
            }
            for (int i = navigationStateStack.Count - 1; i > index; i--)
            {
                if (!await navigationStateStack [i].Hide())
                {
                    return(false);
                }
                if (!await navigationStateStack [i].Unload())
                {
                    return(false);
                }
                navigationStateStack [i].ScreenState.Dispose();
                navigationStateStack.RemoveAt(i);
                if (!await App.Current.Navigation.Pop(null))
                {
                    return(false);
                }
            }
            if (!await state.Show())
            {
                return(false);
            }
            await App.Current.EventsBroker.Publish(new NavigationEvent { Name = state.Name });

            return(await App.Current.Navigation.Push(state.ScreenState.Panel));
        }
예제 #2
0
        public async Task <bool> Unload()
        {
            NavigationStateStatus newStatus = NavigationStateStatus.Unloaded;

            if (IsAlreadyInSameStatus(newStatus))
            {
                return(true);
            }

            bool result = await ScreenState.UnloadState();

            if (result)
            {
                UpdateState(newStatus);
            }

            if (freezingState != null && freezingState.Completion.Task.Status != TaskStatus.RanToCompletion)
            {
                freezingState.Completion.SetResult(true);
                freezingState = null;
            }

            // FIXME: when quit is done a double home navigation is done
            // this causes that the hide/unload of the state is done twice
            // because the stack is not empty, the hide state is the one creating
            // the second home transition
            if (Completion.Task.Status != TaskStatus.RanToCompletion && completeWhenUnload)
            {
                Completion.SetResult(result);
            }

            return(result);
        }
예제 #3
0
        public async Task <bool> Unfreeze()
        {
            NavigationStateStatus newStatus = NavigationStateStatus.Shown;

            if (IsAlreadyInSameStatus(newStatus))
            {
                return(true);
            }

            bool result = await ScreenState.UnfreezeState();

            if (result)
            {
                UpdateState(newStatus);
            }
            var freezingStateMemento = freezingState;

            freezingState = null;
            if (freezingStateMemento.Completion.Task.Status != TaskStatus.RanToCompletion)
            {
                freezingStateMemento.Completion.SetResult(result);
            }

            return(result);
        }
예제 #4
0
        async Task <bool> PopNavigationState()
        {
            NavigationState navigationState = navigationStateStack [navigationStateStack.Count - 1];
            IScreenState    screenToPop     = navigationState.ScreenState;

            navigationStateStack.RemoveAt(navigationStateStack.Count - 1);

            NavigationState lastState = LastNavigationState();

            if (!await screenToPop.HideState())
            {
                return(false);
            }
            if (!await App.Current.Navigation.Pop(lastState?.ScreenState.Panel))
            {
                return(false);
            }
            await App.Current.EventsBroker.Publish(new NavigationEvent { Name = Current.Name });

            if (!await navigationState.Unload())
            {
                return(false);
            }
            screenToPop.Dispose();
            return(true);
        }
예제 #5
0
        async Task <bool> PushNavigationState(string transition, IScreenState state)
        {
            NavigationState navState;

            if (transition == home?.Name)
            {
                navState = home;
            }
            else
            {
                navState = new NavigationState(transition, state);
                navigationStateStack.Add(navState);
            }
            if (!await App.Current.Navigation.Push(state.Panel))
            {
                return(false);
            }
            if (!await navState.Show())
            {
                return(false);
            }
            await App.Current.EventsBroker.Publish(new NavigationEvent { Name = transition });

            return(true);
        }
예제 #6
0
        /// <summary>
        /// Moves the back to previous transition. It also considers Home name transition and goes back home
        /// </summary>
        /// <returns>Ture: If transition could be performed. False otherwise</returns>
        /// <param name="transition">Transition name</param>
        public async Task <bool> MoveBackTo(string transition)
        {
            try {
                NavigationState state = LastStateFromTransition(transition);
                if (state == null)
                {
                    Log.Debug("Moving failed because transition " + transition + " is not in history moves");
                    return(false);
                }
                if (!CanMove(state))
                {
                    return(false);
                }

                if (home != null && state == home)
                {
                    return(await MoveToHome());
                }

                //Check for modals to delete them.
                if (!await PopAllModalStates())
                {
                    return(false);
                }
                return(await PopToNavigationState(state));
            } catch (Exception ex) {
                Log.Exception(ex);
                throw;
            }
        }
예제 #7
0
        public override bool Equals(object obj)
        {
            NavigationState navState = obj as NavigationState;

            if (navState == null)
            {
                return(false);
            }
            return(navState.Name == Name && navState.ScreenState == ScreenState);
        }
예제 #8
0
        // FIXME: Enqueue instead of blocking navigation
        bool CanMove(NavigationState current)
        {
            bool canMove = current == null ||
                           (current.CurrentStatus == NavigationStateStatus.Shown ||
                            current.CurrentStatus == NavigationStateStatus.Hidden);

            if (canMove)
            {
                App.Current.EventsBroker.Publish <NavigatingEvent> ();
            }
            return(canMove);
        }
예제 #9
0
        async Task <bool> PushModalState(NavigationState state, IScreenState current)
        {
            modalStateStack.Add(state);
            if (!await state.Show())
            {
                return(false);
            }

            await App.Current.EventsBroker.Publish(new NavigationEvent { Name = state.ScreenState.Name, IsModal = true });

            await App.Current.Navigation.PushModal(state.ScreenState.Panel, current.Panel);

            return(true);
        }
예제 #10
0
        /// <summary>
        /// Moves Back to the previous transition Panel or Modal.
        /// </summary>
        /// <returns>True: If the transition could be performed. False Otherwise</returns>
        public async Task <bool> MoveBack()
        {
            if (modalStateStack.Count == 0 && navigationStateStack.Count <= 1 && home == null)
            {
                Log.Debug("Moving back failed because is last transition and there isn't any home");
                return(false);
            }

            try {
                bool            triggeredFromModal;
                NavigationState current = LastState(out triggeredFromModal);
                if (!CanMove(current))
                {
                    return(false);
                }
                Log.Debug("Moving Back");
                if (current != null)
                {
                    if (!triggeredFromModal)
                    {
                        if (!await PopNavigationState())
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        if (!await PopModalState(current))
                        {
                            return(false);
                        }
                    }

                    current = LastState();
                    if (triggeredFromModal)
                    {
                        return(await current.Unfreeze());
                    }
                    else
                    {
                        return(await current.Show());
                    }
                }
                return(true);
            } catch (Exception ex) {
                Log.Exception(ex);
                throw;
            }
        }
예제 #11
0
 /// <summary>
 /// Sets the home transition. Needs to be registered first.
 /// </summary>
 /// <returns>True if the home transition could be executed. False otherwise</returns>
 /// <param name="transition">Transition.</param>
 public async Task <bool> SetHomeTransition(string transition, dynamic properties)
 {
     try {
         Log.Debug("Setting Home to " + transition);
         IScreenState homeState = destination [transition] ();
         if (!await homeState.LoadState(properties))
         {
             return(false);
         }
         home = new NavigationState(transition, homeState);
         return(await MoveToHome(true));
     } catch (Exception ex) {
         Log.Exception(ex);
         throw;
     }
 }
예제 #12
0
        /// <summary>
        /// Moves to a Modal window
        /// </summary>
        /// <returns>True if the Move could be performed. False otherwise</returns>
        /// <param name="transition">Transition.</param>
        public async Task <bool> MoveToModal(string transition, dynamic properties, bool waitUntilClose = false)
        {
            Log.Debug("Moving to " + transition + " in modal mode");

            if (!destination.ContainsKey(transition))
            {
                Log.Debug("Moving failed because transition " + transition + " is not in destination dictionary.");
                return(false);
            }

            try {
                IScreenState    state           = destination [transition] ();
                NavigationState transitionState = new NavigationState(transition, state, !waitUntilClose);

                NavigationState lastState = LastState();
                if (!CanMove(lastState))
                {
                    return(false);
                }

                if (!await lastState.Freeze(transitionState))
                {
                    return(false);
                }

                bool ok = await state.LoadState(properties);

                if (ok)
                {
                    await PushModalState(transitionState, LastState()?.ScreenState);

                    NavigationState resultantState = LastState();
                    if (waitUntilClose && resultantState.Name == transition)
                    {
                        await resultantState.Completion.Task;
                    }
                }
                else
                {
                    Log.Debug("Moving failed because panel " + state.Name + " cannot move.");
                }
                return(ok);
            } catch (Exception ex) {
                Log.Exception(ex);
                throw;
            }
        }
예제 #13
0
        public async Task <bool> Freeze(NavigationState freezingState)
        {
            NavigationStateStatus newStatus = NavigationStateStatus.Frozen;

            if (IsAlreadyInSameStatus(newStatus))
            {
                return(true);
            }

            this.freezingState = freezingState;
            bool result = await ScreenState.FreezeState();

            if (result)
            {
                UpdateState(newStatus);
            }
            return(result);
        }
예제 #14
0
        async Task <bool> PopModalState(NavigationState current)
        {
            NavigationState navigationState = modalStateStack [modalStateStack.Count - 1];
            IScreenState    screenToPop     = navigationState.ScreenState;

            if (!await screenToPop.HideState())
            {
                return(false);
            }
            if (!await navigationState.Unload())
            {
                return(false);
            }
            modalStateStack.RemoveAt(modalStateStack.Count - 1);
            await App.Current.EventsBroker.Publish(new NavigationEvent { Name = Current.Name, IsModal = modalStateStack.Any() });

            await App.Current.Navigation.PopModal(screenToPop.Panel);

            screenToPop.Dispose();
            return(true);
        }
예제 #15
0
        /// <summary>
        /// Moves to a Panel inside the main window. If it has some previous modal windows
        /// It Pops them all.
        /// </summary>
        /// <returns>True if the move could be performed. False otherwise</returns>
        /// <param name="transition">Transition.</param>
        public async Task <bool> MoveTo(string transition, dynamic properties, bool emptyStack = false, bool forceMove = false)
        {
            Log.Debug("Moving to " + transition);

            if (!destination.ContainsKey(transition))
            {
                Log.Debug("Moving failed because transition " + transition + " is not in destination dictionary.");
                return(false);
            }

            try {
                bool            isModal   = false;
                NavigationState lastState = LastState(out isModal);
                if (!forceMove && lastState != null && lastState.Name == transition)
                {
                    Log.Debug("Not moved to " + transition + "because we're already there");
                    return(true);
                }
                if (!CanMove(lastState) && !forceMove)
                {
                    return(false);
                }
                if (emptyStack)
                {
                    if (!await EmptyStateStack())
                    {
                        return(false);
                    }
                    if (lastState == home && home.Name != transition)
                    {
                        if (!await lastState.Hide())
                        {
                            Log.Debug("Moving failed because home panel " + lastState.Name + " cannot move.");
                            return(false);
                        }
                    }
                }
                else if (isModal)
                {
                    if (!await PopAllModalStates())
                    {
                        return(false);
                    }
                }
                else if (lastState != null)
                {
                    if (!await lastState.Hide())
                    {
                        Log.Debug("Moving failed because panel " + lastState.Name + " cannot move.");
                        return(false);
                    }
                }

                IScreenState state;
                bool         isHome = transition == home?.Name;
                if (isHome)
                {
                    state = home.ScreenState;
                }
                else
                {
                    state = destination [transition] ();
                    if (!await state.LoadState(properties))
                    {
                        // If the transition failed and the stack is empty, load the home,
                        // otherwise show again the last state that was hidden at the start of the
                        // MoveTo
                        if (emptyStack)
                        {
                            await PushNavigationState(home.Name, home.ScreenState);
                        }
                        else
                        {
                            if (!await lastState.Show())
                            {
                                // This shouldn't fail... but just in case
                                Log.Error("Last state couldn't be shown again, we'll move back home");
                                await PushNavigationState(home.Name, home.ScreenState);
                            }
                        }
                        return(false);
                    }
                }

                return(await PushNavigationState(transition, state));
            } catch (Exception ex) {
                Log.Exception(ex);
                throw;
            }
        }