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