예제 #1
0
        //---------------------------------------------------------------------
        // Static members

        /// <summary>
        /// Loads individual frames to be displayed in an icon animation.  These
        /// are expected to be files named like <b>PREFIX-#.ico</b> in the specified
        /// directory.  The method will start loading <b>PREFIX-0.ico</b> and keep
        /// incrementing the index until no more frame files are found.
        /// </summary>
        /// <param name="folder">The source folder path.</param>
        /// <param name="prefix">The icon file name prefix.</param>
        /// <param name="frameRate">The desired frame rate.</param>
        /// <returns>The <see cref="AnimatedIcon"/>.</returns>
        /// <exception cref="FileNotFoundException">Thrown if no matching icon files were found.</exception>
        public static AnimatedIcon Load(string folder, string prefix, double frameRate)
        {
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(folder));
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(prefix));
            Covenant.Requires <ArgumentException>(frameRate > 0);

            var animatedIcon = new AnimatedIcon()
            {
                FrameRate = frameRate
            };

            for (var i = 0; ; i++)
            {
                var path = Path.Combine(folder, $"{prefix}-{i}.ico");

                if (!File.Exists(path))
                {
                    break;
                }

                animatedIcon.frames.Add(new Icon(path));
            }

            if (animatedIcon.frames.Count == 0)
            {
                throw new FileNotFoundException($"Could not locate any icon files with prefix: {prefix}");
            }

            return(animatedIcon);
        }
예제 #2
0
        /// <summary>
        /// Starts a notify icon animation.
        /// </summary>
        /// <param name="animatedIcon">The icon animation.</param>
        /// <param name="balloonText">Optional text to be displayed in the balloon during the animation.</param>
        /// <param name="isTransient">
        /// Optionally indicates that the state is not associated with
        /// an operation indicating an error or other transient status.
        /// </param>
        /// <param name="isError">
        /// Optionally indicates that the application is in the error state.
        /// This implies <see cref="IsTransient"/><c>=true</c>.
        /// </param>
        /// <remarks>
        /// Calls to this method may be recursed and should be matched
        /// with a call to <see cref="StopNotifyAnimation"/>.  The
        /// amimation will actually stop when the last matching
        /// <see cref="StartNotifyAnimation"/> call was matched with
        /// the last <see cref="StopNotifyAnimation"/>.
        /// </remarks>
        private void StartNotifyAnimation(AnimatedIcon animatedIcon, string balloonText = null, bool isTransient = false, bool isError = false)
        {
            Covenant.Requires <ArgumentNullException>(animatedIcon != null);

            InvokeOnUIThread(
                () =>
            {
                notifyStack.Push(new NotifyState(animatedIcon, balloonText, isTransient, isError));

                if (!string.IsNullOrEmpty(balloonText))
                {
                    SetBalloonText(balloonText);
                }

                if (animatedIcon != null)
                {
                    animationTimer.Stop();
                    animationTimer.Interval = (int)TimeSpan.FromSeconds(1 / animatedIcon.FrameRate).TotalMilliseconds;
                    animationTimer.Tick    +=
                        (s, a) =>
                    {
                        notifyIcon.Icon = animatedIcon.GetNextFrame();
                    };

                    animationTimer.Start();
                }
            });
        }
예제 #3
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="animatedIcon">The optional animation.</param>
 /// <param name="balloonText">The optional balloon text.</param>
 /// <param name="isTransient">
 /// Optionally indicates that the state is not associated with
 /// an operation indicating an error or other transient status.
 /// </param>
 /// <param name="isError">
 /// Optionally indicates that the application is in the error state.
 /// This implies <see cref="IsTransient"/><c>=true</c>.
 /// </param>
 public NotifyState(AnimatedIcon animatedIcon, string balloonText = null, bool isTransient = false, bool isError = false)
 {
     this.AnimatedIcon = animatedIcon;
     this.BalloonText  = balloonText;
     this.IsTransient  = isTransient || isError;
     this.IsError      = isError;
 }
예제 #4
0
        /// <summary>
        /// Indicates that an operation is starting by optionally displaying a working
        /// animation and optionally displaying a status toast.
        /// </summary>
        /// <param name="animatedIcon">The optional notify icon animation.</param>
        /// <param name="toastText">The optional toast text.</param>
        private void StartOperation(AnimatedIcon animatedIcon = null, string toastText = null)
        {
            InvokeOnUIThread(
                () =>
            {
                operationInProgress = true;

                if (animatedIcon != null)
                {
                    StartNotifyAnimation(animatedIcon);
                }

                if (!string.IsNullOrEmpty(toastText))
                {
                    ShowToast(toastText);
                }
            });
        }
예제 #5
0
        /// <summary>
        /// Constructor.
        /// </summary>
        public MainForm()
        {
            MainForm.Current = this;

            InitializeComponent();

            Load  += MainForm_Load;
            Shown += (s, a) => Visible = false; // The main form should always be hidden

            // Ensure that temporary files are written to the users temporary folder because
            // there's a decent chance that this folder will be encrypted at rest.

            TempFile.Root   = KubeHelper.TempFolder;
            TempFolder.Root = KubeHelper.TempFolder;

            // Preload the notification icons and animations for better performance.

            appIcon             = new Icon(@"Images\app.ico");
            connectedIcon       = new Icon(@"Images\connected.ico");
            disconnectedIcon    = new Icon(@"Images\disconnected.ico");
            errorIcon           = new Icon(@"Images\error.ico");
            connectingAnimation = AnimatedIcon.Load("Images", "connecting", animationFrameRate);
            workingAnimation    = AnimatedIcon.Load("Images", "working", animationFrameRate);
            errorAnimation      = AnimatedIcon.Load("Images", "error", animationFrameRate);
            notifyStack         = new Stack <NotifyState>();

            // Initialize the cluster hosting provider components.

            HostingLoader.Initialize();

            // Initialize the client state.

            proxies      = new List <ReverseProxy>();
            portForwards = new List <PortForward>();
            Headend      = new HeadendClient();
            KubeHelper.LoadClientConfig();
        }