moel@176
|
1 |
/*
|
moel@176
|
2 |
|
moel@176
|
3 |
Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
moel@176
|
4 |
|
moel@176
|
5 |
The contents of this file are subject to the Mozilla Public License Version
|
moel@176
|
6 |
1.1 (the "License"); you may not use this file except in compliance with
|
moel@176
|
7 |
the License. You may obtain a copy of the License at
|
moel@176
|
8 |
|
moel@176
|
9 |
http://www.mozilla.org/MPL/
|
moel@176
|
10 |
|
moel@176
|
11 |
Software distributed under the License is distributed on an "AS IS" basis,
|
moel@176
|
12 |
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
moel@176
|
13 |
for the specific language governing rights and limitations under the License.
|
moel@176
|
14 |
|
moel@176
|
15 |
The Original Code is the Open Hardware Monitor code.
|
moel@176
|
16 |
|
moel@176
|
17 |
The Initial Developer of the Original Code is
|
moel@176
|
18 |
Michael Möller <m.moeller@gmx.ch>.
|
moel@176
|
19 |
Portions created by the Initial Developer are Copyright (C) 2010
|
moel@176
|
20 |
the Initial Developer. All Rights Reserved.
|
moel@176
|
21 |
|
moel@176
|
22 |
Contributor(s):
|
moel@176
|
23 |
|
moel@176
|
24 |
Alternatively, the contents of this file may be used under the terms of
|
moel@176
|
25 |
either the GNU General Public License Version 2 or later (the "GPL"), or
|
moel@176
|
26 |
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
moel@176
|
27 |
in which case the provisions of the GPL or the LGPL are applicable instead
|
moel@176
|
28 |
of those above. If you wish to allow use of your version of this file only
|
moel@176
|
29 |
under the terms of either the GPL or the LGPL, and not to allow others to
|
moel@176
|
30 |
use your version of this file under the terms of the MPL, indicate your
|
moel@176
|
31 |
decision by deleting the provisions above and replace them with the notice
|
moel@176
|
32 |
and other provisions required by the GPL or the LGPL. If you do not delete
|
moel@176
|
33 |
the provisions above, a recipient may use your version of this file under
|
moel@176
|
34 |
the terms of any one of the MPL, the GPL or the LGPL.
|
moel@176
|
35 |
|
moel@176
|
36 |
*/
|
moel@176
|
37 |
|
moel@176
|
38 |
using System;
|
moel@176
|
39 |
using System.Collections.Generic;
|
moel@176
|
40 |
using System.Drawing;
|
moel@176
|
41 |
using System.Windows.Forms;
|
moel@176
|
42 |
using OpenHardwareMonitor.Hardware;
|
moel@176
|
43 |
|
moel@176
|
44 |
namespace OpenHardwareMonitor.GUI {
|
moel@176
|
45 |
public class SensorGadget : Gadget {
|
moel@176
|
46 |
|
moel@176
|
47 |
private UnitManager unitManager;
|
moel@176
|
48 |
|
moel@176
|
49 |
private Image back = Utilities.EmbeddedResources.GetImage("gadget.png");
|
moel@176
|
50 |
private Image barBack = Utilities.EmbeddedResources.GetImage("barback.png");
|
moel@176
|
51 |
private Image barblue = Utilities.EmbeddedResources.GetImage("barblue.png");
|
moel@176
|
52 |
private const int topBorder = 4;
|
moel@176
|
53 |
private const int bottomBorder = 6;
|
moel@176
|
54 |
private const int leftBorder = 6;
|
moel@176
|
55 |
private const int rightBorder = 6;
|
moel@176
|
56 |
private const int iconSize = 11;
|
moel@176
|
57 |
private const int hardwareLineHeight = 13;
|
moel@176
|
58 |
private const int sensorLineHeight = 11;
|
moel@176
|
59 |
|
moel@176
|
60 |
private IDictionary<IHardware, IList<ISensor>> sensors =
|
moel@176
|
61 |
new SortedDictionary<IHardware, IList<ISensor>>(new HardwareComparer());
|
moel@176
|
62 |
|
moel@176
|
63 |
private PersistentSettings settings;
|
moel@176
|
64 |
private UserOption alwaysOnTop;
|
moel@176
|
65 |
private UserOption lockPosition;
|
moel@176
|
66 |
|
moel@176
|
67 |
private Font largeFont;
|
moel@176
|
68 |
private Font smallFont;
|
moel@176
|
69 |
private Brush darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0));
|
moel@176
|
70 |
|
moel@176
|
71 |
public SensorGadget(IComputer computer, PersistentSettings settings,
|
moel@176
|
72 |
UnitManager unitManager)
|
moel@176
|
73 |
{
|
moel@176
|
74 |
this.unitManager = unitManager;
|
moel@176
|
75 |
this.settings = settings;
|
moel@176
|
76 |
computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
|
moel@176
|
77 |
computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
|
moel@176
|
78 |
|
moel@176
|
79 |
this.largeFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 7.5f,
|
moel@176
|
80 |
FontStyle.Bold);
|
moel@176
|
81 |
this.smallFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 6.5f);
|
moel@176
|
82 |
|
moel@176
|
83 |
this.Location = new Point(
|
moel@176
|
84 |
settings.GetValue("sensorGadget.Location.X", 100),
|
moel@176
|
85 |
settings.GetValue("sensorGadget.Location.Y", 100));
|
moel@176
|
86 |
LocationChanged += delegate(object sender, EventArgs e) {
|
moel@176
|
87 |
settings.SetValue("sensorGadget.Location.X", Location.X);
|
moel@176
|
88 |
settings.SetValue("sensorGadget.Location.Y", Location.Y);
|
moel@176
|
89 |
};
|
moel@176
|
90 |
|
moel@176
|
91 |
ContextMenu contextMenu = new ContextMenu();
|
moel@176
|
92 |
MenuItem lockItem = new MenuItem("Lock Position");
|
moel@176
|
93 |
contextMenu.MenuItems.Add(lockItem);
|
moel@176
|
94 |
contextMenu.MenuItems.Add(new MenuItem("-"));
|
moel@176
|
95 |
MenuItem alwaysOnTopItem = new MenuItem("Always on Top");
|
moel@176
|
96 |
contextMenu.MenuItems.Add(alwaysOnTopItem);
|
moel@176
|
97 |
MenuItem opacityMenu = new MenuItem("Opacity");
|
moel@176
|
98 |
contextMenu.MenuItems.Add(opacityMenu);
|
moel@176
|
99 |
Opacity = (byte)settings.GetValue("sensorGadget.Opacity", 255);
|
moel@176
|
100 |
for (int i = 0; i < 5; i++) {
|
moel@176
|
101 |
MenuItem item = new MenuItem((20 * (i + 1)).ToString() + " %");
|
moel@176
|
102 |
byte o = (byte)(51 * (i + 1));
|
moel@176
|
103 |
item.Checked = Opacity == o;
|
moel@176
|
104 |
item.Click += delegate(object sender, EventArgs e) {
|
moel@178
|
105 |
Opacity = o;
|
moel@176
|
106 |
settings.SetValue("sensorGadget.Opacity", Opacity);
|
moel@176
|
107 |
foreach (MenuItem mi in opacityMenu.MenuItems)
|
moel@178
|
108 |
mi.Checked = mi == item;
|
moel@176
|
109 |
};
|
moel@176
|
110 |
opacityMenu.MenuItems.Add(item);
|
moel@176
|
111 |
}
|
moel@176
|
112 |
this.ContextMenu = contextMenu;
|
moel@176
|
113 |
|
moel@176
|
114 |
alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false,
|
moel@176
|
115 |
alwaysOnTopItem, settings);
|
moel@176
|
116 |
alwaysOnTop.Changed += delegate(object sender, EventArgs e) {
|
moel@176
|
117 |
this.AlwaysOnTop = alwaysOnTop.Value;
|
moel@176
|
118 |
};
|
moel@176
|
119 |
lockPosition = new UserOption("sensorGadget.LockPosition", false,
|
moel@176
|
120 |
lockItem, settings);
|
moel@176
|
121 |
lockPosition.Changed += delegate(object sender, EventArgs e) {
|
moel@176
|
122 |
this.LockPosition = lockPosition.Value;
|
moel@176
|
123 |
};
|
moel@176
|
124 |
|
moel@176
|
125 |
Resize();
|
moel@176
|
126 |
}
|
moel@176
|
127 |
|
moel@176
|
128 |
private void HardwareRemoved(IHardware hardware) {
|
moel@176
|
129 |
hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
|
moel@176
|
130 |
hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved);
|
moel@176
|
131 |
foreach (ISensor sensor in hardware.Sensors)
|
moel@176
|
132 |
SensorRemoved(sensor);
|
moel@176
|
133 |
foreach (IHardware subHardware in hardware.SubHardware)
|
moel@176
|
134 |
HardwareRemoved(subHardware);
|
moel@176
|
135 |
}
|
moel@176
|
136 |
|
moel@176
|
137 |
private void HardwareAdded(IHardware hardware) {
|
moel@176
|
138 |
foreach (ISensor sensor in hardware.Sensors)
|
moel@176
|
139 |
SensorAdded(sensor);
|
moel@176
|
140 |
hardware.SensorAdded += new SensorEventHandler(SensorAdded);
|
moel@176
|
141 |
hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
|
moel@176
|
142 |
foreach (IHardware subHardware in hardware.SubHardware)
|
moel@176
|
143 |
HardwareAdded(subHardware);
|
moel@176
|
144 |
}
|
moel@176
|
145 |
|
moel@176
|
146 |
private void SensorAdded(ISensor sensor) {
|
moel@176
|
147 |
if (settings.GetValue(new Identifier(sensor.Identifier,
|
moel@176
|
148 |
"gadget").ToString(), false))
|
moel@176
|
149 |
Add(sensor);
|
moel@176
|
150 |
}
|
moel@176
|
151 |
|
moel@176
|
152 |
private void SensorRemoved(ISensor sensor) {
|
moel@176
|
153 |
if (Contains(sensor))
|
moel@176
|
154 |
Remove(sensor, false);
|
moel@176
|
155 |
}
|
moel@176
|
156 |
|
moel@176
|
157 |
public bool Contains(ISensor sensor) {
|
moel@176
|
158 |
foreach (IList<ISensor> list in sensors.Values)
|
moel@176
|
159 |
if (list.Contains(sensor))
|
moel@176
|
160 |
return true;
|
moel@176
|
161 |
return false;
|
moel@176
|
162 |
}
|
moel@176
|
163 |
|
moel@176
|
164 |
public void Add(ISensor sensor) {
|
moel@176
|
165 |
if (Contains(sensor)) {
|
moel@176
|
166 |
return;
|
moel@176
|
167 |
} else {
|
moel@176
|
168 |
// get the right hardware
|
moel@176
|
169 |
IHardware hardware = sensor.Hardware;
|
moel@176
|
170 |
while (hardware.Parent != null)
|
moel@176
|
171 |
hardware = hardware.Parent;
|
moel@176
|
172 |
|
moel@176
|
173 |
// get the sensor list associated with the hardware
|
moel@176
|
174 |
IList<ISensor> list;
|
moel@176
|
175 |
if (!sensors.TryGetValue(hardware, out list)) {
|
moel@176
|
176 |
list = new List<ISensor>();
|
moel@176
|
177 |
sensors.Add(hardware, list);
|
moel@176
|
178 |
}
|
moel@176
|
179 |
|
moel@176
|
180 |
// insert the sensor at the right position
|
moel@176
|
181 |
int i = 0;
|
moel@176
|
182 |
while (i < list.Count && (list[i].SensorType < sensor.SensorType ||
|
moel@176
|
183 |
(list[i].SensorType == sensor.SensorType &&
|
moel@176
|
184 |
list[i].Index < sensor.Index))) i++;
|
moel@176
|
185 |
list.Insert(i, sensor);
|
moel@176
|
186 |
|
moel@176
|
187 |
settings.SetValue(
|
moel@176
|
188 |
new Identifier(sensor.Identifier, "gadget").ToString(), true);
|
moel@176
|
189 |
|
moel@176
|
190 |
Resize();
|
moel@176
|
191 |
Redraw();
|
moel@176
|
192 |
}
|
moel@176
|
193 |
}
|
moel@176
|
194 |
|
moel@176
|
195 |
public void Remove(ISensor sensor) {
|
moel@176
|
196 |
Remove(sensor, true);
|
moel@176
|
197 |
}
|
moel@176
|
198 |
|
moel@176
|
199 |
private void Remove(ISensor sensor, bool deleteConfig) {
|
moel@176
|
200 |
if (deleteConfig)
|
moel@176
|
201 |
settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString());
|
moel@176
|
202 |
|
moel@176
|
203 |
foreach (KeyValuePair<IHardware, IList<ISensor>> keyValue in sensors)
|
moel@176
|
204 |
if (keyValue.Value.Contains(sensor)) {
|
moel@176
|
205 |
keyValue.Value.Remove(sensor);
|
moel@176
|
206 |
if (keyValue.Value.Count == 0) {
|
moel@176
|
207 |
sensors.Remove(keyValue.Key);
|
moel@176
|
208 |
break;
|
moel@176
|
209 |
}
|
moel@176
|
210 |
}
|
moel@176
|
211 |
Resize();
|
moel@176
|
212 |
Redraw();
|
moel@176
|
213 |
}
|
moel@176
|
214 |
|
moel@176
|
215 |
private void Resize() {
|
moel@176
|
216 |
int y = topBorder + 1;
|
moel@176
|
217 |
foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
|
moel@176
|
218 |
y += hardwareLineHeight;
|
moel@176
|
219 |
y += pair.Value.Count * sensorLineHeight;
|
moel@176
|
220 |
}
|
moel@176
|
221 |
y += bottomBorder + 2;
|
moel@176
|
222 |
y = Math.Max(y, topBorder + bottomBorder + 10);
|
moel@176
|
223 |
this.Size = new Size(130, y);
|
moel@176
|
224 |
}
|
moel@176
|
225 |
|
moel@176
|
226 |
private void DrawBackground(Graphics g) {
|
moel@176
|
227 |
int w = Size.Width;
|
moel@176
|
228 |
int h = Size.Height;
|
moel@176
|
229 |
int t = topBorder;
|
moel@176
|
230 |
int b = bottomBorder;
|
moel@176
|
231 |
int l = leftBorder;
|
moel@176
|
232 |
int r = rightBorder;
|
moel@176
|
233 |
GraphicsUnit u = GraphicsUnit.Pixel;
|
moel@176
|
234 |
|
moel@176
|
235 |
g.DrawImage(back, new Rectangle(0, 0, l, t),
|
moel@176
|
236 |
new Rectangle(0, 0, l, t), u);
|
moel@176
|
237 |
g.DrawImage(back, new Rectangle(l, 0, w - l - r, t),
|
moel@176
|
238 |
new Rectangle(l, 0, back.Width - l - r, t), u);
|
moel@176
|
239 |
g.DrawImage(back, new Rectangle(w - r, 0, r, t),
|
moel@176
|
240 |
new Rectangle(back.Width - r, 0, r, t), u);
|
moel@176
|
241 |
|
moel@176
|
242 |
g.DrawImage(back, new Rectangle(0, t, l, h - t - b),
|
moel@176
|
243 |
new Rectangle(0, t, l, back.Height - t - b), u);
|
moel@176
|
244 |
g.DrawImage(back, new Rectangle(l, t, w - l - r, h - t - b),
|
moel@176
|
245 |
new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u);
|
moel@176
|
246 |
g.DrawImage(back, new Rectangle(w - r, t, r, h - t - b),
|
moel@176
|
247 |
new Rectangle(back.Width - r, t, r, back.Height - t - b), u);
|
moel@176
|
248 |
|
moel@176
|
249 |
g.DrawImage(back, new Rectangle(0, h - b, l, b),
|
moel@176
|
250 |
new Rectangle(0, back.Height - b, l, b), u);
|
moel@176
|
251 |
g.DrawImage(back, new Rectangle(l, h - b, w - l - r, b),
|
moel@176
|
252 |
new Rectangle(l, back.Height - b, back.Width - l - r, b), u);
|
moel@176
|
253 |
g.DrawImage(back, new Rectangle(w - r, h - b, r, b),
|
moel@176
|
254 |
new Rectangle(back.Width - r, back.Height - b, r, b), u);
|
moel@176
|
255 |
}
|
moel@176
|
256 |
|
moel@176
|
257 |
private void DrawProgress(Graphics g, int x, int y, int width, int height,
|
moel@176
|
258 |
float progress)
|
moel@176
|
259 |
{
|
moel@176
|
260 |
g.DrawImage(barBack,
|
moel@176
|
261 |
new RectangleF(x + width * progress, y, width * (1 - progress), height),
|
moel@176
|
262 |
new RectangleF(barBack.Width * progress, 0,
|
moel@176
|
263 |
(1 - progress) * barBack.Width, barBack.Height),
|
moel@176
|
264 |
GraphicsUnit.Pixel);
|
moel@176
|
265 |
g.DrawImage(barblue,
|
moel@176
|
266 |
new RectangleF(x, y, width * progress, height),
|
moel@176
|
267 |
new RectangleF(0, 0, progress * barblue.Width, barblue.Height),
|
moel@176
|
268 |
GraphicsUnit.Pixel);
|
moel@176
|
269 |
}
|
moel@176
|
270 |
|
moel@176
|
271 |
protected override void OnPaint(PaintEventArgs e) {
|
moel@176
|
272 |
Graphics g = e.Graphics;
|
moel@176
|
273 |
int w = Size.Width;
|
moel@176
|
274 |
int h = Size.Height;
|
moel@176
|
275 |
|
moel@176
|
276 |
g.Clear(Color.Transparent);
|
moel@176
|
277 |
|
moel@176
|
278 |
DrawBackground(g);
|
moel@176
|
279 |
|
moel@176
|
280 |
StringFormat stringFormat = new StringFormat();
|
moel@176
|
281 |
stringFormat.Alignment = StringAlignment.Far;
|
moel@176
|
282 |
|
moel@176
|
283 |
int x;
|
moel@176
|
284 |
int y = topBorder + 1;
|
moel@176
|
285 |
foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
|
moel@176
|
286 |
x = leftBorder + 1;
|
moel@176
|
287 |
g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType),
|
moel@176
|
288 |
new Rectangle(x, y + 2, iconSize, iconSize));
|
moel@176
|
289 |
x += iconSize + 1;
|
moel@176
|
290 |
g.DrawString(pair.Key.Name, largeFont, Brushes.White,
|
moel@176
|
291 |
new Rectangle(x, y, w - rightBorder - x, 15));
|
moel@176
|
292 |
y += hardwareLineHeight;
|
moel@176
|
293 |
|
moel@176
|
294 |
foreach (ISensor sensor in pair.Value) {
|
moel@176
|
295 |
|
moel@176
|
296 |
g.DrawString(sensor.Name + ":", smallFont, darkWhite,
|
moel@176
|
297 |
new Rectangle(9, y, 64, 15));
|
moel@176
|
298 |
|
moel@176
|
299 |
if (sensor.SensorType != SensorType.Load &&
|
moel@176
|
300 |
sensor.SensorType != SensorType.Control)
|
moel@176
|
301 |
{
|
moel@176
|
302 |
string format = "";
|
moel@176
|
303 |
switch (sensor.SensorType) {
|
moel@176
|
304 |
case SensorType.Voltage:
|
moel@176
|
305 |
format = "{0:F2} V";
|
moel@176
|
306 |
break;
|
moel@176
|
307 |
case SensorType.Clock:
|
moel@176
|
308 |
format = "{0:F0} MHz";
|
moel@176
|
309 |
break;
|
moel@176
|
310 |
case SensorType.Temperature:
|
moel@176
|
311 |
format = "{0:F1} °C";
|
moel@176
|
312 |
break;
|
moel@176
|
313 |
case SensorType.Fan:
|
moel@176
|
314 |
format = "{0:F0} RPM";
|
moel@176
|
315 |
break;
|
moel@176
|
316 |
case SensorType.Flow:
|
moel@176
|
317 |
format = "{0:F0} L/h";
|
moel@176
|
318 |
break;
|
moel@176
|
319 |
}
|
moel@176
|
320 |
|
moel@176
|
321 |
string formattedValue;
|
moel@176
|
322 |
if (sensor.SensorType == SensorType.Temperature &&
|
moel@176
|
323 |
unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) {
|
moel@176
|
324 |
formattedValue = string.Format("{0:F1} °F",
|
moel@176
|
325 |
sensor.Value * 1.8 + 32);
|
moel@176
|
326 |
} else {
|
moel@176
|
327 |
formattedValue = string.Format(format, sensor.Value);
|
moel@176
|
328 |
}
|
moel@176
|
329 |
|
moel@176
|
330 |
x = 75;
|
moel@176
|
331 |
g.DrawString(formattedValue, smallFont, darkWhite,
|
moel@176
|
332 |
new RectangleF(x, y, w - x - 9, 15), stringFormat);
|
moel@176
|
333 |
} else {
|
moel@176
|
334 |
x = 80;
|
moel@176
|
335 |
DrawProgress(g, x, y + 4, w - x - 9, 6, 0.01f * sensor.Value.Value);
|
moel@176
|
336 |
}
|
moel@176
|
337 |
|
moel@176
|
338 |
y += sensorLineHeight;
|
moel@176
|
339 |
}
|
moel@176
|
340 |
}
|
moel@176
|
341 |
}
|
moel@176
|
342 |
|
moel@176
|
343 |
private class HardwareComparer : IComparer<IHardware> {
|
moel@176
|
344 |
public int Compare(IHardware x, IHardware y) {
|
moel@176
|
345 |
if (x == null && y == null)
|
moel@176
|
346 |
return 0;
|
moel@176
|
347 |
if (x == null)
|
moel@176
|
348 |
return -1;
|
moel@176
|
349 |
if (y == null)
|
moel@176
|
350 |
return 1;
|
moel@176
|
351 |
|
moel@176
|
352 |
if (x.HardwareType != y.HardwareType)
|
moel@176
|
353 |
return x.HardwareType.CompareTo(y.HardwareType);
|
moel@176
|
354 |
|
moel@176
|
355 |
return x.Name.CompareTo(y.Name);
|
moel@176
|
356 |
}
|
moel@176
|
357 |
}
|
moel@176
|
358 |
}
|
moel@176
|
359 |
}
|
moel@176
|
360 |
|