-
Notifications
You must be signed in to change notification settings - Fork 326
/
ProgressIndicator.cs
117 lines (104 loc) · 3.93 KB
/
ProgressIndicator.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
namespace Microsoft.VisualStudio.TestPlatform.CommandLine.Internal
{
using System.Globalization;
using Microsoft.VisualStudio.TestPlatform.Utilities;
using Timer = System.Timers.Timer;
/// <summary>
/// Indicates the test run progress
/// </summary>
internal class ProgressIndicator : IProgressIndicator
{
private object syncObject = new object();
private int dotCounter;
private Timer timer;
private string testRunProgressString;
/// <summary>
/// Used to output to the console
/// </summary>
public IOutput ConsoleOutput { get; private set; }
/// <summary>
/// Wrapper over the System Console class
/// </summary>
public IConsoleHelper ConsoleHelper { get; private set; }
/// <summary>
/// True is the indicator is to be displayed
/// </summary>
public bool IsRunning { get; private set; }
public ProgressIndicator(IOutput output, IConsoleHelper consoleHelper)
{
this.ConsoleOutput = output;
this.ConsoleHelper = consoleHelper;
this.testRunProgressString = string.Format(CultureInfo.CurrentCulture, "{0}...", Resources.Resources.ProgressIndicatorString);
}
/// <inheritdoc />
public void Start()
{
lock (syncObject)
{
if (timer == null)
{
this.timer = new Timer(1000);
this.timer.Elapsed += Timer_Elapsed;
this.timer.Start();
}
// Print the string based on the previous state, that is dotCounter
// This is required for smooth transition
this.ConsoleOutput.Write(testRunProgressString.Substring(0, testRunProgressString.Length + dotCounter - 2), OutputLevel.Information);
this.IsRunning = true;
}
}
/// <summary>
// Get the current cursor position
// Clear the console starting given position
// Reset the cursor position back
/// </summary>
/// <param name="startPos">the starting position</param>
private void Clear(int startPos)
{
var currentLineCursor = this.ConsoleHelper.CursorTop;
this.ConsoleHelper.SetCursorPosition(startPos, this.ConsoleHelper.CursorTop);
this.ConsoleOutput.Write(new string(' ', this.ConsoleHelper.WindowWidth - startPos), OutputLevel.Information);
this.ConsoleHelper.SetCursorPosition(startPos, currentLineCursor);
}
/// <summary>
/// Sets the isRunning flag to false so that indicator is not shown.
/// </summary>
public void Pause()
{
lock (syncObject)
{
this.IsRunning = false;
this.Clear(0);
}
}
/// <summary>
/// Stops the indicator and clears the current line.
/// </summary>
public void Stop()
{
lock (syncObject)
{
this.IsRunning = false;
this.timer?.Stop();
this.Clear(0);
}
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (IsRunning)
{
// If running, prints dot every second.
this.ConsoleOutput.Write(".", OutputLevel.Information);
dotCounter = ++dotCounter % 3;
// When counter reaches 3, that is 3 dots have been printed
// Clear and start printing again
if (dotCounter == 0)
{
this.Clear(this.ConsoleHelper.CursorLeft - 3);
}
}
}
}
}