wasSharpNET – Rev 11

Subversion Repositories:
Rev:
///////////////////////////////////////////////////////////////////////////
//  Copyright (C) Wizardry and Steamworks 2016 - License: GNU GPLv3      //
//  Please see: http://www.gnu.org/licenses/gpl.html for legal details,  //
//  rights of fair usage, the disclaimer and warranty conditions.        //
///////////////////////////////////////////////////////////////////////////

using System;
using System.Threading;
using wasSharp.Collections.Generic;

namespace wasSharpNET.Console
{
    ///////////////////////////////////////////////////////////////////////////
    //    Copyright (C) 2016 Wizardry and Steamworks - License: GNU GPLv3    //
    ///////////////////////////////////////////////////////////////////////////
    /// <summary>
    ///     A command-line spinner indicating activity.
    /// </summary>
    public class ConsoleSpin : IDisposable
    {
        private static readonly CircularQueue<string> spinArt =
            new CircularQueue<string>(new[] { ".oOo", "oOo.", "Oo.o", "o.oO" });

        private static readonly ManualResetEvent spinEvent = new ManualResetEvent(false);
        private static Thread spinThread;
        private static bool run = true;

        public ConsoleSpin() : this(ConsoleExtensions.ConsoleTextAlignment.TOP_LEFT)
        {
        }

        public ConsoleSpin(ConsoleExtensions.ConsoleTextAlignment alignment)
        {
            spinThread = new Thread(() =>
            {
                while (run)
                {
                    spinEvent.WaitOne();
                    var deco = spinArt.Dequeue();
                    deco.Write(alignment);
                    foreach (var c in deco)
                        "\b".Write(alignment);

                    Thread.Sleep(100);
                }
            })
            {
                IsBackground = true
            };
            spinThread.Start();
        }

        public void Dispose()
        {
            // Stop the callback thread.
            try
            {
                if (spinThread != null)
                {
                    run = false;
                    spinEvent.Reset();
                    if ((!spinThread.ThreadState.Equals(ThreadState.Running) &&
                         !spinThread.ThreadState.Equals(ThreadState.WaitSleepJoin)) || spinThread.Join(1000))
                        return;
                    spinThread.Abort();
                    spinThread.Join();
                }
            }
            catch (Exception)
            {
                /* We are going down and we do not care. */
            }
            finally
            {
                spinThread = null;
            }
        }

        public void Start()
        {
            spinEvent.Set();
        }

        public void Stop()
        {
            spinEvent.Reset();
        }
    }
}