88using Microsoft . VisualStudio . PlatformUI ;
99using AppHelpers ;
1010using R = Codist . Properties . Resources ;
11+ using Microsoft . VisualStudio . Shell ;
12+ using Task = System . Threading . Tasks . Task ;
1113
1214namespace Codist . Display
1315{
1416 static class ResourceMonitor
1517 {
1618 static Timer _Timer ;
17- static readonly StackPanel _MeterContainer = new StackPanel { Orientation = Orientation . Horizontal } ;
18- static Meter _CpuMeter , _RamMeter ;
19+ static readonly StackPanel _MeterContainer = new StackPanel {
20+ Orientation = Orientation . Horizontal ,
21+ Children = { new ContentPresenter ( ) , new ContentPresenter ( ) , new ContentPresenter ( ) , }
22+ } ;
23+ static Meter _CpuMeter , _RamMeter , _DriveMeter ;
1924 static int _IsInited ;
2025
2126 public static void Reload ( DisplayOptimizations option ) {
22- if ( option . HasAnyFlag ( DisplayOptimizations . ShowCpu | DisplayOptimizations . ShowMemory ) == false ) {
27+ if ( option . HasAnyFlag ( DisplayOptimizations . ResourceMonitors ) == false ) {
2328 Stop ( ) ;
2429 return ;
2530 }
26- if ( option . MatchFlags ( DisplayOptimizations . ShowCpu ) ) {
27- if ( _CpuMeter != null ) {
28- _CpuMeter . Start ( ) ;
29- }
30- else {
31- _CpuMeter = new CpuMeter ( ) ;
32- _MeterContainer . Children . Insert ( 0 , _CpuMeter ) ;
33- }
34- }
35- else {
36- _CpuMeter ? . Stop ( ) ;
31+ ToggleMeter < CpuMeter > ( 0 , option , DisplayOptimizations . ShowCpu , ref _CpuMeter ) ;
32+ ToggleMeter < DriveMeter > ( 1 , option , DisplayOptimizations . ShowDrive , ref _DriveMeter ) ;
33+ ToggleMeter < RamMeter > ( 2 , option , DisplayOptimizations . ShowMemory , ref _RamMeter ) ;
34+ if ( _Timer == null ) {
35+ _Timer = new Timer ( Update , null , 1000 , 1000 ) ;
3736 }
38- if ( option . MatchFlags ( DisplayOptimizations . ShowMemory ) ) {
39- if ( _RamMeter != null ) {
40- _RamMeter . Start ( ) ;
37+ }
38+
39+ static void ToggleMeter < TMeter > ( int index , DisplayOptimizations option , DisplayOptimizations flag , ref Meter meter ) where TMeter : Meter , new ( ) {
40+ if ( option . MatchFlags ( flag ) ) {
41+ if ( meter != null ) {
42+ meter . Start ( ) ;
4143 }
4244 else {
43- _RamMeter = new RamMeter ( ) ;
44- _MeterContainer . Children . Add ( _RamMeter ) ;
45+ meter = new TMeter ( ) ;
46+ _MeterContainer . Children . RemoveAt ( index ) ;
47+ _MeterContainer . Children . Insert ( index , meter ) ;
4548 }
4649 }
4750 else {
48- _RamMeter ? . Stop ( ) ;
49- }
50- if ( _Timer == null ) {
51- _Timer = new Timer ( Update , null , 1000 , 1000 ) ;
51+ meter ? . Stop ( ) ;
5252 }
5353 }
5454
@@ -58,16 +58,23 @@ static void Stop() {
5858 _Timer = null ;
5959 _CpuMeter ? . Stop ( ) ;
6060 _RamMeter ? . Stop ( ) ;
61+ _DriveMeter ? . Stop ( ) ;
6162 }
6263 }
6364
6465 static void Update ( object dummy ) {
66+ UpdateAsync ( ) . FireAndForget ( ) ;
67+ }
68+
69+ async static Task UpdateAsync ( ) {
70+ await ThreadHelper . JoinableTaskFactory . SwitchToMainThreadAsync ( ) ;
6571 if ( _IsInited == 0 ) {
66- _MeterContainer . Dispatcher . Invoke ( Init ) ;
72+ Init ( ) ;
6773 return ;
6874 }
6975 _CpuMeter ? . Update ( ) ;
7076 _RamMeter ? . Update ( ) ;
77+ _DriveMeter ? . Update ( ) ;
7178 }
7279
7380 static void Init ( ) {
@@ -99,23 +106,25 @@ abstract class Meter : StackPanel
99106 protected Meter ( int iconId , string tooltip ) {
100107 Orientation = Orientation . Horizontal ;
101108 Children . Add ( ThemeHelper . GetImage ( iconId ) . WrapMargin ( WpfHelper . SmallHorizontalMargin ) ) ;
102- Children . Add ( _Label = new TextBlock { MinWidth = 40 , VerticalAlignment = VerticalAlignment . Center } ) ;
103- _Label . SetResourceReference ( Control . ForegroundProperty , EnvironmentColors . StatusBarDefaultTextBrushKey ) ;
109+ Children . Add ( _Label = new TextBlock { MinWidth = 40 , VerticalAlignment = VerticalAlignment . Center } . ReferenceProperty ( Control . ForegroundProperty , EnvironmentColors . StatusBarDefaultTextBrushKey ) ) ;
104110 _Counter = CreateCounter ( ) ;
105- var t = new CommandToolTip ( iconId , tooltip ) ;
106- t . SetResourceReference ( ImageThemingUtilities . ImageBackgroundColorProperty , EnvironmentColors . ToolTipColorKey ) ;
107- ToolTip = t ;
108- ToolTipService . SetPlacement ( this , System . Windows . Controls . Primitives . PlacementMode . Top ) ;
111+ ToolTip = new CommandToolTip ( iconId , tooltip )
112+ . ReferenceCrispImageBackground ( EnvironmentColors . ToolTipColorKey )
113+ . SetTipPlacementTop ( ) ;
109114 }
110115
111116 protected TextBlock Label => _Label ;
112117
113118 public void Update ( ) {
119+ var c = _Counter ;
120+ if ( c == null ) {
121+ return ;
122+ }
114123 try {
115- Dispatcher . Invoke ( UpdateMeter ) ;
124+ UpdateDisplay ( c . NextValue ( ) ) ;
116125 }
117- catch ( System . Threading . Tasks . TaskCanceledException ) {
118- // ignore
126+ catch ( Exception ex ) {
127+ Debug . WriteLine ( ex ) ;
119128 }
120129 }
121130
@@ -135,26 +144,13 @@ public virtual void Stop() {
135144 _Counter = null ;
136145 }
137146 }
138-
139- void UpdateMeter ( ) {
140- var c = _Counter ;
141- if ( c == null ) {
142- return ;
143- }
144- try {
145- UpdateDisplay ( c . NextValue ( ) ) ;
146- }
147- catch ( Exception ex ) {
148- Debug . WriteLine ( ex ) ;
149- }
150- }
151147 }
152148
153149 sealed class CpuMeter : Meter
154150 {
155151 const int SampleCount = 10 ;
156152 readonly float [ ] _Samples = new float [ SampleCount ] ;
157- float _SampleSum ;
153+ float _SampleSum , _LastSample ;
158154 int _SampleIndex ;
159155
160156 public CpuMeter ( ) : base ( IconIds . Cpu , R . T_CpuUsage ) {
@@ -173,8 +169,16 @@ protected override void UpdateDisplay(float counterValue) {
173169 if ( ++ _SampleIndex == SampleCount ) {
174170 _SampleIndex = 0 ;
175171 }
176- counterValue = Math . Min ( 50 , Math . Min ( counterValue , _SampleSum / SampleCount ) ) / 50 ;
177- Background = counterValue < 0.2f ? Brushes . Transparent : Brushes . Red . Alpha ( counterValue ) ;
172+ counterValue = Math . Min ( 50 , _SampleSum / SampleCount ) / 50 ;
173+ if ( counterValue < 0.2f ) {
174+ if ( _LastSample >= 0.2f ) {
175+ ClearValue ( BackgroundProperty ) ;
176+ }
177+ }
178+ else {
179+ Background = Brushes . Red . Alpha ( counterValue ) ;
180+ }
181+ _LastSample = counterValue ;
178182 }
179183 }
180184
@@ -192,5 +196,41 @@ protected override void UpdateDisplay(float counterValue) {
192196 Label . Opacity = ( counterValue + 100 ) / 200 ;
193197 }
194198 }
199+
200+ sealed class DriveMeter : Meter
201+ {
202+ const int SampleCount = 10 ;
203+ readonly float [ ] _Samples = new float [ SampleCount ] ;
204+ float _SampleSum , _LastSample ;
205+ int _SampleIndex ;
206+
207+ public DriveMeter ( ) : base ( IconIds . Drive , R . T_DriveUsage ) {
208+ }
209+
210+ protected override PerformanceCounter CreateCounter ( ) {
211+ return new PerformanceCounter ( "LogicalDisk" , "% Disk Time" , "_Total" ) ;
212+ }
213+
214+ protected override void UpdateDisplay ( float counterValue ) {
215+ Label . Text = counterValue . ToString ( "0" ) + "%" ;
216+ Label . Opacity = ( Math . Min ( 50 , counterValue ) + 50 ) / 100 ;
217+ _SampleSum -= _Samples [ _SampleIndex ] ;
218+ _Samples [ _SampleIndex ] = counterValue ;
219+ _SampleSum += counterValue ;
220+ if ( ++ _SampleIndex == SampleCount ) {
221+ _SampleIndex = 0 ;
222+ }
223+ counterValue = Math . Min ( 30 , Math . Min ( counterValue , _SampleSum / SampleCount ) ) / 30 ;
224+ if ( counterValue < 0.2f ) {
225+ if ( _LastSample >= 0.2f ) {
226+ ClearValue ( BackgroundProperty ) ;
227+ }
228+ }
229+ else {
230+ Background = Brushes . Red . Alpha ( counterValue ) ;
231+ }
232+ _LastSample = counterValue ;
233+ }
234+ }
195235 }
196236}
0 commit comments