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