예제 #1
0
        /// <summary>
        /// Creates a new console app given a set of boundaries
        /// </summary>
        /// <param name="w">The width of the app</param>
        /// <param name="h">The height of the app</param>
        public ConsoleApp(int w, int h)
        {
            this.Name              = GetType().Name;
            this.console           = ConsoleProvider.Current;
            consoleWriter          = Console.Out;
            this.lastConsoleWidth  = this.console.BufferWidth;
            this.lastConsoleHeight = this.console.WindowHeight;
            this.observable        = new ObservableObject(this);

            cycleRateMeter = new FrameRateMeter();

            this.EndOfCycle.SubscribeForLifetime(Cycle, this);
            SetFocusOnStart        = true;
            LayoutRoot             = new ConsolePanel(w, h);
            FocusManager           = new FocusManager();
            LayoutRoot.Application = this;
            isFullScreen           = false;
            FocusManager.SubscribeForLifetime(nameof(FocusManager.FocusedControl), () => RequestPaintAsync(), this);
            LayoutRoot.Controls.BeforeAdded.SubscribeForLifetime((c) => { c.Application = this; c.BeforeAddedToVisualTreeInternal(); }, this);
            LayoutRoot.Controls.BeforeRemoved.SubscribeForLifetime((c) => { c.BeforeRemovedFromVisualTreeInternal(); }, this);
            LayoutRoot.Controls.Added.SubscribeForLifetime(ControlAddedToVisualTree, this);
            LayoutRoot.Controls.Removed.SubscribeForLifetime(ControlRemovedFromVisualTree, this);
            WindowResized.SubscribeForLifetime(HandleDebouncedResize, this);
            this.LoopStarted.SubscribeOnce(() => _current = this);
            this.EndOfCycle.SubscribeForLifetime(DrainPaints, this);
        }
예제 #2
0
        private void Pump()
        {
            try
            {
                bool stopRequested = false;
                frameRateMeter = new FrameRateMeter();
                paintRateMeter = new FrameRateMeter();
                while (true)
                {
                    if ((lastConsoleWidth != this.console.BufferWidth || lastConsoleHeight != this.console.WindowHeight))
                    {
                        DebounceResize();
                        WindowResized.Fire();
                    }

                    bool idle = true;
                    List <PumpMessage> iterationQueue;
                    PaintMessage       iterationPaintMessage = null;
                    lock (pumpMessageQueue)
                    {
                        iterationQueue = new List <PumpMessage>(pumpMessageQueue);
                        pumpMessageQueue.Clear();
                    }

                    foreach (var message in iterationQueue)
                    {
                        idle = false;
                        if (message is StopPumpMessage)
                        {
                            stopRequested = true;
                            break;
                        }
                        else if (message is PaintMessage)
                        {
                            iterationPaintMessage = message as PaintMessage;
                        }
                        else
                        {
                            TryWork(message);
                        }
                    }

                    if (iterationPaintMessage != null)
                    {
                        TryWork(iterationPaintMessage);
                        paintRateMeter.Increment();
#if PROFILING
                        CliProfiler.Instance.PaintMessagesProcessed++;
#endif
                    }

                    if (stopRequested)
                    {
                        break;
                    }

                    if (this.console.KeyAvailable)
                    {
                        idle = false;
                        var info = this.console.ReadKey(true);
                        QueueAction(() =>
                        {
                            HandleKeyInput(info);
                        });
                    }

                    frameRateMeter.Increment();
                    if (idle)
                    {
                        Thread.Sleep(0);
                    }
#if PROFILING
                    else
                    {
                        CliProfiler.Instance.TotalNonIdleIterations++;
                    }
#endif
                }
                runDeferred.Resolve();
            }
            catch (Exception ex)
            {
                runDeferred.Reject(ex);
            }
            finally
            {
                IsRunning   = false;
                runDeferred = null;
            }
        }
예제 #3
0
        private void Pump()
        {
            try
            {
                OnThredStart();
                SynchronizationContext.SetSynchronizationContext(new CustomSyncContext(this));
                bool stopRequested = false;
                cycleRateMeter = new FrameRateMeter();
                paintRateMeter = new FrameRateMeter();
                while (true)
                {
                    cycleRateMeter.Increment();
                    if ((lastConsoleWidth != this.console.BufferWidth || lastConsoleHeight != this.console.WindowHeight))
                    {
                        DebounceResize();
                        WindowResized.Fire();
                    }

                    bool idle = true;
                    List <PumpMessage> iterationQueue;
                    PaintMessage       iterationPaintMessage = null;
                    var paintDeferreds = new List <Deferred>();
                    lock (pumpMessageQueue)
                    {
                        iterationQueue = new List <PumpMessage>(pumpMessageQueue);
                        pumpMessageQueue.Clear();
                    }

                    foreach (var message in iterationQueue)
                    {
                        idle = false;
                        if (message is StopPumpMessage)
                        {
                            stopRequested = true;
                            break;
                        }
                        else if (message is PaintMessage)
                        {
                            if (message.Deferred != null)
                            {
                                paintDeferreds.Add(message.Deferred);
                            }
                            iterationPaintMessage = message as PaintMessage;
                        }
                        else
                        {
                            TryWork(message);
                        }
                    }

                    if (iterationPaintMessage != null)
                    {
                        TryWork(iterationPaintMessage);

                        // since we debounce paints, make sure the paints
                        // that got debounced get resolved
                        foreach (var deferred in paintDeferreds)
                        {
                            if (deferred != iterationPaintMessage.Deferred)
                            {
                                deferred.Resolve();
                            }
                        }
                        paintRateMeter.Increment();
                    }

                    if (stopRequested)
                    {
                        break;
                    }

                    if (this.console.KeyAvailable)
                    {
                        idle = false;
                        var info = this.console.ReadKey(true);

                        var effectiveMinTimeBetweenKeyPresses = MinTimeBetweenKeyPresses;
                        if (KeyThrottlingEnabled && info.Key == lastKey && DateTime.UtcNow - lastKeyPressTime < effectiveMinTimeBetweenKeyPresses)
                        {
                            // the user is holding the key down and throttling is enabled
                        }
                        else
                        {
                            lastKeyPressTime = DateTime.UtcNow;
                            lastKey          = info.Key;
                            QueueAction(() => HandleKeyInput(info));
                        }
                    }
                    else if (sendKeys.Count > 0)
                    {
                        idle = false;
                        var info = sendKeys.Dequeue();
                        QueueAction(() => HandleKeyInput(info));
                    }

                    if (idle)
                    {
                        Thread.Sleep(1);
                    }
                }
                runDeferred.Resolve();
            }
            catch (Exception ex)
            {
                runDeferred.Reject(ex);
            }
            finally
            {
                IsRunning   = false;
                runDeferred = null;
            }
        }