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