moel@176: /* moel@176: moel@176: Version: MPL 1.1/GPL 2.0/LGPL 2.1 moel@176: moel@176: The contents of this file are subject to the Mozilla Public License Version moel@176: 1.1 (the "License"); you may not use this file except in compliance with moel@176: the License. You may obtain a copy of the License at moel@176: moel@176: http://www.mozilla.org/MPL/ moel@176: moel@176: Software distributed under the License is distributed on an "AS IS" basis, moel@176: WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License moel@176: for the specific language governing rights and limitations under the License. moel@176: moel@176: The Original Code is the Open Hardware Monitor code. moel@176: moel@176: The Initial Developer of the Original Code is moel@176: Michael Möller . moel@176: Portions created by the Initial Developer are Copyright (C) 2010 moel@176: the Initial Developer. All Rights Reserved. moel@176: moel@176: Contributor(s): moel@176: moel@176: Alternatively, the contents of this file may be used under the terms of moel@176: either the GNU General Public License Version 2 or later (the "GPL"), or moel@176: the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), moel@176: in which case the provisions of the GPL or the LGPL are applicable instead moel@176: of those above. If you wish to allow use of your version of this file only moel@176: under the terms of either the GPL or the LGPL, and not to allow others to moel@176: use your version of this file under the terms of the MPL, indicate your moel@176: decision by deleting the provisions above and replace them with the notice moel@176: and other provisions required by the GPL or the LGPL. If you do not delete moel@176: the provisions above, a recipient may use your version of this file under moel@176: the terms of any one of the MPL, the GPL or the LGPL. moel@176: moel@176: */ moel@176: moel@176: using System; moel@176: using System.Collections.Generic; moel@176: using System.Drawing; moel@176: using System.Windows.Forms; moel@176: using OpenHardwareMonitor.Hardware; moel@176: moel@176: namespace OpenHardwareMonitor.GUI { moel@176: public class SensorGadget : Gadget { moel@176: moel@176: private UnitManager unitManager; moel@176: moel@176: private Image back = Utilities.EmbeddedResources.GetImage("gadget.png"); moel@176: private Image barBack = Utilities.EmbeddedResources.GetImage("barback.png"); moel@176: private Image barblue = Utilities.EmbeddedResources.GetImage("barblue.png"); moel@176: private const int topBorder = 4; moel@176: private const int bottomBorder = 6; moel@176: private const int leftBorder = 6; moel@176: private const int rightBorder = 6; moel@176: private const int iconSize = 11; moel@176: private const int hardwareLineHeight = 13; moel@176: private const int sensorLineHeight = 11; moel@176: moel@176: private IDictionary> sensors = moel@176: new SortedDictionary>(new HardwareComparer()); moel@176: moel@176: private PersistentSettings settings; moel@176: private UserOption alwaysOnTop; moel@176: private UserOption lockPosition; moel@176: moel@176: private Font largeFont; moel@176: private Font smallFont; moel@176: private Brush darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0)); moel@176: moel@176: public SensorGadget(IComputer computer, PersistentSettings settings, moel@176: UnitManager unitManager) moel@176: { moel@176: this.unitManager = unitManager; moel@176: this.settings = settings; moel@176: computer.HardwareAdded += new HardwareEventHandler(HardwareAdded); moel@176: computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved); moel@176: moel@176: this.largeFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 7.5f, moel@176: FontStyle.Bold); moel@176: this.smallFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 6.5f); moel@176: moel@176: this.Location = new Point( moel@176: settings.GetValue("sensorGadget.Location.X", 100), moel@176: settings.GetValue("sensorGadget.Location.Y", 100)); moel@176: LocationChanged += delegate(object sender, EventArgs e) { moel@176: settings.SetValue("sensorGadget.Location.X", Location.X); moel@176: settings.SetValue("sensorGadget.Location.Y", Location.Y); moel@176: }; moel@176: moel@176: ContextMenu contextMenu = new ContextMenu(); moel@176: MenuItem lockItem = new MenuItem("Lock Position"); moel@176: contextMenu.MenuItems.Add(lockItem); moel@176: contextMenu.MenuItems.Add(new MenuItem("-")); moel@176: MenuItem alwaysOnTopItem = new MenuItem("Always on Top"); moel@176: contextMenu.MenuItems.Add(alwaysOnTopItem); moel@176: MenuItem opacityMenu = new MenuItem("Opacity"); moel@176: contextMenu.MenuItems.Add(opacityMenu); moel@176: Opacity = (byte)settings.GetValue("sensorGadget.Opacity", 255); moel@176: for (int i = 0; i < 5; i++) { moel@176: MenuItem item = new MenuItem((20 * (i + 1)).ToString() + " %"); moel@176: byte o = (byte)(51 * (i + 1)); moel@176: item.Tag = o; moel@176: item.Checked = Opacity == o; moel@176: item.Click += delegate(object sender, EventArgs e) { moel@176: Opacity = (byte)item.Tag; moel@176: settings.SetValue("sensorGadget.Opacity", Opacity); moel@176: foreach (MenuItem mi in opacityMenu.MenuItems) moel@176: mi.Checked = (byte)mi.Tag == Opacity; moel@176: }; moel@176: opacityMenu.MenuItems.Add(item); moel@176: } moel@176: this.ContextMenu = contextMenu; moel@176: moel@176: alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false, moel@176: alwaysOnTopItem, settings); moel@176: alwaysOnTop.Changed += delegate(object sender, EventArgs e) { moel@176: this.AlwaysOnTop = alwaysOnTop.Value; moel@176: }; moel@176: lockPosition = new UserOption("sensorGadget.LockPosition", false, moel@176: lockItem, settings); moel@176: lockPosition.Changed += delegate(object sender, EventArgs e) { moel@176: this.LockPosition = lockPosition.Value; moel@176: }; moel@176: moel@176: Resize(); moel@176: } moel@176: moel@176: private void HardwareRemoved(IHardware hardware) { moel@176: hardware.SensorAdded -= new SensorEventHandler(SensorAdded); moel@176: hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved); moel@176: foreach (ISensor sensor in hardware.Sensors) moel@176: SensorRemoved(sensor); moel@176: foreach (IHardware subHardware in hardware.SubHardware) moel@176: HardwareRemoved(subHardware); moel@176: } moel@176: moel@176: private void HardwareAdded(IHardware hardware) { moel@176: foreach (ISensor sensor in hardware.Sensors) moel@176: SensorAdded(sensor); moel@176: hardware.SensorAdded += new SensorEventHandler(SensorAdded); moel@176: hardware.SensorRemoved += new SensorEventHandler(SensorRemoved); moel@176: foreach (IHardware subHardware in hardware.SubHardware) moel@176: HardwareAdded(subHardware); moel@176: } moel@176: moel@176: private void SensorAdded(ISensor sensor) { moel@176: if (settings.GetValue(new Identifier(sensor.Identifier, moel@176: "gadget").ToString(), false)) moel@176: Add(sensor); moel@176: } moel@176: moel@176: private void SensorRemoved(ISensor sensor) { moel@176: if (Contains(sensor)) moel@176: Remove(sensor, false); moel@176: } moel@176: moel@176: public bool Contains(ISensor sensor) { moel@176: foreach (IList list in sensors.Values) moel@176: if (list.Contains(sensor)) moel@176: return true; moel@176: return false; moel@176: } moel@176: moel@176: public void Add(ISensor sensor) { moel@176: if (Contains(sensor)) { moel@176: return; moel@176: } else { moel@176: // get the right hardware moel@176: IHardware hardware = sensor.Hardware; moel@176: while (hardware.Parent != null) moel@176: hardware = hardware.Parent; moel@176: moel@176: // get the sensor list associated with the hardware moel@176: IList list; moel@176: if (!sensors.TryGetValue(hardware, out list)) { moel@176: list = new List(); moel@176: sensors.Add(hardware, list); moel@176: } moel@176: moel@176: // insert the sensor at the right position moel@176: int i = 0; moel@176: while (i < list.Count && (list[i].SensorType < sensor.SensorType || moel@176: (list[i].SensorType == sensor.SensorType && moel@176: list[i].Index < sensor.Index))) i++; moel@176: list.Insert(i, sensor); moel@176: moel@176: settings.SetValue( moel@176: new Identifier(sensor.Identifier, "gadget").ToString(), true); moel@176: moel@176: Resize(); moel@176: Redraw(); moel@176: } moel@176: } moel@176: moel@176: public void Remove(ISensor sensor) { moel@176: Remove(sensor, true); moel@176: } moel@176: moel@176: private void Remove(ISensor sensor, bool deleteConfig) { moel@176: if (deleteConfig) moel@176: settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString()); moel@176: moel@176: foreach (KeyValuePair> keyValue in sensors) moel@176: if (keyValue.Value.Contains(sensor)) { moel@176: keyValue.Value.Remove(sensor); moel@176: if (keyValue.Value.Count == 0) { moel@176: sensors.Remove(keyValue.Key); moel@176: break; moel@176: } moel@176: } moel@176: Resize(); moel@176: Redraw(); moel@176: } moel@176: moel@176: private void Resize() { moel@176: int y = topBorder + 1; moel@176: foreach (KeyValuePair> pair in sensors) { moel@176: y += hardwareLineHeight; moel@176: y += pair.Value.Count * sensorLineHeight; moel@176: } moel@176: y += bottomBorder + 2; moel@176: y = Math.Max(y, topBorder + bottomBorder + 10); moel@176: this.Size = new Size(130, y); moel@176: } moel@176: moel@176: private void DrawBackground(Graphics g) { moel@176: int w = Size.Width; moel@176: int h = Size.Height; moel@176: int t = topBorder; moel@176: int b = bottomBorder; moel@176: int l = leftBorder; moel@176: int r = rightBorder; moel@176: GraphicsUnit u = GraphicsUnit.Pixel; moel@176: moel@176: g.DrawImage(back, new Rectangle(0, 0, l, t), moel@176: new Rectangle(0, 0, l, t), u); moel@176: g.DrawImage(back, new Rectangle(l, 0, w - l - r, t), moel@176: new Rectangle(l, 0, back.Width - l - r, t), u); moel@176: g.DrawImage(back, new Rectangle(w - r, 0, r, t), moel@176: new Rectangle(back.Width - r, 0, r, t), u); moel@176: moel@176: g.DrawImage(back, new Rectangle(0, t, l, h - t - b), moel@176: new Rectangle(0, t, l, back.Height - t - b), u); moel@176: g.DrawImage(back, new Rectangle(l, t, w - l - r, h - t - b), moel@176: new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u); moel@176: g.DrawImage(back, new Rectangle(w - r, t, r, h - t - b), moel@176: new Rectangle(back.Width - r, t, r, back.Height - t - b), u); moel@176: moel@176: g.DrawImage(back, new Rectangle(0, h - b, l, b), moel@176: new Rectangle(0, back.Height - b, l, b), u); moel@176: g.DrawImage(back, new Rectangle(l, h - b, w - l - r, b), moel@176: new Rectangle(l, back.Height - b, back.Width - l - r, b), u); moel@176: g.DrawImage(back, new Rectangle(w - r, h - b, r, b), moel@176: new Rectangle(back.Width - r, back.Height - b, r, b), u); moel@176: } moel@176: moel@176: private void DrawProgress(Graphics g, int x, int y, int width, int height, moel@176: float progress) moel@176: { moel@176: g.DrawImage(barBack, moel@176: new RectangleF(x + width * progress, y, width * (1 - progress), height), moel@176: new RectangleF(barBack.Width * progress, 0, moel@176: (1 - progress) * barBack.Width, barBack.Height), moel@176: GraphicsUnit.Pixel); moel@176: g.DrawImage(barblue, moel@176: new RectangleF(x, y, width * progress, height), moel@176: new RectangleF(0, 0, progress * barblue.Width, barblue.Height), moel@176: GraphicsUnit.Pixel); moel@176: } moel@176: moel@176: protected override void OnPaint(PaintEventArgs e) { moel@176: Graphics g = e.Graphics; moel@176: int w = Size.Width; moel@176: int h = Size.Height; moel@176: moel@176: g.Clear(Color.Transparent); moel@176: moel@176: DrawBackground(g); moel@176: moel@176: StringFormat stringFormat = new StringFormat(); moel@176: stringFormat.Alignment = StringAlignment.Far; moel@176: moel@176: int x; moel@176: int y = topBorder + 1; moel@176: foreach (KeyValuePair> pair in sensors) { moel@176: x = leftBorder + 1; moel@176: g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType), moel@176: new Rectangle(x, y + 2, iconSize, iconSize)); moel@176: x += iconSize + 1; moel@176: g.DrawString(pair.Key.Name, largeFont, Brushes.White, moel@176: new Rectangle(x, y, w - rightBorder - x, 15)); moel@176: y += hardwareLineHeight; moel@176: moel@176: foreach (ISensor sensor in pair.Value) { moel@176: moel@176: g.DrawString(sensor.Name + ":", smallFont, darkWhite, moel@176: new Rectangle(9, y, 64, 15)); moel@176: moel@176: if (sensor.SensorType != SensorType.Load && moel@176: sensor.SensorType != SensorType.Control) moel@176: { moel@176: string format = ""; moel@176: switch (sensor.SensorType) { moel@176: case SensorType.Voltage: moel@176: format = "{0:F2} V"; moel@176: break; moel@176: case SensorType.Clock: moel@176: format = "{0:F0} MHz"; moel@176: break; moel@176: case SensorType.Temperature: moel@176: format = "{0:F1} °C"; moel@176: break; moel@176: case SensorType.Fan: moel@176: format = "{0:F0} RPM"; moel@176: break; moel@176: case SensorType.Flow: moel@176: format = "{0:F0} L/h"; moel@176: break; moel@176: } moel@176: moel@176: string formattedValue; moel@176: if (sensor.SensorType == SensorType.Temperature && moel@176: unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) { moel@176: formattedValue = string.Format("{0:F1} °F", moel@176: sensor.Value * 1.8 + 32); moel@176: } else { moel@176: formattedValue = string.Format(format, sensor.Value); moel@176: } moel@176: moel@176: x = 75; moel@176: g.DrawString(formattedValue, smallFont, darkWhite, moel@176: new RectangleF(x, y, w - x - 9, 15), stringFormat); moel@176: } else { moel@176: x = 80; moel@176: DrawProgress(g, x, y + 4, w - x - 9, 6, 0.01f * sensor.Value.Value); moel@176: } moel@176: moel@176: y += sensorLineHeight; moel@176: } moel@176: } moel@176: } moel@176: moel@176: private class HardwareComparer : IComparer { moel@176: public int Compare(IHardware x, IHardware y) { moel@176: if (x == null && y == null) moel@176: return 0; moel@176: if (x == null) moel@176: return -1; moel@176: if (y == null) moel@176: return 1; moel@176: moel@176: if (x.HardwareType != y.HardwareType) moel@176: return x.HardwareType.CompareTo(y.HardwareType); moel@176: moel@176: return x.Name.CompareTo(y.Name); moel@176: } moel@176: } moel@176: } moel@176: } moel@176: