GUI/SensorGadget.cs
author moel.mich
Thu, 11 Nov 2010 21:22:24 +0000
changeset 241 52007c404f32
parent 215 79e9a77f6a71
child 243 07a9329cd87c
permissions -rw-r--r--
Fixed a problem, where the MainForm location and size was lost when the application is started minimized and exited without ever showing the form. This caused MainForm_Load to be never called (location and size was not loaded), but the default size and location were still saved. The new implementation only saves the location and size when one of the two is changed.
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@215
   308
      try {
moel@215
   309
        return new Font(SystemFonts.MessageBoxFont.FontFamily, size, style);
moel@215
   310
      } catch (ArgumentException) {
moel@215
   311
        // if the style is not supported, fall back to the original one
moel@215
   312
        return new Font(SystemFonts.MessageBoxFont.FontFamily, size, 
moel@215
   313
          SystemFonts.MessageBoxFont.Style);
moel@215
   314
      }
moel@183
   315
    }
moel@183
   316
moel@183
   317
    private void SetFontSize(float size) {
moel@183
   318
      fontSize = size;
moel@183
   319
      largeFont = CreateFont(fontSize, FontStyle.Bold);
moel@183
   320
      smallFont = CreateFont(fontSize, FontStyle.Regular);
moel@183
   321
      iconSize = (int)Math.Round(1.5 * fontSize);
moel@183
   322
      hardwareLineHeight = (int)Math.Round(1.66 * fontSize);
moel@183
   323
      sensorLineHeight = (int)Math.Round(1.33 * fontSize);      
moel@183
   324
      leftMargin = leftBorder + (int)Math.Round(0.3 * fontSize);
moel@183
   325
      rightMargin = rightBorder + (int)Math.Round(0.3 * fontSize);
moel@183
   326
      topMargin = topBorder;
moel@183
   327
      bottomMargin = bottomBorder + (int)Math.Round(0.3 * fontSize);
moel@183
   328
      progressWidth = (int)Math.Round(5.3 * fontSize);
moel@183
   329
      Resize((int)Math.Round(17.3 * fontSize));
moel@176
   330
    }
moel@176
   331
moel@176
   332
    private void Resize() {
moel@183
   333
      Resize(this.Size.Width);
moel@183
   334
    }
moel@183
   335
moel@183
   336
    private void Resize(int width) {
moel@183
   337
      int y = topMargin;      
moel@176
   338
      foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
moel@181
   339
        if (hardwareNames.Value) {
moel@183
   340
          if (y > topMargin)
moel@183
   341
            y += hardwareLineHeight - sensorLineHeight;
moel@181
   342
          y += hardwareLineHeight;
moel@181
   343
        }
moel@176
   344
        y += pair.Value.Count * sensorLineHeight;
moel@176
   345
      }
moel@183
   346
      y += bottomMargin;
moel@186
   347
      y = Math.Max(y, topBorder + hardwareLineHeight + bottomBorder);
moel@183
   348
      this.Size = new Size(width, y);
moel@176
   349
    }
moel@176
   350
moel@176
   351
    private void DrawBackground(Graphics g) {
moel@176
   352
      int w = Size.Width;
moel@176
   353
      int h = Size.Height;
moel@176
   354
      int t = topBorder;
moel@176
   355
      int b = bottomBorder;
moel@176
   356
      int l = leftBorder;
moel@176
   357
      int r = rightBorder;
moel@176
   358
      GraphicsUnit u = GraphicsUnit.Pixel;
moel@176
   359
moel@176
   360
      g.DrawImage(back, new Rectangle(0, 0, l, t),
moel@176
   361
        new Rectangle(0, 0, l, t), u);
moel@176
   362
      g.DrawImage(back, new Rectangle(l, 0, w - l - r, t),
moel@176
   363
        new Rectangle(l, 0, back.Width - l - r, t), u);
moel@176
   364
      g.DrawImage(back, new Rectangle(w - r, 0, r, t),
moel@176
   365
        new Rectangle(back.Width - r, 0, r, t), u);
moel@176
   366
moel@176
   367
      g.DrawImage(back, new Rectangle(0, t, l, h - t - b),
moel@176
   368
        new Rectangle(0, t, l, back.Height - t - b), u);
moel@176
   369
      g.DrawImage(back, new Rectangle(l, t, w - l - r, h - t - b),
moel@176
   370
        new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u);
moel@176
   371
      g.DrawImage(back, new Rectangle(w - r, t, r, h - t - b),
moel@176
   372
        new Rectangle(back.Width - r, t, r, back.Height - t - b), u);
moel@176
   373
moel@176
   374
      g.DrawImage(back, new Rectangle(0, h - b, l, b),
moel@176
   375
        new Rectangle(0, back.Height - b, l, b), u);
moel@176
   376
      g.DrawImage(back, new Rectangle(l, h - b, w - l - r, b),
moel@176
   377
        new Rectangle(l, back.Height - b, back.Width - l - r, b), u);
moel@176
   378
      g.DrawImage(back, new Rectangle(w - r, h - b, r, b),
moel@176
   379
        new Rectangle(back.Width - r, back.Height - b, r, b), u);
moel@176
   380
    }
moel@176
   381
moel@176
   382
    private void DrawProgress(Graphics g, int x, int y, int width, int height,
moel@176
   383
      float progress) 
moel@176
   384
    {
moel@176
   385
      g.DrawImage(barBack, 
moel@176
   386
        new RectangleF(x + width * progress, y, width * (1 - progress), height), 
moel@176
   387
        new RectangleF(barBack.Width * progress, 0, 
moel@176
   388
          (1 - progress) * barBack.Width, barBack.Height), 
moel@176
   389
        GraphicsUnit.Pixel);
moel@176
   390
      g.DrawImage(barblue,
moel@176
   391
        new RectangleF(x, y, width * progress, height),
moel@176
   392
        new RectangleF(0, 0, progress * barblue.Width, barblue.Height),
moel@176
   393
        GraphicsUnit.Pixel);
moel@176
   394
    }
moel@176
   395
moel@176
   396
    protected override void OnPaint(PaintEventArgs e) {
moel@176
   397
      Graphics g = e.Graphics;
moel@176
   398
      int w = Size.Width;
moel@176
   399
moel@176
   400
      g.Clear(Color.Transparent);
moel@183
   401
      
moel@176
   402
      DrawBackground(g);
moel@176
   403
moel@176
   404
      int x;
moel@183
   405
      int y = topMargin;
moel@186
   406
moel@186
   407
      if (sensors.Count == 0) {
moel@186
   408
        x = leftBorder + 1;
moel@186
   409
        g.DrawString("Add a sensor ...", smallFont, Brushes.White,
moel@186
   410
          new Rectangle(x, y - 1, w - rightBorder - x, 0));
moel@186
   411
      }
moel@186
   412
moel@176
   413
      foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
moel@181
   414
        if (hardwareNames.Value) {
moel@183
   415
          if (y > topMargin)
moel@183
   416
            y += hardwareLineHeight - sensorLineHeight;
moel@181
   417
          x = leftBorder + 1;
moel@181
   418
          g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType),
moel@181
   419
            new Rectangle(x, y + 1, iconSize, iconSize));
moel@181
   420
          x += iconSize + 1;
moel@181
   421
          g.DrawString(pair.Key.Name, largeFont, Brushes.White,
moel@183
   422
            new Rectangle(x, y - 1, w - rightBorder - x, 0), 
moel@183
   423
            stringFormat);
moel@181
   424
          y += hardwareLineHeight;
moel@181
   425
        }
moel@176
   426
moel@176
   427
        foreach (ISensor sensor in pair.Value) {
moel@183
   428
          int remainingWidth;
moel@176
   429
moel@187
   430
moel@187
   431
          if ((sensor.SensorType != SensorType.Load &&
moel@217
   432
               sensor.SensorType != SensorType.Control &&
moel@217
   433
               sensor.SensorType != SensorType.Level) || !sensor.Value.HasValue) 
moel@176
   434
          {
moel@187
   435
            string formatted;
moel@187
   436
moel@187
   437
            if (sensor.Value.HasValue) {
moel@187
   438
              string format = "";
moel@187
   439
              switch (sensor.SensorType) {
moel@187
   440
                case SensorType.Voltage:
moel@187
   441
                  format = "{0:F2} V";
moel@187
   442
                  break;
moel@187
   443
                case SensorType.Clock:
moel@187
   444
                  format = "{0:F0} MHz";
moel@187
   445
                  break;
moel@187
   446
                case SensorType.Temperature:
moel@187
   447
                  format = "{0:F1} °C";
moel@187
   448
                  break;
moel@187
   449
                case SensorType.Fan:
moel@187
   450
                  format = "{0:F0} RPM";
moel@187
   451
                  break;
moel@187
   452
                case SensorType.Flow:
moel@187
   453
                  format = "{0:F0} L/h";
moel@187
   454
                  break;
moel@187
   455
              }
moel@187
   456
moel@187
   457
              if (sensor.SensorType == SensorType.Temperature &&
moel@187
   458
                unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) {
moel@187
   459
                formatted = string.Format("{0:F1} °F",
moel@187
   460
                  sensor.Value * 1.8 + 32);
moel@187
   461
              } else {
moel@187
   462
                formatted = string.Format(format, sensor.Value);
moel@187
   463
              }
moel@187
   464
            } else {
moel@187
   465
              formatted = "-";
moel@176
   466
            }
moel@176
   467
moel@187
   468
            g.DrawString(formatted, smallFont, darkWhite,
moel@187
   469
              new RectangleF(-1, y - 1, w - rightMargin + 3, 0),
moel@181
   470
              alignRightStringFormat);
moel@181
   471
moel@187
   472
            remainingWidth = w - (int)Math.Floor(g.MeasureString(formatted,
moel@187
   473
              smallFont, w, StringFormat.GenericTypographic).Width) -
moel@181
   474
              rightMargin;
moel@187
   475
          } else {
moel@187
   476
            DrawProgress(g, w - progressWidth - rightMargin,
moel@183
   477
              y + 4, progressWidth, 6, 0.01f * sensor.Value.Value);
moel@183
   478
moel@183
   479
            remainingWidth = w - progressWidth - rightMargin;
moel@176
   480
          }
moel@187
   481
           
moel@183
   482
          remainingWidth -= leftMargin + 2;
moel@183
   483
          if (remainingWidth > 0) {
moel@183
   484
            g.DrawString(sensor.Name, smallFont, darkWhite,
moel@183
   485
              new RectangleF(leftMargin - 1, y - 1, remainingWidth, 0), 
moel@183
   486
              trimStringFormat);
moel@183
   487
          }
moel@181
   488
moel@176
   489
          y += sensorLineHeight;
moel@176
   490
        }
moel@176
   491
      }
moel@176
   492
    }
moel@176
   493
moel@176
   494
    private class HardwareComparer : IComparer<IHardware> {
moel@176
   495
      public int Compare(IHardware x, IHardware y) {
moel@176
   496
        if (x == null && y == null)
moel@176
   497
          return 0;
moel@176
   498
        if (x == null)
moel@176
   499
          return -1;
moel@176
   500
        if (y == null)
moel@176
   501
          return 1;
moel@176
   502
moel@176
   503
        if (x.HardwareType != y.HardwareType)
moel@176
   504
          return x.HardwareType.CompareTo(y.HardwareType);
moel@176
   505
moel@184
   506
        return x.Identifier.CompareTo(y.Identifier);
moel@176
   507
      }
moel@176
   508
    }
moel@176
   509
  }
moel@176
   510
}
moel@176
   511