GUI/SensorGadget.cs
author moel.mich
Tue, 07 Sep 2010 22:15:02 +0000
changeset 181 9901dbb25f18
parent 178 67b9b4d8c5fc
child 183 3096735e99b2
permissions -rw-r--r--
Improved the gadget formatting and added an option to remove the hardware names in the gadget.
     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 = 12;
    58     private const int sensorLineHeight = 10;
    59 
    60     private IDictionary<IHardware, IList<ISensor>> sensors =
    61       new SortedDictionary<IHardware, IList<ISensor>>(new HardwareComparer());
    62 
    63     private PersistentSettings settings;
    64     private UserOption hardwareNames;
    65     private UserOption alwaysOnTop;
    66     private UserOption lockPosition;
    67 
    68     private Font largeFont;
    69     private Font smallFont;
    70     private Brush darkWhite;
    71     private StringFormat trimStringFormat;
    72     private StringFormat alignRightStringFormat;
    73 
    74     public SensorGadget(IComputer computer, PersistentSettings settings, 
    75       UnitManager unitManager) 
    76     {
    77       this.unitManager = unitManager;
    78       this.settings = settings;
    79       computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
    80       computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
    81 
    82       this.largeFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 7.5f, 
    83         FontStyle.Bold); 
    84       this.smallFont = new Font(SystemFonts.MessageBoxFont.FontFamily, 7.5f);
    85       this.darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0));
    86 
    87       this.trimStringFormat = new StringFormat();
    88       this.trimStringFormat.Trimming = StringTrimming.EllipsisCharacter;
    89 
    90       this.alignRightStringFormat = new StringFormat();
    91       this.alignRightStringFormat.Alignment = StringAlignment.Far;
    92 
    93       this.Location = new Point(
    94         settings.GetValue("sensorGadget.Location.X", 100),
    95         settings.GetValue("sensorGadget.Location.Y", 100)); 
    96       LocationChanged += delegate(object sender, EventArgs e) {
    97         settings.SetValue("sensorGadget.Location.X", Location.X);
    98         settings.SetValue("sensorGadget.Location.Y", Location.Y);
    99       };
   100       
   101       ContextMenu contextMenu = new ContextMenu();
   102       MenuItem hardwareNamesItem = new MenuItem("Hardware Names");
   103       contextMenu.MenuItems.Add(hardwareNamesItem);
   104       contextMenu.MenuItems.Add(new MenuItem("-"));
   105       MenuItem lockItem = new MenuItem("Lock Position");
   106       contextMenu.MenuItems.Add(lockItem);
   107       contextMenu.MenuItems.Add(new MenuItem("-"));
   108       MenuItem alwaysOnTopItem = new MenuItem("Always on Top");
   109       contextMenu.MenuItems.Add(alwaysOnTopItem);
   110       MenuItem opacityMenu = new MenuItem("Opacity");
   111       contextMenu.MenuItems.Add(opacityMenu);
   112       Opacity = (byte)settings.GetValue("sensorGadget.Opacity", 255);      
   113       for (int i = 0; i < 5; i++) {
   114         MenuItem item = new MenuItem((20 * (i + 1)).ToString() + " %");
   115         byte o = (byte)(51 * (i + 1));
   116         item.Checked = Opacity == o;
   117         item.Click += delegate(object sender, EventArgs e) {
   118           Opacity = o;
   119           settings.SetValue("sensorGadget.Opacity", Opacity);
   120           foreach (MenuItem mi in opacityMenu.MenuItems)
   121             mi.Checked = mi == item;          
   122         };
   123         opacityMenu.MenuItems.Add(item);
   124       }
   125       this.ContextMenu = contextMenu;
   126 
   127       hardwareNames = new UserOption("sensorGadget.Hardwarenames", true,
   128         hardwareNamesItem, settings);
   129       hardwareNames.Changed += delegate(object sender, EventArgs e) {
   130         Resize();
   131         Redraw();
   132       };
   133 
   134       alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false, 
   135         alwaysOnTopItem, settings);
   136       alwaysOnTop.Changed += delegate(object sender, EventArgs e) {
   137         this.AlwaysOnTop = alwaysOnTop.Value;
   138       };
   139       lockPosition = new UserOption("sensorGadget.LockPosition", false,
   140         lockItem, settings);
   141       lockPosition.Changed += delegate(object sender, EventArgs e) {
   142         this.LockPosition = lockPosition.Value;
   143       };
   144 
   145       Resize();
   146     }
   147 
   148     public override void Dispose() {
   149 
   150       largeFont.Dispose();
   151       largeFont = null;
   152 
   153       smallFont.Dispose();
   154       smallFont = null;
   155 
   156       darkWhite.Dispose();
   157       darkWhite = null;
   158 
   159       trimStringFormat.Dispose();
   160       trimStringFormat = null;
   161 
   162       alignRightStringFormat.Dispose();
   163       alignRightStringFormat = null;      
   164 
   165       base.Dispose();
   166     }
   167 
   168     private void HardwareRemoved(IHardware hardware) {
   169       hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
   170       hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved);
   171       foreach (ISensor sensor in hardware.Sensors)
   172         SensorRemoved(sensor);
   173       foreach (IHardware subHardware in hardware.SubHardware)
   174         HardwareRemoved(subHardware);
   175     }
   176 
   177     private void HardwareAdded(IHardware hardware) {
   178       foreach (ISensor sensor in hardware.Sensors)
   179         SensorAdded(sensor);
   180       hardware.SensorAdded += new SensorEventHandler(SensorAdded);
   181       hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
   182       foreach (IHardware subHardware in hardware.SubHardware)
   183         HardwareAdded(subHardware);
   184     }
   185 
   186     private void SensorAdded(ISensor sensor) {
   187       if (settings.GetValue(new Identifier(sensor.Identifier,
   188         "gadget").ToString(), false)) 
   189         Add(sensor);
   190     }
   191 
   192     private void SensorRemoved(ISensor sensor) {
   193       if (Contains(sensor))
   194         Remove(sensor, false);
   195     }
   196 
   197     public bool Contains(ISensor sensor) {
   198       foreach (IList<ISensor> list in sensors.Values)
   199         if (list.Contains(sensor))
   200           return true;
   201       return false;
   202     }
   203 
   204     public void Add(ISensor sensor) {
   205       if (Contains(sensor)) {
   206         return;
   207       } else {
   208         // get the right hardware
   209         IHardware hardware = sensor.Hardware;
   210         while (hardware.Parent != null)
   211           hardware = hardware.Parent;
   212 
   213         // get the sensor list associated with the hardware
   214         IList<ISensor> list;
   215         if (!sensors.TryGetValue(hardware, out list)) {
   216           list = new List<ISensor>();
   217           sensors.Add(hardware, list);
   218         }
   219 
   220         // insert the sensor at the right position
   221         int i = 0;
   222         while (i < list.Count && (list[i].SensorType < sensor.SensorType || 
   223           (list[i].SensorType == sensor.SensorType && 
   224            list[i].Index < sensor.Index))) i++;
   225         list.Insert(i, sensor);
   226 
   227         settings.SetValue(
   228           new Identifier(sensor.Identifier, "gadget").ToString(), true);
   229         
   230         Resize();
   231         Redraw();
   232       }
   233     }
   234 
   235     public void Remove(ISensor sensor) {
   236       Remove(sensor, true);
   237     }
   238 
   239     private void Remove(ISensor sensor, bool deleteConfig) {
   240       if (deleteConfig) 
   241         settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString());
   242 
   243       foreach (KeyValuePair<IHardware, IList<ISensor>> keyValue in sensors)
   244         if (keyValue.Value.Contains(sensor)) {
   245           keyValue.Value.Remove(sensor);          
   246           if (keyValue.Value.Count == 0) {
   247             sensors.Remove(keyValue.Key);
   248             break;
   249           }
   250         }
   251       Resize();
   252       Redraw();
   253     }
   254 
   255     private void Resize() {
   256       int y = topBorder + 1;      
   257       foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
   258         if (hardwareNames.Value) {
   259           if (y > topBorder + 1)
   260             y += 2;
   261           y += hardwareLineHeight;
   262         }
   263         y += pair.Value.Count * sensorLineHeight;
   264       }
   265       y += bottomBorder + 3;
   266       y = Math.Max(y, topBorder + bottomBorder + 10);
   267       this.Size = new Size(130, y);
   268     }
   269 
   270     private void DrawBackground(Graphics g) {
   271       int w = Size.Width;
   272       int h = Size.Height;
   273       int t = topBorder;
   274       int b = bottomBorder;
   275       int l = leftBorder;
   276       int r = rightBorder;
   277       GraphicsUnit u = GraphicsUnit.Pixel;
   278 
   279       g.DrawImage(back, new Rectangle(0, 0, l, t),
   280         new Rectangle(0, 0, l, t), u);
   281       g.DrawImage(back, new Rectangle(l, 0, w - l - r, t),
   282         new Rectangle(l, 0, back.Width - l - r, t), u);
   283       g.DrawImage(back, new Rectangle(w - r, 0, r, t),
   284         new Rectangle(back.Width - r, 0, r, t), u);
   285 
   286       g.DrawImage(back, new Rectangle(0, t, l, h - t - b),
   287         new Rectangle(0, t, l, back.Height - t - b), u);
   288       g.DrawImage(back, new Rectangle(l, t, w - l - r, h - t - b),
   289         new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u);
   290       g.DrawImage(back, new Rectangle(w - r, t, r, h - t - b),
   291         new Rectangle(back.Width - r, t, r, back.Height - t - b), u);
   292 
   293       g.DrawImage(back, new Rectangle(0, h - b, l, b),
   294         new Rectangle(0, back.Height - b, l, b), u);
   295       g.DrawImage(back, new Rectangle(l, h - b, w - l - r, b),
   296         new Rectangle(l, back.Height - b, back.Width - l - r, b), u);
   297       g.DrawImage(back, new Rectangle(w - r, h - b, r, b),
   298         new Rectangle(back.Width - r, back.Height - b, r, b), u);
   299     }
   300 
   301     private void DrawProgress(Graphics g, int x, int y, int width, int height,
   302       float progress) 
   303     {
   304       g.DrawImage(barBack, 
   305         new RectangleF(x + width * progress, y, width * (1 - progress), height), 
   306         new RectangleF(barBack.Width * progress, 0, 
   307           (1 - progress) * barBack.Width, barBack.Height), 
   308         GraphicsUnit.Pixel);
   309       g.DrawImage(barblue,
   310         new RectangleF(x, y, width * progress, height),
   311         new RectangleF(0, 0, progress * barblue.Width, barblue.Height),
   312         GraphicsUnit.Pixel);
   313     }
   314 
   315     protected override void OnPaint(PaintEventArgs e) {
   316       Graphics g = e.Graphics;
   317       int w = Size.Width;
   318       int h = Size.Height;
   319 
   320       g.Clear(Color.Transparent);
   321 
   322       DrawBackground(g);
   323 
   324       int x;
   325       int y = topBorder + 1;
   326       foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
   327         if (hardwareNames.Value) {
   328           if (y > topBorder + 1)
   329             y += 2;
   330           x = leftBorder + 1;
   331           g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType),
   332             new Rectangle(x, y + 1, iconSize, iconSize));
   333           x += iconSize + 1;
   334           g.DrawString(pair.Key.Name, largeFont, Brushes.White,
   335             new Rectangle(x, y - 1, w - rightBorder - x, 15));
   336           y += hardwareLineHeight;
   337         }
   338 
   339         foreach (ISensor sensor in pair.Value) {
   340           int restWidth;
   341 
   342           if (sensor.SensorType != SensorType.Load && 
   343             sensor.SensorType != SensorType.Control) 
   344           {
   345             string format = "";
   346             switch (sensor.SensorType) {
   347               case SensorType.Voltage:
   348                 format = "{0:F2} V";
   349                 break;
   350               case SensorType.Clock:
   351                 format = "{0:F0} MHz";
   352                 break;
   353               case SensorType.Temperature:
   354                 format = "{0:F1} °C";
   355                 break;
   356               case SensorType.Fan:
   357                 format = "{0:F0} RPM";
   358                 break;
   359               case SensorType.Flow:
   360                 format = "{0:F0} L/h";
   361                 break;
   362             }
   363 
   364             string formattedValue;
   365             if (sensor.SensorType == SensorType.Temperature &&
   366               unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) {
   367               formattedValue = string.Format("{0:F1} °F",
   368                 sensor.Value * 1.8 + 32);
   369             } else {
   370               formattedValue = string.Format(format, sensor.Value);
   371             }
   372 
   373             int rightMargin = 8;
   374             g.DrawString(formattedValue, smallFont, darkWhite,
   375               new RectangleF(-1, y - 1, w - rightMargin + 2, 15), 
   376               alignRightStringFormat);
   377 
   378             restWidth = w - (int)Math.Floor(g.MeasureString(formattedValue,
   379               smallFont, w, StringFormat.GenericTypographic).Width) - 
   380               rightMargin;
   381           } else {
   382             restWidth = 80;
   383             DrawProgress(g, restWidth, y + 4, w - restWidth - 9, 6, 
   384               0.01f * sensor.Value.Value);
   385           }
   386 
   387           int leftMargin = 8;
   388           g.DrawString(sensor.Name, smallFont, darkWhite,
   389             new RectangleF(leftMargin - 1, y - 1, restWidth - leftMargin + 2, 
   390             15), trimStringFormat);
   391 
   392           y += sensorLineHeight;
   393         }
   394       }
   395     }
   396 
   397     private class HardwareComparer : IComparer<IHardware> {
   398       public int Compare(IHardware x, IHardware y) {
   399         if (x == null && y == null)
   400           return 0;
   401         if (x == null)
   402           return -1;
   403         if (y == null)
   404           return 1;
   405 
   406         if (x.HardwareType != y.HardwareType)
   407           return x.HardwareType.CompareTo(y.HardwareType);
   408 
   409         return x.Name.CompareTo(y.Name);
   410       }
   411     }
   412   }
   413 }
   414