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