GUI/SensorGadget.cs
author moel.mich
Sat, 02 Oct 2010 18:15:46 +0000
changeset 206 1fa8eddc24a7
parent 187 a7c93597137f
child 215 79e9a77f6a71
permissions -rw-r--r--
Replaced HttpUtility.UrlEncode with Uri.EscapeDataString and deleted the reference to the System.Web assembly. The System.Web assembly seems to be missing on some .NET 4.0 installations (and the overhead of using it is a bit large, just for the UrlEncode method).
moel@202
     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@183
    52
    private const int topBorder = 6;
moel@183
    53
    private const int bottomBorder = 7;
moel@176
    54
    private const int leftBorder = 6;
moel@183
    55
    private const int rightBorder = 7;
moel@183
    56
moel@183
    57
    private float fontSize;
moel@183
    58
    private int iconSize;
moel@183
    59
    private int hardwareLineHeight;
moel@183
    60
    private int sensorLineHeight;
moel@183
    61
    private int rightMargin;
moel@183
    62
    private int leftMargin;
moel@183
    63
    private int topMargin;
moel@183
    64
    private int bottomMargin;
moel@183
    65
    private int progressWidth;
moel@176
    66
moel@176
    67
    private IDictionary<IHardware, IList<ISensor>> sensors =
moel@176
    68
      new SortedDictionary<IHardware, IList<ISensor>>(new HardwareComparer());
moel@176
    69
moel@176
    70
    private PersistentSettings settings;
moel@181
    71
    private UserOption hardwareNames;
moel@176
    72
    private UserOption alwaysOnTop;
moel@183
    73
    private UserOption lockPositionAndSize;
moel@176
    74
moel@176
    75
    private Font largeFont;
moel@176
    76
    private Font smallFont;
moel@181
    77
    private Brush darkWhite;
moel@183
    78
    private StringFormat stringFormat;
moel@181
    79
    private StringFormat trimStringFormat;
moel@181
    80
    private StringFormat alignRightStringFormat;
moel@176
    81
moel@176
    82
    public SensorGadget(IComputer computer, PersistentSettings settings, 
moel@176
    83
      UnitManager unitManager) 
moel@176
    84
    {
moel@176
    85
      this.unitManager = unitManager;
moel@176
    86
      this.settings = settings;
moel@176
    87
      computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
moel@183
    88
      computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);      
moel@176
    89
moel@181
    90
      this.darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0));
moel@181
    91
moel@183
    92
      this.stringFormat = new StringFormat();
moel@183
    93
      this.stringFormat.FormatFlags = StringFormatFlags.NoWrap;
moel@183
    94
moel@181
    95
      this.trimStringFormat = new StringFormat();
moel@181
    96
      this.trimStringFormat.Trimming = StringTrimming.EllipsisCharacter;
moel@183
    97
      this.trimStringFormat.FormatFlags = StringFormatFlags.NoWrap;
moel@181
    98
moel@181
    99
      this.alignRightStringFormat = new StringFormat();
moel@181
   100
      this.alignRightStringFormat.Alignment = StringAlignment.Far;
moel@183
   101
      this.alignRightStringFormat.FormatFlags = StringFormatFlags.NoWrap;
moel@176
   102
moel@176
   103
      this.Location = new Point(
moel@176
   104
        settings.GetValue("sensorGadget.Location.X", 100),
moel@176
   105
        settings.GetValue("sensorGadget.Location.Y", 100)); 
moel@176
   106
      LocationChanged += delegate(object sender, EventArgs e) {
moel@176
   107
        settings.SetValue("sensorGadget.Location.X", Location.X);
moel@176
   108
        settings.SetValue("sensorGadget.Location.Y", Location.Y);
moel@176
   109
      };
moel@183
   110
moel@183
   111
      SetFontSize(settings.GetValue("sensorGadget.FontSize", 7.5f));
moel@183
   112
      Resize(settings.GetValue("sensorGadget.Width", Size.Width));
moel@176
   113
      
moel@176
   114
      ContextMenu contextMenu = new ContextMenu();
moel@181
   115
      MenuItem hardwareNamesItem = new MenuItem("Hardware Names");
moel@181
   116
      contextMenu.MenuItems.Add(hardwareNamesItem);
moel@183
   117
      MenuItem fontSizeMenu = new MenuItem("Font Size");
moel@183
   118
      for (int i = 0; i < 4; i++) {
moel@183
   119
        float size;
moel@183
   120
        string name;
moel@183
   121
        switch (i) {
moel@183
   122
          case 0: size = 6.5f; name = "Small"; break;
moel@183
   123
          case 1: size = 7.5f; name = "Medium"; break;
moel@183
   124
          case 2: size = 9f; name = "Large"; break;
moel@183
   125
          case 3: size = 11f; name = "Very Large"; break;
moel@183
   126
          default: throw new NotImplementedException();
moel@183
   127
        }
moel@183
   128
        MenuItem item = new MenuItem(name);
moel@183
   129
        item.Checked = fontSize == size;
moel@183
   130
        item.Click += delegate(object sender, EventArgs e) {
moel@183
   131
          SetFontSize(size);
moel@183
   132
          settings.SetValue("sensorGadget.FontSize", size);
moel@183
   133
          foreach (MenuItem mi in fontSizeMenu.MenuItems)
moel@183
   134
            mi.Checked = mi == item;
moel@183
   135
        };
moel@183
   136
        fontSizeMenu.MenuItems.Add(item);
moel@183
   137
      }
moel@183
   138
      contextMenu.MenuItems.Add(fontSizeMenu);
moel@181
   139
      contextMenu.MenuItems.Add(new MenuItem("-"));
moel@183
   140
      MenuItem lockItem = new MenuItem("Lock Position and Size");
moel@176
   141
      contextMenu.MenuItems.Add(lockItem);
moel@176
   142
      contextMenu.MenuItems.Add(new MenuItem("-"));
moel@176
   143
      MenuItem alwaysOnTopItem = new MenuItem("Always on Top");
moel@176
   144
      contextMenu.MenuItems.Add(alwaysOnTopItem);
moel@176
   145
      MenuItem opacityMenu = new MenuItem("Opacity");
moel@176
   146
      contextMenu.MenuItems.Add(opacityMenu);
moel@176
   147
      Opacity = (byte)settings.GetValue("sensorGadget.Opacity", 255);      
moel@176
   148
      for (int i = 0; i < 5; i++) {
moel@176
   149
        MenuItem item = new MenuItem((20 * (i + 1)).ToString() + " %");
moel@176
   150
        byte o = (byte)(51 * (i + 1));
moel@176
   151
        item.Checked = Opacity == o;
moel@176
   152
        item.Click += delegate(object sender, EventArgs e) {
moel@178
   153
          Opacity = o;
moel@176
   154
          settings.SetValue("sensorGadget.Opacity", Opacity);
moel@176
   155
          foreach (MenuItem mi in opacityMenu.MenuItems)
moel@178
   156
            mi.Checked = mi == item;          
moel@176
   157
        };
moel@176
   158
        opacityMenu.MenuItems.Add(item);
moel@176
   159
      }
moel@176
   160
      this.ContextMenu = contextMenu;
moel@176
   161
moel@181
   162
      hardwareNames = new UserOption("sensorGadget.Hardwarenames", true,
moel@181
   163
        hardwareNamesItem, settings);
moel@181
   164
      hardwareNames.Changed += delegate(object sender, EventArgs e) {
moel@181
   165
        Resize();
moel@181
   166
      };
moel@181
   167
moel@176
   168
      alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false, 
moel@176
   169
        alwaysOnTopItem, settings);
moel@176
   170
      alwaysOnTop.Changed += delegate(object sender, EventArgs e) {
moel@176
   171
        this.AlwaysOnTop = alwaysOnTop.Value;
moel@176
   172
      };
moel@183
   173
      lockPositionAndSize = new UserOption("sensorGadget.LockPositionAndSize", 
moel@183
   174
        false, lockItem, settings);
moel@183
   175
      lockPositionAndSize.Changed += delegate(object sender, EventArgs e) {
moel@183
   176
        this.LockPositionAndSize = lockPositionAndSize.Value;
moel@176
   177
      };
moel@176
   178
moel@183
   179
      HitTest += delegate(object sender, HitTestEventArgs e) {
moel@183
   180
        if (lockPositionAndSize.Value)
moel@183
   181
          return;
moel@183
   182
moel@183
   183
        if (e.Location.X < leftBorder) {
moel@183
   184
          e.HitResult = HitResult.Left;
moel@183
   185
          return;
moel@183
   186
        }
moel@183
   187
        if (e.Location.X > Size.Width - 1 - rightBorder) {
moel@183
   188
          e.HitResult = HitResult.Right;
moel@183
   189
          return;
moel@183
   190
        }
moel@183
   191
      };
moel@183
   192
moel@183
   193
      SizeChanged += delegate(object sender, EventArgs e) {
moel@183
   194
        settings.SetValue("sensorGadget.Width", Size.Width);
moel@183
   195
        Redraw();
moel@183
   196
      };
moel@176
   197
    }
moel@176
   198
moel@181
   199
    public override void Dispose() {
moel@181
   200
moel@181
   201
      largeFont.Dispose();
moel@181
   202
      largeFont = null;
moel@181
   203
moel@181
   204
      smallFont.Dispose();
moel@181
   205
      smallFont = null;
moel@181
   206
moel@181
   207
      darkWhite.Dispose();
moel@181
   208
      darkWhite = null;
moel@181
   209
moel@183
   210
      stringFormat.Dispose();
moel@183
   211
      stringFormat = null;
moel@183
   212
moel@181
   213
      trimStringFormat.Dispose();
moel@181
   214
      trimStringFormat = null;
moel@181
   215
moel@181
   216
      alignRightStringFormat.Dispose();
moel@181
   217
      alignRightStringFormat = null;      
moel@181
   218
moel@181
   219
      base.Dispose();
moel@181
   220
    }
moel@181
   221
moel@176
   222
    private void HardwareRemoved(IHardware hardware) {
moel@176
   223
      hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
moel@176
   224
      hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved);
moel@176
   225
      foreach (ISensor sensor in hardware.Sensors)
moel@176
   226
        SensorRemoved(sensor);
moel@176
   227
      foreach (IHardware subHardware in hardware.SubHardware)
moel@176
   228
        HardwareRemoved(subHardware);
moel@176
   229
    }
moel@176
   230
moel@176
   231
    private void HardwareAdded(IHardware hardware) {
moel@176
   232
      foreach (ISensor sensor in hardware.Sensors)
moel@176
   233
        SensorAdded(sensor);
moel@176
   234
      hardware.SensorAdded += new SensorEventHandler(SensorAdded);
moel@176
   235
      hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
moel@176
   236
      foreach (IHardware subHardware in hardware.SubHardware)
moel@176
   237
        HardwareAdded(subHardware);
moel@176
   238
    }
moel@176
   239
moel@176
   240
    private void SensorAdded(ISensor sensor) {
moel@176
   241
      if (settings.GetValue(new Identifier(sensor.Identifier,
moel@176
   242
        "gadget").ToString(), false)) 
moel@176
   243
        Add(sensor);
moel@176
   244
    }
moel@176
   245
moel@176
   246
    private void SensorRemoved(ISensor sensor) {
moel@176
   247
      if (Contains(sensor))
moel@176
   248
        Remove(sensor, false);
moel@176
   249
    }
moel@176
   250
moel@176
   251
    public bool Contains(ISensor sensor) {
moel@176
   252
      foreach (IList<ISensor> list in sensors.Values)
moel@176
   253
        if (list.Contains(sensor))
moel@176
   254
          return true;
moel@176
   255
      return false;
moel@176
   256
    }
moel@176
   257
moel@176
   258
    public void Add(ISensor sensor) {
moel@176
   259
      if (Contains(sensor)) {
moel@176
   260
        return;
moel@176
   261
      } else {
moel@176
   262
        // get the right hardware
moel@176
   263
        IHardware hardware = sensor.Hardware;
moel@176
   264
        while (hardware.Parent != null)
moel@176
   265
          hardware = hardware.Parent;
moel@176
   266
moel@176
   267
        // get the sensor list associated with the hardware
moel@176
   268
        IList<ISensor> list;
moel@176
   269
        if (!sensors.TryGetValue(hardware, out list)) {
moel@176
   270
          list = new List<ISensor>();
moel@176
   271
          sensors.Add(hardware, list);
moel@176
   272
        }
moel@176
   273
moel@176
   274
        // insert the sensor at the right position
moel@176
   275
        int i = 0;
moel@176
   276
        while (i < list.Count && (list[i].SensorType < sensor.SensorType || 
moel@176
   277
          (list[i].SensorType == sensor.SensorType && 
moel@176
   278
           list[i].Index < sensor.Index))) i++;
moel@176
   279
        list.Insert(i, sensor);
moel@176
   280
moel@176
   281
        settings.SetValue(
moel@176
   282
          new Identifier(sensor.Identifier, "gadget").ToString(), true);
moel@176
   283
        
moel@176
   284
        Resize();
moel@176
   285
      }
moel@176
   286
    }
moel@176
   287
moel@176
   288
    public void Remove(ISensor sensor) {
moel@176
   289
      Remove(sensor, true);
moel@176
   290
    }
moel@176
   291
moel@176
   292
    private void Remove(ISensor sensor, bool deleteConfig) {
moel@176
   293
      if (deleteConfig) 
moel@176
   294
        settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString());
moel@176
   295
moel@176
   296
      foreach (KeyValuePair<IHardware, IList<ISensor>> keyValue in sensors)
moel@176
   297
        if (keyValue.Value.Contains(sensor)) {
moel@176
   298
          keyValue.Value.Remove(sensor);          
moel@176
   299
          if (keyValue.Value.Count == 0) {
moel@176
   300
            sensors.Remove(keyValue.Key);
moel@176
   301
            break;
moel@176
   302
          }
moel@176
   303
        }
moel@176
   304
      Resize();
moel@183
   305
    }
moel@183
   306
moel@183
   307
    private Font CreateFont(float size, FontStyle style) {
moel@183
   308
      return new Font(SystemFonts.MessageBoxFont.FontFamily, size,
moel@183
   309
        style);
moel@183
   310
    }
moel@183
   311
moel@183
   312
    private void SetFontSize(float size) {
moel@183
   313
      fontSize = size;
moel@183
   314
      largeFont = CreateFont(fontSize, FontStyle.Bold);
moel@183
   315
      smallFont = CreateFont(fontSize, FontStyle.Regular);
moel@183
   316
      iconSize = (int)Math.Round(1.5 * fontSize);
moel@183
   317
      hardwareLineHeight = (int)Math.Round(1.66 * fontSize);
moel@183
   318
      sensorLineHeight = (int)Math.Round(1.33 * fontSize);      
moel@183
   319
      leftMargin = leftBorder + (int)Math.Round(0.3 * fontSize);
moel@183
   320
      rightMargin = rightBorder + (int)Math.Round(0.3 * fontSize);
moel@183
   321
      topMargin = topBorder;
moel@183
   322
      bottomMargin = bottomBorder + (int)Math.Round(0.3 * fontSize);
moel@183
   323
      progressWidth = (int)Math.Round(5.3 * fontSize);
moel@183
   324
      Resize((int)Math.Round(17.3 * fontSize));
moel@176
   325
    }
moel@176
   326
moel@176
   327
    private void Resize() {
moel@183
   328
      Resize(this.Size.Width);
moel@183
   329
    }
moel@183
   330
moel@183
   331
    private void Resize(int width) {
moel@183
   332
      int y = topMargin;      
moel@176
   333
      foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
moel@181
   334
        if (hardwareNames.Value) {
moel@183
   335
          if (y > topMargin)
moel@183
   336
            y += hardwareLineHeight - sensorLineHeight;
moel@181
   337
          y += hardwareLineHeight;
moel@181
   338
        }
moel@176
   339
        y += pair.Value.Count * sensorLineHeight;
moel@176
   340
      }
moel@183
   341
      y += bottomMargin;
moel@186
   342
      y = Math.Max(y, topBorder + hardwareLineHeight + bottomBorder);
moel@183
   343
      this.Size = new Size(width, y);
moel@176
   344
    }
moel@176
   345
moel@176
   346
    private void DrawBackground(Graphics g) {
moel@176
   347
      int w = Size.Width;
moel@176
   348
      int h = Size.Height;
moel@176
   349
      int t = topBorder;
moel@176
   350
      int b = bottomBorder;
moel@176
   351
      int l = leftBorder;
moel@176
   352
      int r = rightBorder;
moel@176
   353
      GraphicsUnit u = GraphicsUnit.Pixel;
moel@176
   354
moel@176
   355
      g.DrawImage(back, new Rectangle(0, 0, l, t),
moel@176
   356
        new Rectangle(0, 0, l, t), u);
moel@176
   357
      g.DrawImage(back, new Rectangle(l, 0, w - l - r, t),
moel@176
   358
        new Rectangle(l, 0, back.Width - l - r, t), u);
moel@176
   359
      g.DrawImage(back, new Rectangle(w - r, 0, r, t),
moel@176
   360
        new Rectangle(back.Width - r, 0, r, t), u);
moel@176
   361
moel@176
   362
      g.DrawImage(back, new Rectangle(0, t, l, h - t - b),
moel@176
   363
        new Rectangle(0, t, l, back.Height - t - b), u);
moel@176
   364
      g.DrawImage(back, new Rectangle(l, t, w - l - r, h - t - b),
moel@176
   365
        new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u);
moel@176
   366
      g.DrawImage(back, new Rectangle(w - r, t, r, h - t - b),
moel@176
   367
        new Rectangle(back.Width - r, t, r, back.Height - t - b), u);
moel@176
   368
moel@176
   369
      g.DrawImage(back, new Rectangle(0, h - b, l, b),
moel@176
   370
        new Rectangle(0, back.Height - b, l, b), u);
moel@176
   371
      g.DrawImage(back, new Rectangle(l, h - b, w - l - r, b),
moel@176
   372
        new Rectangle(l, back.Height - b, back.Width - l - r, b), u);
moel@176
   373
      g.DrawImage(back, new Rectangle(w - r, h - b, r, b),
moel@176
   374
        new Rectangle(back.Width - r, back.Height - b, r, b), u);
moel@176
   375
    }
moel@176
   376
moel@176
   377
    private void DrawProgress(Graphics g, int x, int y, int width, int height,
moel@176
   378
      float progress) 
moel@176
   379
    {
moel@176
   380
      g.DrawImage(barBack, 
moel@176
   381
        new RectangleF(x + width * progress, y, width * (1 - progress), height), 
moel@176
   382
        new RectangleF(barBack.Width * progress, 0, 
moel@176
   383
          (1 - progress) * barBack.Width, barBack.Height), 
moel@176
   384
        GraphicsUnit.Pixel);
moel@176
   385
      g.DrawImage(barblue,
moel@176
   386
        new RectangleF(x, y, width * progress, height),
moel@176
   387
        new RectangleF(0, 0, progress * barblue.Width, barblue.Height),
moel@176
   388
        GraphicsUnit.Pixel);
moel@176
   389
    }
moel@176
   390
moel@176
   391
    protected override void OnPaint(PaintEventArgs e) {
moel@176
   392
      Graphics g = e.Graphics;
moel@176
   393
      int w = Size.Width;
moel@176
   394
moel@176
   395
      g.Clear(Color.Transparent);
moel@183
   396
      
moel@176
   397
      DrawBackground(g);
moel@176
   398
moel@176
   399
      int x;
moel@183
   400
      int y = topMargin;
moel@186
   401
moel@186
   402
      if (sensors.Count == 0) {
moel@186
   403
        x = leftBorder + 1;
moel@186
   404
        g.DrawString("Add a sensor ...", smallFont, Brushes.White,
moel@186
   405
          new Rectangle(x, y - 1, w - rightBorder - x, 0));
moel@186
   406
      }
moel@186
   407
moel@176
   408
      foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
moel@181
   409
        if (hardwareNames.Value) {
moel@183
   410
          if (y > topMargin)
moel@183
   411
            y += hardwareLineHeight - sensorLineHeight;
moel@181
   412
          x = leftBorder + 1;
moel@181
   413
          g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType),
moel@181
   414
            new Rectangle(x, y + 1, iconSize, iconSize));
moel@181
   415
          x += iconSize + 1;
moel@181
   416
          g.DrawString(pair.Key.Name, largeFont, Brushes.White,
moel@183
   417
            new Rectangle(x, y - 1, w - rightBorder - x, 0), 
moel@183
   418
            stringFormat);
moel@181
   419
          y += hardwareLineHeight;
moel@181
   420
        }
moel@176
   421
moel@176
   422
        foreach (ISensor sensor in pair.Value) {
moel@183
   423
          int remainingWidth;
moel@176
   424
moel@187
   425
moel@187
   426
          if ((sensor.SensorType != SensorType.Load &&
moel@187
   427
            sensor.SensorType != SensorType.Control) || !sensor.Value.HasValue) 
moel@176
   428
          {
moel@187
   429
            string formatted;
moel@187
   430
moel@187
   431
            if (sensor.Value.HasValue) {
moel@187
   432
              string format = "";
moel@187
   433
              switch (sensor.SensorType) {
moel@187
   434
                case SensorType.Voltage:
moel@187
   435
                  format = "{0:F2} V";
moel@187
   436
                  break;
moel@187
   437
                case SensorType.Clock:
moel@187
   438
                  format = "{0:F0} MHz";
moel@187
   439
                  break;
moel@187
   440
                case SensorType.Temperature:
moel@187
   441
                  format = "{0:F1} °C";
moel@187
   442
                  break;
moel@187
   443
                case SensorType.Fan:
moel@187
   444
                  format = "{0:F0} RPM";
moel@187
   445
                  break;
moel@187
   446
                case SensorType.Flow:
moel@187
   447
                  format = "{0:F0} L/h";
moel@187
   448
                  break;
moel@187
   449
              }
moel@187
   450
moel@187
   451
              if (sensor.SensorType == SensorType.Temperature &&
moel@187
   452
                unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) {
moel@187
   453
                formatted = string.Format("{0:F1} °F",
moel@187
   454
                  sensor.Value * 1.8 + 32);
moel@187
   455
              } else {
moel@187
   456
                formatted = string.Format(format, sensor.Value);
moel@187
   457
              }
moel@187
   458
            } else {
moel@187
   459
              formatted = "-";
moel@176
   460
            }
moel@176
   461
moel@187
   462
            g.DrawString(formatted, smallFont, darkWhite,
moel@187
   463
              new RectangleF(-1, y - 1, w - rightMargin + 3, 0),
moel@181
   464
              alignRightStringFormat);
moel@181
   465
moel@187
   466
            remainingWidth = w - (int)Math.Floor(g.MeasureString(formatted,
moel@187
   467
              smallFont, w, StringFormat.GenericTypographic).Width) -
moel@181
   468
              rightMargin;
moel@187
   469
          } else {
moel@187
   470
            DrawProgress(g, w - progressWidth - rightMargin,
moel@183
   471
              y + 4, progressWidth, 6, 0.01f * sensor.Value.Value);
moel@183
   472
moel@183
   473
            remainingWidth = w - progressWidth - rightMargin;
moel@176
   474
          }
moel@187
   475
           
moel@183
   476
          remainingWidth -= leftMargin + 2;
moel@183
   477
          if (remainingWidth > 0) {
moel@183
   478
            g.DrawString(sensor.Name, smallFont, darkWhite,
moel@183
   479
              new RectangleF(leftMargin - 1, y - 1, remainingWidth, 0), 
moel@183
   480
              trimStringFormat);
moel@183
   481
          }
moel@181
   482
moel@176
   483
          y += sensorLineHeight;
moel@176
   484
        }
moel@176
   485
      }
moel@176
   486
    }
moel@176
   487
moel@176
   488
    private class HardwareComparer : IComparer<IHardware> {
moel@176
   489
      public int Compare(IHardware x, IHardware y) {
moel@176
   490
        if (x == null && y == null)
moel@176
   491
          return 0;
moel@176
   492
        if (x == null)
moel@176
   493
          return -1;
moel@176
   494
        if (y == null)
moel@176
   495
          return 1;
moel@176
   496
moel@176
   497
        if (x.HardwareType != y.HardwareType)
moel@176
   498
          return x.HardwareType.CompareTo(y.HardwareType);
moel@176
   499
moel@184
   500
        return x.Identifier.CompareTo(y.Identifier);
moel@176
   501
      }
moel@176
   502
    }
moel@176
   503
  }
moel@176
   504
}
moel@176
   505