internal void Push(IScreen source, IScreen newScreen)
        {
            if (stack.Contains(newScreen))
            {
                throw new ScreenAlreadyEnteredException();
            }

            if (source == null && stack.Count > 0)
            {
                throw new InvalidOperationException($"A source must be provided when pushing to a non-empty {nameof(ScreenStack)}");
            }

            if (newScreen.AsDrawable().RemoveWhenNotAlive)
            {
                throw new ScreenWillBeRemovedOnPushException(newScreen.GetType());
            }

            // Suspend the current screen, if there is one
            if (source != null && source != stack.Peek())
            {
                throw new ScreenNotCurrentException(nameof(Push));
            }

            var newScreenDrawable = newScreen.AsDrawable();

            if (newScreenDrawable.IsLoaded)
            {
                throw new InvalidOperationException("A screen should not be loaded before being pushed.");
            }

            if (suspendImmediately)
            {
                suspend(source, newScreen);
            }

            stack.Push(newScreen);
            ScreenPushed?.Invoke(source, newScreen);

            // this needs to be queued here before the load is begun so it preceed any potential OnSuspending event (also attached to OnLoadComplete).
            newScreenDrawable.OnLoadComplete += _ => newScreen.OnEntering(new ScreenTransitionEvent(source, newScreen));

            if (source == null)
            {
                // this is the first screen to be loaded.
                if (LoadState >= LoadState.Ready)
                {
                    LoadScreen(this, newScreenDrawable, () => finishPush(null, newScreen));
                }
                else
                {
                    log($"scheduling push {getTypeString(newScreen)}");
                    Schedule(() => finishPush(null, newScreen));
                }
            }
            else
            {
                LoadScreen((CompositeDrawable)source, newScreenDrawable, () => finishPush(source, newScreen));
            }
        }
示例#2
0
        internal void Push(IScreen source, IScreen newScreen)
        {
            if (stack.Contains(newScreen))
            {
                throw new ScreenAlreadyEnteredException();
            }

            if (source == null && stack.Count > 0)
            {
                throw new InvalidOperationException($"A source must be provided when pushing to a non-empty {nameof(ScreenStack)}");
            }

            if (newScreen.AsDrawable().RemoveWhenNotAlive)
            {
                throw new ScreenWillBeRemovedOnPushException(newScreen.GetType());
            }

            // Suspend the current screen, if there is one
            if (source != null)
            {
                if (source != stack.Peek())
                {
                    throw new ScreenNotCurrentException(nameof(Push));
                }

                source.OnSuspending(newScreen);
                source.AsDrawable().Expire();
            }

            // Push the new screen
            stack.Push(newScreen);
            ScreenPushed?.Invoke(source, newScreen);

            void finishLoad()
            {
                if (!newScreen.ValidForPush)
                {
                    exitFrom(null);
                    return;
                }

                AddInternal(newScreen.AsDrawable());
                newScreen.OnEntering(source);
            }

            if (source != null)
            {
                LoadScreen((CompositeDrawable)source, newScreen.AsDrawable(), finishLoad);
            }
            else if (LoadState >= LoadState.Ready)
            {
                LoadScreen(this, newScreen.AsDrawable(), finishLoad);
            }
            else
            {
                Schedule(finishLoad);
            }
        }
示例#3
0
        internal void Push(IScreen source, IScreen newScreen)
        {
            if (stack.Contains(newScreen))
            {
                throw new ScreenAlreadyEnteredException();
            }

            if (source == null && stack.Count > 0)
            {
                throw new InvalidOperationException($"A source must be provided when pushing to a non-empty {nameof(ScreenStack)}");
            }

            if (newScreen.AsDrawable().RemoveWhenNotAlive)
            {
                throw new ScreenWillBeRemovedOnPushException(newScreen.GetType());
            }

            // Suspend the current screen, if there is one
            if (source != null && source != stack.Peek())
            {
                throw new ScreenNotCurrentException(nameof(Push));
            }

            if (suspendImmediately)
            {
                suspend(source, newScreen);
            }

            stack.Push(newScreen);
            ScreenPushed?.Invoke(source, newScreen);

            var newScreenDrawable = newScreen.AsDrawable();

            if (source == null)
            {
                // this is the first screen to be loaded.
                if (LoadState >= LoadState.Ready)
                {
                    LoadScreen(this, newScreenDrawable, () => finishPush(null, newScreen));
                }
                else
                {
                    Schedule(() => finishPush(null, newScreen));
                }
            }
            else
            {
                LoadScreen((CompositeDrawable)source, newScreenDrawable, () => finishPush(source, newScreen));
            }
        }