/// <summary> /// Exits the current <see cref="IScreen"/>. /// </summary> /// <param name="source">The <see cref="IScreen"/> which last exited.</param> /// <param name="onExiting">An action that is invoked when the current screen allows the exit to continue.</param> private void exitFrom([CanBeNull] IScreen source, Action onExiting = null) { // The current screen is at the top of the stack, it will be the one that is exited var toExit = stack.Pop(); // The next current screen will be resumed if (toExit.OnExiting(CurrentScreen)) { stack.Push(toExit); return; } // we will probably want to change this logic when we support returning to a screen after exiting. toExit.ValidForResume = false; toExit.ValidForPush = false; onExiting?.Invoke(); if (source == null) { // This is the first screen that exited toExit.AsDrawable().Expire(); } else { // This screen exited via a recursive-exit chain. Lifetime is propagated from the parent. toExit.AsDrawable().LifetimeEnd = ((Drawable)source).LifetimeEnd; } ScreenExited?.Invoke(toExit, CurrentScreen); // Resume the next current screen from the exited one resumeFrom(toExit); }
private bool exitFrom([CanBeNull] IScreen source, bool shouldFireExitEvent = true, bool shouldFireResumeEvent = true, IScreen destination = null) { if (stack.Count == 0) { return(false); } // The current screen is at the top of the stack, it will be the one that is exited var toExit = stack.Pop(); // The next current screen will be resumed if (shouldFireExitEvent && toExit.AsDrawable().IsLoaded) { var next = CurrentScreen; // Add the screen back on the stack to allow pushing screens in OnExiting. stack.Push(toExit); // if a screen is !ValidForResume, it should not be allowed to block unless it is the current screen (source == null) // OnExiting should still be called regardless. bool blockRequested = toExit.OnExiting(new ScreenExitEvent(toExit, next, destination ?? next)); if ((source == null || toExit.ValidForResume) && blockRequested) { return(true); } stack.Pop(); } // we will probably want to change this logic when we support returning to a screen after exiting. toExit.ValidForResume = false; toExit.ValidForPush = false; if (source == null) { // This is the first screen that exited toExit.AsDrawable().Expire(); } exited.Add(toExit.AsDrawable()); log($"exit from {getTypeString(toExit)}"); log($"resume to {getTypeString(CurrentScreen)}"); ScreenExited?.Invoke(toExit, CurrentScreen); // Resume the next current screen from the exited one if (shouldFireResumeEvent) { resumeFrom(toExit); } return(false); }
/// <summary> /// Exits the current <see cref="IScreen"/>. /// </summary> /// <param name="source">The <see cref="IScreen"/> which last exited.</param> /// <param name="onExiting">An action that is invoked when the current screen allows the exit to continue.</param> /// <param name="shouldFireExitEvent">Whether <see cref="IScreen.OnExiting"/> should be fired on the exiting screen.</param> /// <param name="shouldFireResumeEvent">Whether <see cref="IScreen.OnResuming"/> should be fired on the resuming screen.</param> private void exitFrom([CanBeNull] IScreen source, Action onExiting = null, bool shouldFireExitEvent = true, bool shouldFireResumeEvent = true) { if (stack.Count == 0) { return; } // The current screen is at the top of the stack, it will be the one that is exited var toExit = stack.Pop(); // The next current screen will be resumed if (shouldFireExitEvent && toExit.AsDrawable().IsLoaded&& toExit.OnExiting(CurrentScreen)) { // If the exit event gets cancelled, add the screen back on the stack. stack.Push(toExit); return; } // we will probably want to change this logic when we support returning to a screen after exiting. toExit.ValidForResume = false; toExit.ValidForPush = false; onExiting?.Invoke(); if (source == null) { // This is the first screen that exited toExit.AsDrawable().Expire(); } exited.Add(toExit.AsDrawable()); ScreenExited?.Invoke(toExit, CurrentScreen); // Resume the next current screen from the exited one if (shouldFireResumeEvent) { resumeFrom(toExit); } }