Added mainboard specific configurations for the following Gigabyte mainboards: EX58-UD3R, G41M-Combo, G41MT-S2, G41MT-S2P, GA-MA770T-UD3P, GA-MA785GM-US2H, GA-MA78LM-S2H, GA-MA790X-UD3P, H55-USB3, H55N-USB3, H61M-DS2 REV 1.2, H61M-USB3-B3 REV 2.0, H67A-USB3-B3, P55A-UD3, P67A-UD3-B3, P67A-UD3R-B3, Z68A-D3H-B3, Z68AP-D3, Z68X-UD3H-B3.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2010-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
12 using System.Collections.Generic;
14 using System.Drawing.Imaging;
15 using System.Windows.Forms;
17 using OpenHardwareMonitor.Hardware;
19 namespace OpenHardwareMonitor.GUI {
20 public class SensorGadget : Gadget {
22 private UnitManager unitManager;
24 private Image back = Utilities.EmbeddedResources.GetImage("gadget.png");
25 private Image image = null;
26 private Image fore = null;
27 private Image barBack = Utilities.EmbeddedResources.GetImage("barback.png");
28 private Image barFore = Utilities.EmbeddedResources.GetImage("barblue.png");
29 private const int topBorder = 6;
30 private const int bottomBorder = 7;
31 private const int leftBorder = 6;
32 private const int rightBorder = 7;
33 private Image background = new Bitmap(1, 1);
35 private readonly float scale;
36 private float fontSize;
38 private int hardwareLineHeight;
39 private int sensorLineHeight;
40 private int rightMargin;
41 private int leftMargin;
42 private int topMargin;
43 private int bottomMargin;
44 private int progressWidth;
46 private IDictionary<IHardware, IList<ISensor>> sensors =
47 new SortedDictionary<IHardware, IList<ISensor>>(new HardwareComparer());
49 private PersistentSettings settings;
50 private UserOption hardwareNames;
51 private UserOption alwaysOnTop;
52 private UserOption lockPositionAndSize;
54 private Font largeFont;
55 private Font smallFont;
56 private Brush darkWhite;
57 private StringFormat stringFormat;
58 private StringFormat trimStringFormat;
59 private StringFormat alignRightStringFormat;
61 public SensorGadget(IComputer computer, PersistentSettings settings,
62 UnitManager unitManager)
64 this.unitManager = unitManager;
65 this.settings = settings;
66 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
67 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
69 this.darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0));
71 this.stringFormat = new StringFormat();
72 this.stringFormat.FormatFlags = StringFormatFlags.NoWrap;
74 this.trimStringFormat = new StringFormat();
75 this.trimStringFormat.Trimming = StringTrimming.EllipsisCharacter;
76 this.trimStringFormat.FormatFlags = StringFormatFlags.NoWrap;
78 this.alignRightStringFormat = new StringFormat();
79 this.alignRightStringFormat.Alignment = StringAlignment.Far;
80 this.alignRightStringFormat.FormatFlags = StringFormatFlags.NoWrap;
82 if (File.Exists("gadget_background.png")) {
84 Image newBack = new Bitmap("gadget_background.png");
90 if (File.Exists("gadget_image.png")) {
92 image = new Bitmap("gadget_image.png");
96 if (File.Exists("gadget_foreground.png")) {
98 fore = new Bitmap("gadget_foreground.png");
102 if (File.Exists("gadget_bar_background.png")) {
104 Image newBarBack = new Bitmap("gadget_bar_background.png");
106 barBack = newBarBack;
110 if (File.Exists("gadget_bar_foreground.png")) {
112 Image newBarColor = new Bitmap("gadget_bar_foreground.png");
114 barFore = newBarColor;
118 this.Location = new Point(
119 settings.GetValue("sensorGadget.Location.X", 100),
120 settings.GetValue("sensorGadget.Location.Y", 100));
121 LocationChanged += delegate(object sender, EventArgs e) {
122 settings.SetValue("sensorGadget.Location.X", Location.X);
123 settings.SetValue("sensorGadget.Location.Y", Location.Y);
126 // get the custom to default dpi ratio
127 using (Bitmap b = new Bitmap(1, 1)) {
128 scale = b.HorizontalResolution / 96.0f;
131 SetFontSize(settings.GetValue("sensorGadget.FontSize", 7.5f));
132 Resize(settings.GetValue("sensorGadget.Width", Size.Width));
134 ContextMenu contextMenu = new ContextMenu();
135 MenuItem hardwareNamesItem = new MenuItem("Hardware Names");
136 contextMenu.MenuItems.Add(hardwareNamesItem);
137 MenuItem fontSizeMenu = new MenuItem("Font Size");
138 for (int i = 0; i < 4; i++) {
142 case 0: size = 6.5f; name = "Small"; break;
143 case 1: size = 7.5f; name = "Medium"; break;
144 case 2: size = 9f; name = "Large"; break;
145 case 3: size = 11f; name = "Very Large"; break;
146 default: throw new NotImplementedException();
148 MenuItem item = new MenuItem(name);
149 item.Checked = fontSize == size;
150 item.Click += delegate(object sender, EventArgs e) {
152 settings.SetValue("sensorGadget.FontSize", size);
153 foreach (MenuItem mi in fontSizeMenu.MenuItems)
154 mi.Checked = mi == item;
156 fontSizeMenu.MenuItems.Add(item);
158 contextMenu.MenuItems.Add(fontSizeMenu);
159 contextMenu.MenuItems.Add(new MenuItem("-"));
160 MenuItem lockItem = new MenuItem("Lock Position and Size");
161 contextMenu.MenuItems.Add(lockItem);
162 contextMenu.MenuItems.Add(new MenuItem("-"));
163 MenuItem alwaysOnTopItem = new MenuItem("Always on Top");
164 contextMenu.MenuItems.Add(alwaysOnTopItem);
165 MenuItem opacityMenu = new MenuItem("Opacity");
166 contextMenu.MenuItems.Add(opacityMenu);
167 Opacity = (byte)settings.GetValue("sensorGadget.Opacity", 255);
168 for (int i = 0; i < 5; i++) {
169 MenuItem item = new MenuItem((20 * (i + 1)).ToString() + " %");
170 byte o = (byte)(51 * (i + 1));
171 item.Checked = Opacity == o;
172 item.Click += delegate(object sender, EventArgs e) {
174 settings.SetValue("sensorGadget.Opacity", Opacity);
175 foreach (MenuItem mi in opacityMenu.MenuItems)
176 mi.Checked = mi == item;
178 opacityMenu.MenuItems.Add(item);
180 this.ContextMenu = contextMenu;
182 hardwareNames = new UserOption("sensorGadget.Hardwarenames", true,
183 hardwareNamesItem, settings);
184 hardwareNames.Changed += delegate(object sender, EventArgs e) {
188 alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false,
189 alwaysOnTopItem, settings);
190 alwaysOnTop.Changed += delegate(object sender, EventArgs e) {
191 this.AlwaysOnTop = alwaysOnTop.Value;
193 lockPositionAndSize = new UserOption("sensorGadget.LockPositionAndSize",
194 false, lockItem, settings);
195 lockPositionAndSize.Changed += delegate(object sender, EventArgs e) {
196 this.LockPositionAndSize = lockPositionAndSize.Value;
199 HitTest += delegate(object sender, HitTestEventArgs e) {
200 if (lockPositionAndSize.Value)
203 if (e.Location.X < leftBorder) {
204 e.HitResult = HitResult.Left;
207 if (e.Location.X > Size.Width - 1 - rightBorder) {
208 e.HitResult = HitResult.Right;
213 SizeChanged += delegate(object sender, EventArgs e) {
214 settings.SetValue("sensorGadget.Width", Size.Width);
218 VisibleChanged += delegate(object sender, EventArgs e) {
219 Rectangle bounds = new Rectangle(Location, Size);
220 Screen screen = Screen.FromRectangle(bounds);
221 Rectangle intersection =
222 Rectangle.Intersect(screen.WorkingArea, bounds);
223 if (intersection.Width < Math.Min(16, bounds.Width) ||
224 intersection.Height < Math.Min(16, bounds.Height))
226 Location = new Point(
227 screen.WorkingArea.Width / 2 - bounds.Width / 2,
228 screen.WorkingArea.Height / 2 - bounds.Height / 2);
232 MouseDoubleClick += delegate(object obj, MouseEventArgs args) {
233 SendHideShowCommand();
237 public override void Dispose() {
248 stringFormat.Dispose();
251 trimStringFormat.Dispose();
252 trimStringFormat = null;
254 alignRightStringFormat.Dispose();
255 alignRightStringFormat = null;
266 background.Dispose();
282 private void HardwareRemoved(IHardware hardware) {
283 hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
284 hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved);
285 foreach (ISensor sensor in hardware.Sensors)
286 SensorRemoved(sensor);
287 foreach (IHardware subHardware in hardware.SubHardware)
288 HardwareRemoved(subHardware);
291 private void HardwareAdded(IHardware hardware) {
292 foreach (ISensor sensor in hardware.Sensors)
294 hardware.SensorAdded += new SensorEventHandler(SensorAdded);
295 hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
296 foreach (IHardware subHardware in hardware.SubHardware)
297 HardwareAdded(subHardware);
300 private void SensorAdded(ISensor sensor) {
301 if (settings.GetValue(new Identifier(sensor.Identifier,
302 "gadget").ToString(), false))
306 private void SensorRemoved(ISensor sensor) {
307 if (Contains(sensor))
308 Remove(sensor, false);
311 public bool Contains(ISensor sensor) {
312 foreach (IList<ISensor> list in sensors.Values)
313 if (list.Contains(sensor))
318 public void Add(ISensor sensor) {
319 if (Contains(sensor)) {
322 // get the right hardware
323 IHardware hardware = sensor.Hardware;
324 while (hardware.Parent != null)
325 hardware = hardware.Parent;
327 // get the sensor list associated with the hardware
329 if (!sensors.TryGetValue(hardware, out list)) {
330 list = new List<ISensor>();
331 sensors.Add(hardware, list);
334 // insert the sensor at the right position
336 while (i < list.Count && (list[i].SensorType < sensor.SensorType ||
337 (list[i].SensorType == sensor.SensorType &&
338 list[i].Index < sensor.Index))) i++;
339 list.Insert(i, sensor);
342 new Identifier(sensor.Identifier, "gadget").ToString(), true);
348 public void Remove(ISensor sensor) {
349 Remove(sensor, true);
352 private void Remove(ISensor sensor, bool deleteConfig) {
354 settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString());
356 foreach (KeyValuePair<IHardware, IList<ISensor>> keyValue in sensors)
357 if (keyValue.Value.Contains(sensor)) {
358 keyValue.Value.Remove(sensor);
359 if (keyValue.Value.Count == 0) {
360 sensors.Remove(keyValue.Key);
367 public event EventHandler HideShowCommand;
369 public void SendHideShowCommand() {
370 if (HideShowCommand != null)
371 HideShowCommand(this, null);
374 private Font CreateFont(float size, FontStyle style) {
376 return new Font(SystemFonts.MessageBoxFont.FontFamily, size, style);
377 } catch (ArgumentException) {
378 // if the style is not supported, fall back to the original one
379 return new Font(SystemFonts.MessageBoxFont.FontFamily, size,
380 SystemFonts.MessageBoxFont.Style);
384 private void SetFontSize(float size) {
386 largeFont = CreateFont(fontSize, FontStyle.Bold);
387 smallFont = CreateFont(fontSize, FontStyle.Regular);
389 double scaledFontSize = fontSize * scale;
390 iconSize = (int)Math.Round(1.5 * scaledFontSize);
391 hardwareLineHeight = (int)Math.Round(1.66 * scaledFontSize);
392 sensorLineHeight = (int)Math.Round(1.33 * scaledFontSize);
393 leftMargin = leftBorder + (int)Math.Round(0.3 * scaledFontSize);
394 rightMargin = rightBorder + (int)Math.Round(0.3 * scaledFontSize);
395 topMargin = topBorder;
396 bottomMargin = bottomBorder + (int)Math.Round(0.3 * scaledFontSize);
397 progressWidth = (int)Math.Round(5.3 * scaledFontSize);
399 Resize((int)Math.Round(17.3 * scaledFontSize));
402 private void Resize() {
403 Resize(this.Size.Width);
406 private void Resize(int width) {
408 foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
409 if (hardwareNames.Value) {
411 y += hardwareLineHeight - sensorLineHeight;
412 y += hardwareLineHeight;
414 y += pair.Value.Count * sensorLineHeight;
416 if (sensors.Count == 0)
417 y += 4 * sensorLineHeight + hardwareLineHeight;
419 this.Size = new Size(width, y);
422 private void DrawImageWidthBorder(Graphics g, int width, int height,
423 Image back, int t, int b, int l, int r)
425 GraphicsUnit u = GraphicsUnit.Pixel;
427 g.DrawImage(back, new Rectangle(0, 0, l, t),
428 new Rectangle(0, 0, l, t), u);
429 g.DrawImage(back, new Rectangle(l, 0, width - l - r, t),
430 new Rectangle(l, 0, back.Width - l - r, t), u);
431 g.DrawImage(back, new Rectangle(width - r, 0, r, t),
432 new Rectangle(back.Width - r, 0, r, t), u);
434 g.DrawImage(back, new Rectangle(0, t, l, height - t - b),
435 new Rectangle(0, t, l, back.Height - t - b), u);
436 g.DrawImage(back, new Rectangle(l, t, width - l - r, height - t - b),
437 new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u);
438 g.DrawImage(back, new Rectangle(width - r, t, r, height - t - b),
439 new Rectangle(back.Width - r, t, r, back.Height - t - b), u);
441 g.DrawImage(back, new Rectangle(0, height - b, l, b),
442 new Rectangle(0, back.Height - b, l, b), u);
443 g.DrawImage(back, new Rectangle(l, height - b, width - l - r, b),
444 new Rectangle(l, back.Height - b, back.Width - l - r, b), u);
445 g.DrawImage(back, new Rectangle(width - r, height - b, r, b),
446 new Rectangle(back.Width - r, back.Height - b, r, b), u);
449 private void DrawBackground(Graphics g) {
453 if (w != background.Width || h != background.Height) {
455 background.Dispose();
456 background = new Bitmap(w, h, PixelFormat.Format32bppPArgb);
457 using (Graphics graphics = Graphics.FromImage(background)) {
459 DrawImageWidthBorder(graphics, w, h, back, topBorder, bottomBorder,
460 leftBorder, rightBorder);
463 DrawImageWidthBorder(graphics, w, h, fore, topBorder, bottomBorder,
464 leftBorder, rightBorder);
467 int width = w - leftBorder - rightBorder;
468 int height = h - topBorder - bottomBorder;
469 float xRatio = width / (float)image.Width;
470 float yRatio = height / (float)image.Height;
471 float destWidth, destHeight;
472 float xOffset, yOffset;
473 if (xRatio < yRatio) {
475 destHeight = image.Height * xRatio;
477 yOffset = 0.5f * (height - destHeight);
479 destWidth = image.Width * yRatio;
481 xOffset = 0.5f * (width - destWidth);
485 graphics.DrawImage(image,
486 new RectangleF(leftBorder + xOffset, topBorder + yOffset,
487 destWidth, destHeight));
492 g.DrawImageUnscaled(background, 0, 0);
495 private void DrawProgress(Graphics g, float x, float y,
496 float width, float height, float progress)
499 new RectangleF(x + width * progress, y, width * (1 - progress), height),
500 new RectangleF(barBack.Width * progress, 0,
501 (1 - progress) * barBack.Width, barBack.Height),
504 new RectangleF(x, y, width * progress, height),
505 new RectangleF(0, 0, progress * barFore.Width, barFore.Height),
509 protected override void OnPaint(PaintEventArgs e) {
510 Graphics g = e.Graphics;
513 g.Clear(Color.Transparent);
520 if (sensors.Count == 0) {
522 g.DrawString("Right-click on a sensor in the main window and select " +
523 "\"Show in Gadget\" to show the sensor here.",
524 smallFont, Brushes.White,
525 new Rectangle(x, y - 1, w - rightBorder - x, 0));
528 foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
529 if (hardwareNames.Value) {
531 y += hardwareLineHeight - sensorLineHeight;
533 g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType),
534 new Rectangle(x, y + 1, iconSize, iconSize));
536 g.DrawString(pair.Key.Name, largeFont, Brushes.White,
537 new Rectangle(x, y - 1, w - rightBorder - x, 0),
539 y += hardwareLineHeight;
542 foreach (ISensor sensor in pair.Value) {
546 if ((sensor.SensorType != SensorType.Load &&
547 sensor.SensorType != SensorType.Control &&
548 sensor.SensorType != SensorType.Level) || !sensor.Value.HasValue)
552 if (sensor.Value.HasValue) {
554 switch (sensor.SensorType) {
555 case SensorType.Voltage:
558 case SensorType.Clock:
559 format = "{0:F0} MHz";
561 case SensorType.Temperature:
562 format = "{0:F1} °C";
565 format = "{0:F0} RPM";
567 case SensorType.Flow:
568 format = "{0:F0} L/h";
570 case SensorType.Power:
573 case SensorType.Data:
574 format = "{0:F1} GB";
576 case SensorType.Factor:
581 if (sensor.SensorType == SensorType.Temperature &&
582 unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) {
583 formatted = string.Format("{0:F1} °F",
584 sensor.Value * 1.8 + 32);
586 formatted = string.Format(format, sensor.Value);
592 g.DrawString(formatted, smallFont, darkWhite,
593 new RectangleF(-1, y - 1, w - rightMargin + 3, 0),
594 alignRightStringFormat);
596 remainingWidth = w - (int)Math.Floor(g.MeasureString(formatted,
597 smallFont, w, StringFormat.GenericTypographic).Width) -
600 DrawProgress(g, w - progressWidth - rightMargin,
601 y + 0.35f * sensorLineHeight, progressWidth,
602 0.6f * sensorLineHeight, 0.01f * sensor.Value.Value);
604 remainingWidth = w - progressWidth - rightMargin;
607 remainingWidth -= leftMargin + 2;
608 if (remainingWidth > 0) {
609 g.DrawString(sensor.Name, smallFont, darkWhite,
610 new RectangleF(leftMargin - 1, y - 1, remainingWidth, 0),
614 y += sensorLineHeight;
619 private class HardwareComparer : IComparer<IHardware> {
620 public int Compare(IHardware x, IHardware y) {
621 if (x == null && y == null)
628 if (x.HardwareType != y.HardwareType)
629 return x.HardwareType.CompareTo(y.HardwareType);
631 return x.Identifier.CompareTo(y.Identifier);