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.
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