GUI/SensorGadget.cs
author moel.mich
Wed, 22 Feb 2012 23:36:26 +0000
changeset 343 46b6b567f14f
parent 340 600962f8a298
child 344 3145aadca3d2
permissions -rw-r--r--
Fixed a division by zero in the Sandforce write amplification sensor.
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@340
    19
  Portions created by the Initial Developer are Copyright (C) 2010-2012
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@316
    41
using System.Drawing.Imaging;
moel@176
    42
using System.Windows.Forms;
moel@342
    43
using System.IO;
moel@176
    44
using OpenHardwareMonitor.Hardware;
moel@176
    45
moel@176
    46
namespace OpenHardwareMonitor.GUI {
moel@176
    47
  public class SensorGadget : Gadget {
moel@176
    48
moel@176
    49
    private UnitManager unitManager;
moel@176
    50
moel@176
    51
    private Image back = Utilities.EmbeddedResources.GetImage("gadget.png");
moel@342
    52
    private Image image = null;
moel@342
    53
    private Image fore = null;
moel@176
    54
    private Image barBack = Utilities.EmbeddedResources.GetImage("barback.png");
moel@342
    55
    private Image barFore = Utilities.EmbeddedResources.GetImage("barblue.png");
moel@183
    56
    private const int topBorder = 6;
moel@183
    57
    private const int bottomBorder = 7;
moel@176
    58
    private const int leftBorder = 6;
moel@183
    59
    private const int rightBorder = 7;
moel@316
    60
    private Image background = new Bitmap(1, 1);
moel@183
    61
moel@252
    62
    private readonly float scale;
moel@183
    63
    private float fontSize;
moel@183
    64
    private int iconSize;
moel@183
    65
    private int hardwareLineHeight;
moel@183
    66
    private int sensorLineHeight;
moel@183
    67
    private int rightMargin;
moel@183
    68
    private int leftMargin;
moel@183
    69
    private int topMargin;
moel@183
    70
    private int bottomMargin;
moel@183
    71
    private int progressWidth;
moel@176
    72
moel@176
    73
    private IDictionary<IHardware, IList<ISensor>> sensors =
moel@176
    74
      new SortedDictionary<IHardware, IList<ISensor>>(new HardwareComparer());
moel@176
    75
moel@176
    76
    private PersistentSettings settings;
moel@181
    77
    private UserOption hardwareNames;
moel@176
    78
    private UserOption alwaysOnTop;
moel@183
    79
    private UserOption lockPositionAndSize;
moel@176
    80
moel@176
    81
    private Font largeFont;
moel@176
    82
    private Font smallFont;
moel@181
    83
    private Brush darkWhite;
moel@183
    84
    private StringFormat stringFormat;
moel@181
    85
    private StringFormat trimStringFormat;
moel@181
    86
    private StringFormat alignRightStringFormat;
moel@176
    87
moel@176
    88
    public SensorGadget(IComputer computer, PersistentSettings settings, 
moel@176
    89
      UnitManager unitManager) 
moel@176
    90
    {
moel@176
    91
      this.unitManager = unitManager;
moel@176
    92
      this.settings = settings;
moel@176
    93
      computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
moel@183
    94
      computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);      
moel@176
    95
moel@181
    96
      this.darkWhite = new SolidBrush(Color.FromArgb(0xF0, 0xF0, 0xF0));
moel@181
    97
moel@183
    98
      this.stringFormat = new StringFormat();
moel@183
    99
      this.stringFormat.FormatFlags = StringFormatFlags.NoWrap;
moel@183
   100
moel@181
   101
      this.trimStringFormat = new StringFormat();
moel@181
   102
      this.trimStringFormat.Trimming = StringTrimming.EllipsisCharacter;
moel@183
   103
      this.trimStringFormat.FormatFlags = StringFormatFlags.NoWrap;
moel@181
   104
moel@181
   105
      this.alignRightStringFormat = new StringFormat();
moel@181
   106
      this.alignRightStringFormat.Alignment = StringAlignment.Far;
moel@183
   107
      this.alignRightStringFormat.FormatFlags = StringFormatFlags.NoWrap;
moel@176
   108
moel@342
   109
      if (File.Exists("gadget_background.png")) {
moel@342
   110
        try { 
moel@342
   111
          Image newBack = new Bitmap("gadget_background.png");
moel@342
   112
          back.Dispose();
moel@342
   113
          back = newBack;
moel@342
   114
        } catch { }
moel@342
   115
      }
moel@342
   116
moel@342
   117
      if (File.Exists("gadget_image.png")) {
moel@342
   118
        try {
moel@342
   119
          image = new Bitmap("gadget_image.png"); 
moel@342
   120
        } catch {}
moel@342
   121
      }
moel@342
   122
moel@342
   123
      if (File.Exists("gadget_foreground.png")) {
moel@342
   124
        try {
moel@342
   125
          fore = new Bitmap("gadget_foreground.png"); 
moel@342
   126
        } catch { }
moel@342
   127
      }
moel@342
   128
moel@342
   129
      if (File.Exists("gadget_bar_background.png")) {
moel@342
   130
        try {
moel@342
   131
          Image newBarBack = new Bitmap("gadget_bar_background.png");
moel@342
   132
          barBack.Dispose();
moel@342
   133
          barBack = newBarBack;
moel@342
   134
        } catch { }
moel@342
   135
      }
moel@342
   136
moel@342
   137
      if (File.Exists("gadget_bar_foreground.png")) {
moel@342
   138
        try {
moel@342
   139
          Image newBarColor = new Bitmap("gadget_bar_foreground.png");
moel@342
   140
          barFore.Dispose();
moel@342
   141
          barFore = newBarColor;
moel@342
   142
        } catch { }
moel@342
   143
      }
moel@342
   144
moel@176
   145
      this.Location = new Point(
moel@176
   146
        settings.GetValue("sensorGadget.Location.X", 100),
moel@176
   147
        settings.GetValue("sensorGadget.Location.Y", 100)); 
moel@176
   148
      LocationChanged += delegate(object sender, EventArgs e) {
moel@176
   149
        settings.SetValue("sensorGadget.Location.X", Location.X);
moel@176
   150
        settings.SetValue("sensorGadget.Location.Y", Location.Y);
moel@176
   151
      };
moel@183
   152
moel@252
   153
      // get the custom to default dpi ratio
moel@252
   154
      using (Bitmap b = new Bitmap(1, 1)) {
moel@252
   155
        scale = b.HorizontalResolution / 96.0f;
moel@252
   156
      }
moel@252
   157
moel@183
   158
      SetFontSize(settings.GetValue("sensorGadget.FontSize", 7.5f));
moel@183
   159
      Resize(settings.GetValue("sensorGadget.Width", Size.Width));
moel@176
   160
      
moel@176
   161
      ContextMenu contextMenu = new ContextMenu();
moel@181
   162
      MenuItem hardwareNamesItem = new MenuItem("Hardware Names");
moel@181
   163
      contextMenu.MenuItems.Add(hardwareNamesItem);
moel@183
   164
      MenuItem fontSizeMenu = new MenuItem("Font Size");
moel@183
   165
      for (int i = 0; i < 4; i++) {
moel@183
   166
        float size;
moel@183
   167
        string name;
moel@183
   168
        switch (i) {
moel@183
   169
          case 0: size = 6.5f; name = "Small"; break;
moel@183
   170
          case 1: size = 7.5f; name = "Medium"; break;
moel@183
   171
          case 2: size = 9f; name = "Large"; break;
moel@183
   172
          case 3: size = 11f; name = "Very Large"; break;
moel@183
   173
          default: throw new NotImplementedException();
moel@183
   174
        }
moel@183
   175
        MenuItem item = new MenuItem(name);
moel@183
   176
        item.Checked = fontSize == size;
moel@183
   177
        item.Click += delegate(object sender, EventArgs e) {
moel@183
   178
          SetFontSize(size);
moel@183
   179
          settings.SetValue("sensorGadget.FontSize", size);
moel@183
   180
          foreach (MenuItem mi in fontSizeMenu.MenuItems)
moel@183
   181
            mi.Checked = mi == item;
moel@183
   182
        };
moel@183
   183
        fontSizeMenu.MenuItems.Add(item);
moel@183
   184
      }
moel@183
   185
      contextMenu.MenuItems.Add(fontSizeMenu);
moel@181
   186
      contextMenu.MenuItems.Add(new MenuItem("-"));
moel@183
   187
      MenuItem lockItem = new MenuItem("Lock Position and Size");
moel@176
   188
      contextMenu.MenuItems.Add(lockItem);
moel@176
   189
      contextMenu.MenuItems.Add(new MenuItem("-"));
moel@176
   190
      MenuItem alwaysOnTopItem = new MenuItem("Always on Top");
moel@176
   191
      contextMenu.MenuItems.Add(alwaysOnTopItem);
moel@176
   192
      MenuItem opacityMenu = new MenuItem("Opacity");
moel@176
   193
      contextMenu.MenuItems.Add(opacityMenu);
moel@176
   194
      Opacity = (byte)settings.GetValue("sensorGadget.Opacity", 255);      
moel@176
   195
      for (int i = 0; i < 5; i++) {
moel@176
   196
        MenuItem item = new MenuItem((20 * (i + 1)).ToString() + " %");
moel@176
   197
        byte o = (byte)(51 * (i + 1));
moel@176
   198
        item.Checked = Opacity == o;
moel@176
   199
        item.Click += delegate(object sender, EventArgs e) {
moel@178
   200
          Opacity = o;
moel@176
   201
          settings.SetValue("sensorGadget.Opacity", Opacity);
moel@176
   202
          foreach (MenuItem mi in opacityMenu.MenuItems)
moel@178
   203
            mi.Checked = mi == item;          
moel@176
   204
        };
moel@176
   205
        opacityMenu.MenuItems.Add(item);
moel@176
   206
      }
moel@176
   207
      this.ContextMenu = contextMenu;
moel@176
   208
moel@181
   209
      hardwareNames = new UserOption("sensorGadget.Hardwarenames", true,
moel@181
   210
        hardwareNamesItem, settings);
moel@181
   211
      hardwareNames.Changed += delegate(object sender, EventArgs e) {
moel@181
   212
        Resize();
moel@181
   213
      };
moel@181
   214
moel@176
   215
      alwaysOnTop = new UserOption("sensorGadget.AlwaysOnTop", false, 
moel@176
   216
        alwaysOnTopItem, settings);
moel@176
   217
      alwaysOnTop.Changed += delegate(object sender, EventArgs e) {
moel@176
   218
        this.AlwaysOnTop = alwaysOnTop.Value;
moel@176
   219
      };
moel@183
   220
      lockPositionAndSize = new UserOption("sensorGadget.LockPositionAndSize", 
moel@183
   221
        false, lockItem, settings);
moel@183
   222
      lockPositionAndSize.Changed += delegate(object sender, EventArgs e) {
moel@183
   223
        this.LockPositionAndSize = lockPositionAndSize.Value;
moel@176
   224
      };
moel@176
   225
moel@183
   226
      HitTest += delegate(object sender, HitTestEventArgs e) {
moel@183
   227
        if (lockPositionAndSize.Value)
moel@183
   228
          return;
moel@183
   229
moel@183
   230
        if (e.Location.X < leftBorder) {
moel@183
   231
          e.HitResult = HitResult.Left;
moel@183
   232
          return;
moel@183
   233
        }
moel@183
   234
        if (e.Location.X > Size.Width - 1 - rightBorder) {
moel@183
   235
          e.HitResult = HitResult.Right;
moel@183
   236
          return;
moel@183
   237
        }
moel@183
   238
      };
moel@183
   239
moel@183
   240
      SizeChanged += delegate(object sender, EventArgs e) {
moel@183
   241
        settings.SetValue("sensorGadget.Width", Size.Width);
moel@183
   242
        Redraw();
moel@183
   243
      };
moel@244
   244
moel@289
   245
      VisibleChanged += delegate(object sender, EventArgs e) {
moel@289
   246
        Rectangle bounds = new Rectangle(Location, Size);
moel@289
   247
        Screen screen = Screen.FromRectangle(bounds);
moel@289
   248
        Rectangle intersection = 
moel@289
   249
          Rectangle.Intersect(screen.WorkingArea, bounds);
moel@289
   250
        if (intersection.Width < Math.Min(16, bounds.Width) || 
moel@289
   251
            intersection.Height < Math.Min(16, bounds.Height)) 
moel@289
   252
        {
moel@289
   253
          Location = new Point(
moel@289
   254
            screen.WorkingArea.Width / 2 - bounds.Width / 2, 
moel@289
   255
            screen.WorkingArea.Height / 2 - bounds.Height / 2);
moel@289
   256
        }
moel@289
   257
      };
moel@289
   258
moel@244
   259
      MouseDoubleClick += delegate(object obj, MouseEventArgs args) {
moel@244
   260
        SendHideShowCommand();
moel@244
   261
      };
moel@176
   262
    }
moel@176
   263
moel@181
   264
    public override void Dispose() {
moel@181
   265
moel@181
   266
      largeFont.Dispose();
moel@181
   267
      largeFont = null;
moel@181
   268
moel@181
   269
      smallFont.Dispose();
moel@181
   270
      smallFont = null;
moel@181
   271
moel@181
   272
      darkWhite.Dispose();
moel@181
   273
      darkWhite = null;
moel@181
   274
moel@183
   275
      stringFormat.Dispose();
moel@183
   276
      stringFormat = null;
moel@183
   277
moel@181
   278
      trimStringFormat.Dispose();
moel@181
   279
      trimStringFormat = null;
moel@181
   280
moel@181
   281
      alignRightStringFormat.Dispose();
moel@316
   282
      alignRightStringFormat = null;     
moel@316
   283
 
moel@316
   284
      back.Dispose();
moel@316
   285
      back = null;
moel@316
   286
moel@342
   287
      barFore.Dispose();
moel@342
   288
      barFore = null;
moel@316
   289
moel@316
   290
      barBack.Dispose();
moel@316
   291
      barBack = null;
moel@316
   292
moel@316
   293
      background.Dispose();
moel@316
   294
      background = null;
moel@181
   295
moel@342
   296
      if (image != null) {
moel@342
   297
        image.Dispose();
moel@342
   298
        image = null;
moel@342
   299
      }
moel@342
   300
moel@342
   301
      if (fore != null) {
moel@342
   302
        fore.Dispose();
moel@342
   303
        fore = null;
moel@342
   304
      }
moel@342
   305
moel@181
   306
      base.Dispose();
moel@181
   307
    }
moel@181
   308
moel@176
   309
    private void HardwareRemoved(IHardware hardware) {
moel@176
   310
      hardware.SensorAdded -= new SensorEventHandler(SensorAdded);
moel@176
   311
      hardware.SensorRemoved -= new SensorEventHandler(SensorRemoved);
moel@176
   312
      foreach (ISensor sensor in hardware.Sensors)
moel@176
   313
        SensorRemoved(sensor);
moel@176
   314
      foreach (IHardware subHardware in hardware.SubHardware)
moel@176
   315
        HardwareRemoved(subHardware);
moel@176
   316
    }
moel@176
   317
moel@176
   318
    private void HardwareAdded(IHardware hardware) {
moel@176
   319
      foreach (ISensor sensor in hardware.Sensors)
moel@176
   320
        SensorAdded(sensor);
moel@176
   321
      hardware.SensorAdded += new SensorEventHandler(SensorAdded);
moel@176
   322
      hardware.SensorRemoved += new SensorEventHandler(SensorRemoved);
moel@176
   323
      foreach (IHardware subHardware in hardware.SubHardware)
moel@176
   324
        HardwareAdded(subHardware);
moel@176
   325
    }
moel@176
   326
moel@176
   327
    private void SensorAdded(ISensor sensor) {
moel@176
   328
      if (settings.GetValue(new Identifier(sensor.Identifier,
moel@176
   329
        "gadget").ToString(), false)) 
moel@176
   330
        Add(sensor);
moel@176
   331
    }
moel@176
   332
moel@176
   333
    private void SensorRemoved(ISensor sensor) {
moel@176
   334
      if (Contains(sensor))
moel@176
   335
        Remove(sensor, false);
moel@176
   336
    }
moel@176
   337
moel@176
   338
    public bool Contains(ISensor sensor) {
moel@176
   339
      foreach (IList<ISensor> list in sensors.Values)
moel@176
   340
        if (list.Contains(sensor))
moel@176
   341
          return true;
moel@176
   342
      return false;
moel@176
   343
    }
moel@176
   344
moel@176
   345
    public void Add(ISensor sensor) {
moel@176
   346
      if (Contains(sensor)) {
moel@176
   347
        return;
moel@176
   348
      } else {
moel@176
   349
        // get the right hardware
moel@176
   350
        IHardware hardware = sensor.Hardware;
moel@176
   351
        while (hardware.Parent != null)
moel@176
   352
          hardware = hardware.Parent;
moel@176
   353
moel@176
   354
        // get the sensor list associated with the hardware
moel@176
   355
        IList<ISensor> list;
moel@176
   356
        if (!sensors.TryGetValue(hardware, out list)) {
moel@176
   357
          list = new List<ISensor>();
moel@176
   358
          sensors.Add(hardware, list);
moel@176
   359
        }
moel@176
   360
moel@176
   361
        // insert the sensor at the right position
moel@176
   362
        int i = 0;
moel@176
   363
        while (i < list.Count && (list[i].SensorType < sensor.SensorType || 
moel@176
   364
          (list[i].SensorType == sensor.SensorType && 
moel@176
   365
           list[i].Index < sensor.Index))) i++;
moel@176
   366
        list.Insert(i, sensor);
moel@176
   367
moel@176
   368
        settings.SetValue(
moel@176
   369
          new Identifier(sensor.Identifier, "gadget").ToString(), true);
moel@176
   370
        
moel@176
   371
        Resize();
moel@176
   372
      }
moel@176
   373
    }
moel@176
   374
moel@176
   375
    public void Remove(ISensor sensor) {
moel@176
   376
      Remove(sensor, true);
moel@176
   377
    }
moel@176
   378
moel@176
   379
    private void Remove(ISensor sensor, bool deleteConfig) {
moel@176
   380
      if (deleteConfig) 
moel@176
   381
        settings.Remove(new Identifier(sensor.Identifier, "gadget").ToString());
moel@176
   382
moel@176
   383
      foreach (KeyValuePair<IHardware, IList<ISensor>> keyValue in sensors)
moel@176
   384
        if (keyValue.Value.Contains(sensor)) {
moel@176
   385
          keyValue.Value.Remove(sensor);          
moel@176
   386
          if (keyValue.Value.Count == 0) {
moel@176
   387
            sensors.Remove(keyValue.Key);
moel@176
   388
            break;
moel@176
   389
          }
moel@176
   390
        }
moel@176
   391
      Resize();
moel@183
   392
    }
moel@183
   393
moel@244
   394
    public event EventHandler HideShowCommand;
moel@244
   395
moel@244
   396
    public void SendHideShowCommand() {
moel@244
   397
      if (HideShowCommand != null)
moel@244
   398
        HideShowCommand(this, null);
moel@244
   399
    }
moel@244
   400
moel@183
   401
    private Font CreateFont(float size, FontStyle style) {
moel@215
   402
      try {
moel@215
   403
        return new Font(SystemFonts.MessageBoxFont.FontFamily, size, style);
moel@215
   404
      } catch (ArgumentException) {
moel@215
   405
        // if the style is not supported, fall back to the original one
moel@215
   406
        return new Font(SystemFonts.MessageBoxFont.FontFamily, size, 
moel@215
   407
          SystemFonts.MessageBoxFont.Style);
moel@215
   408
      }
moel@183
   409
    }
moel@183
   410
moel@183
   411
    private void SetFontSize(float size) {
moel@183
   412
      fontSize = size;
moel@183
   413
      largeFont = CreateFont(fontSize, FontStyle.Bold);
moel@183
   414
      smallFont = CreateFont(fontSize, FontStyle.Regular);
moel@252
   415
      
moel@252
   416
      double scaledFontSize = fontSize * scale;
moel@252
   417
      iconSize = (int)Math.Round(1.5 * scaledFontSize);
moel@252
   418
      hardwareLineHeight = (int)Math.Round(1.66 * scaledFontSize);
moel@252
   419
      sensorLineHeight = (int)Math.Round(1.33 * scaledFontSize);
moel@252
   420
      leftMargin = leftBorder + (int)Math.Round(0.3 * scaledFontSize);
moel@252
   421
      rightMargin = rightBorder + (int)Math.Round(0.3 * scaledFontSize);
moel@183
   422
      topMargin = topBorder;
moel@252
   423
      bottomMargin = bottomBorder + (int)Math.Round(0.3 * scaledFontSize);
moel@252
   424
      progressWidth = (int)Math.Round(5.3 * scaledFontSize);
moel@252
   425
moel@252
   426
      Resize((int)Math.Round(17.3 * scaledFontSize));
moel@176
   427
    }
moel@176
   428
moel@176
   429
    private void Resize() {
moel@183
   430
      Resize(this.Size.Width);
moel@183
   431
    }
moel@183
   432
moel@183
   433
    private void Resize(int width) {
moel@183
   434
      int y = topMargin;      
moel@176
   435
      foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
moel@181
   436
        if (hardwareNames.Value) {
moel@183
   437
          if (y > topMargin)
moel@183
   438
            y += hardwareLineHeight - sensorLineHeight;
moel@181
   439
          y += hardwareLineHeight;
moel@181
   440
        }
moel@176
   441
        y += pair.Value.Count * sensorLineHeight;
moel@263
   442
      }      
moel@263
   443
      if (sensors.Count == 0)
moel@263
   444
        y += 4 * sensorLineHeight + hardwareLineHeight;
moel@183
   445
      y += bottomMargin;
moel@183
   446
      this.Size = new Size(width, y);
moel@176
   447
    }
moel@176
   448
moel@342
   449
    private void DrawImageWidthBorder(Graphics g, int width, int height, 
moel@342
   450
      Image back, int t, int b, int l, int r) 
moel@342
   451
    {
moel@342
   452
      GraphicsUnit u = GraphicsUnit.Pixel;
moel@342
   453
moel@342
   454
      g.DrawImage(back, new Rectangle(0, 0, l, t),
moel@342
   455
            new Rectangle(0, 0, l, t), u);
moel@342
   456
      g.DrawImage(back, new Rectangle(l, 0, width - l - r, t),
moel@342
   457
        new Rectangle(l, 0, back.Width - l - r, t), u);
moel@342
   458
      g.DrawImage(back, new Rectangle(width - r, 0, r, t),
moel@342
   459
        new Rectangle(back.Width - r, 0, r, t), u);
moel@342
   460
moel@342
   461
      g.DrawImage(back, new Rectangle(0, t, l, height - t - b),
moel@342
   462
        new Rectangle(0, t, l, back.Height - t - b), u);
moel@342
   463
      g.DrawImage(back, new Rectangle(l, t, width - l - r, height - t - b),
moel@342
   464
        new Rectangle(l, t, back.Width - l - r, back.Height - t - b), u);
moel@342
   465
      g.DrawImage(back, new Rectangle(width - r, t, r, height - t - b),
moel@342
   466
        new Rectangle(back.Width - r, t, r, back.Height - t - b), u);
moel@342
   467
moel@342
   468
      g.DrawImage(back, new Rectangle(0, height - b, l, b),
moel@342
   469
        new Rectangle(0, back.Height - b, l, b), u);
moel@342
   470
      g.DrawImage(back, new Rectangle(l, height - b, width - l - r, b),
moel@342
   471
        new Rectangle(l, back.Height - b, back.Width - l - r, b), u);
moel@342
   472
      g.DrawImage(back, new Rectangle(width - r, height - b, r, b),
moel@342
   473
        new Rectangle(back.Width - r, back.Height - b, r, b), u);
moel@342
   474
    }
moel@342
   475
moel@176
   476
    private void DrawBackground(Graphics g) {
moel@176
   477
      int w = Size.Width;
moel@316
   478
      int h = Size.Height;      
moel@176
   479
moel@316
   480
      if (w != background.Width || h != background.Height) {
moel@176
   481
moel@316
   482
        background.Dispose();
moel@316
   483
        background = new Bitmap(w, h, PixelFormat.Format32bppPArgb);
moel@316
   484
        using (Graphics graphics = Graphics.FromImage(background)) {
moel@176
   485
moel@342
   486
          DrawImageWidthBorder(graphics, w, h, back, topBorder, bottomBorder, 
moel@342
   487
            leftBorder, rightBorder);    
moel@342
   488
      
moel@342
   489
          if (fore != null)
moel@342
   490
            DrawImageWidthBorder(graphics, w, h, fore, topBorder, bottomBorder,
moel@342
   491
            leftBorder, rightBorder);
moel@316
   492
moel@342
   493
          if (image != null) {
moel@342
   494
            int width = w - leftBorder - rightBorder;
moel@342
   495
            int height = h - topBorder - bottomBorder;
moel@342
   496
            float xRatio = width / (float)image.Width;
moel@342
   497
            float yRatio = height / (float)image.Height;
moel@342
   498
            float destWidth, destHeight;
moel@342
   499
            float xOffset, yOffset;
moel@342
   500
            if (xRatio < yRatio) {
moel@342
   501
              destWidth = width;
moel@342
   502
              destHeight = image.Height * xRatio;
moel@342
   503
              xOffset = 0;
moel@342
   504
              yOffset = 0.5f * (height - destHeight);
moel@342
   505
            } else {
moel@342
   506
              destWidth = image.Width * yRatio;
moel@342
   507
              destHeight = height;
moel@342
   508
              xOffset = 0.5f * (width - destWidth);
moel@342
   509
              yOffset = 0;
moel@342
   510
            }
moel@316
   511
moel@342
   512
            graphics.DrawImage(image,
moel@342
   513
              new RectangleF(leftBorder + xOffset, topBorder + yOffset, 
moel@342
   514
                destWidth, destHeight));
moel@342
   515
          }
moel@316
   516
        }
moel@316
   517
      }
moel@316
   518
moel@316
   519
      g.DrawImageUnscaled(background, 0, 0);
moel@176
   520
    }
moel@176
   521
moel@243
   522
    private void DrawProgress(Graphics g, float x, float y, 
moel@243
   523
      float width, float height, float progress) 
moel@176
   524
    {
moel@176
   525
      g.DrawImage(barBack, 
moel@176
   526
        new RectangleF(x + width * progress, y, width * (1 - progress), height), 
moel@176
   527
        new RectangleF(barBack.Width * progress, 0, 
moel@176
   528
          (1 - progress) * barBack.Width, barBack.Height), 
moel@176
   529
        GraphicsUnit.Pixel);
moel@342
   530
      g.DrawImage(barFore,
moel@176
   531
        new RectangleF(x, y, width * progress, height),
moel@342
   532
        new RectangleF(0, 0, progress * barFore.Width, barFore.Height),
moel@176
   533
        GraphicsUnit.Pixel);
moel@176
   534
    }
moel@176
   535
moel@176
   536
    protected override void OnPaint(PaintEventArgs e) {
moel@176
   537
      Graphics g = e.Graphics;
moel@176
   538
      int w = Size.Width;
moel@176
   539
moel@176
   540
      g.Clear(Color.Transparent);
moel@183
   541
      
moel@176
   542
      DrawBackground(g);
moel@176
   543
moel@176
   544
      int x;
moel@183
   545
      int y = topMargin;
moel@186
   546
moel@186
   547
      if (sensors.Count == 0) {
moel@186
   548
        x = leftBorder + 1;
moel@263
   549
        g.DrawString("Right-click on a sensor in the main window and select " + 
moel@263
   550
          "\"Show in Gadget\" to show the sensor here.", 
moel@263
   551
          smallFont, Brushes.White,
moel@186
   552
          new Rectangle(x, y - 1, w - rightBorder - x, 0));
moel@186
   553
      }
moel@186
   554
moel@176
   555
      foreach (KeyValuePair<IHardware, IList<ISensor>> pair in sensors) {
moel@181
   556
        if (hardwareNames.Value) {
moel@183
   557
          if (y > topMargin)
moel@183
   558
            y += hardwareLineHeight - sensorLineHeight;
moel@181
   559
          x = leftBorder + 1;
moel@181
   560
          g.DrawImage(HardwareTypeImage.Instance.GetImage(pair.Key.HardwareType),
moel@181
   561
            new Rectangle(x, y + 1, iconSize, iconSize));
moel@181
   562
          x += iconSize + 1;
moel@181
   563
          g.DrawString(pair.Key.Name, largeFont, Brushes.White,
moel@183
   564
            new Rectangle(x, y - 1, w - rightBorder - x, 0), 
moel@183
   565
            stringFormat);
moel@181
   566
          y += hardwareLineHeight;
moel@181
   567
        }
moel@176
   568
moel@176
   569
        foreach (ISensor sensor in pair.Value) {
moel@183
   570
          int remainingWidth;
moel@176
   571
moel@187
   572
moel@187
   573
          if ((sensor.SensorType != SensorType.Load &&
moel@217
   574
               sensor.SensorType != SensorType.Control &&
moel@217
   575
               sensor.SensorType != SensorType.Level) || !sensor.Value.HasValue) 
moel@176
   576
          {
moel@187
   577
            string formatted;
moel@187
   578
moel@187
   579
            if (sensor.Value.HasValue) {
moel@187
   580
              string format = "";
moel@187
   581
              switch (sensor.SensorType) {
moel@187
   582
                case SensorType.Voltage:
moel@300
   583
                  format = "{0:F3} V";
moel@187
   584
                  break;
moel@187
   585
                case SensorType.Clock:
moel@187
   586
                  format = "{0:F0} MHz";
moel@187
   587
                  break;
moel@187
   588
                case SensorType.Temperature:
moel@187
   589
                  format = "{0:F1} °C";
moel@187
   590
                  break;
moel@187
   591
                case SensorType.Fan:
moel@187
   592
                  format = "{0:F0} RPM";
moel@187
   593
                  break;
moel@187
   594
                case SensorType.Flow:
moel@187
   595
                  format = "{0:F0} L/h";
moel@187
   596
                  break;
moel@318
   597
                case SensorType.Power:
moel@318
   598
                  format = "{0:F1} W";
moel@318
   599
                  break;
moel@324
   600
                case SensorType.Data:
moel@324
   601
                  format = "{0:F1} GB";
moel@324
   602
                  break;
moel@340
   603
                case SensorType.Factor:
moel@340
   604
                  format = "{0:F3}";
moel@340
   605
                  break;
moel@187
   606
              }
moel@187
   607
moel@187
   608
              if (sensor.SensorType == SensorType.Temperature &&
moel@187
   609
                unitManager.TemperatureUnit == TemperatureUnit.Fahrenheit) {
moel@187
   610
                formatted = string.Format("{0:F1} °F",
moel@187
   611
                  sensor.Value * 1.8 + 32);
moel@187
   612
              } else {
moel@187
   613
                formatted = string.Format(format, sensor.Value);
moel@187
   614
              }
moel@187
   615
            } else {
moel@187
   616
              formatted = "-";
moel@176
   617
            }
moel@176
   618
moel@187
   619
            g.DrawString(formatted, smallFont, darkWhite,
moel@187
   620
              new RectangleF(-1, y - 1, w - rightMargin + 3, 0),
moel@181
   621
              alignRightStringFormat);
moel@181
   622
moel@187
   623
            remainingWidth = w - (int)Math.Floor(g.MeasureString(formatted,
moel@187
   624
              smallFont, w, StringFormat.GenericTypographic).Width) -
moel@181
   625
              rightMargin;
moel@187
   626
          } else {
moel@187
   627
            DrawProgress(g, w - progressWidth - rightMargin,
moel@243
   628
              y + 0.35f * sensorLineHeight, progressWidth,
moel@243
   629
              0.6f * sensorLineHeight, 0.01f * sensor.Value.Value);
moel@183
   630
moel@183
   631
            remainingWidth = w - progressWidth - rightMargin;
moel@176
   632
          }
moel@187
   633
           
moel@183
   634
          remainingWidth -= leftMargin + 2;
moel@183
   635
          if (remainingWidth > 0) {
moel@183
   636
            g.DrawString(sensor.Name, smallFont, darkWhite,
moel@183
   637
              new RectangleF(leftMargin - 1, y - 1, remainingWidth, 0), 
moel@183
   638
              trimStringFormat);
moel@183
   639
          }
moel@181
   640
moel@176
   641
          y += sensorLineHeight;
moel@176
   642
        }
moel@176
   643
      }
moel@176
   644
    }
moel@176
   645
moel@176
   646
    private class HardwareComparer : IComparer<IHardware> {
moel@176
   647
      public int Compare(IHardware x, IHardware y) {
moel@176
   648
        if (x == null && y == null)
moel@176
   649
          return 0;
moel@176
   650
        if (x == null)
moel@176
   651
          return -1;
moel@176
   652
        if (y == null)
moel@176
   653
          return 1;
moel@176
   654
moel@176
   655
        if (x.HardwareType != y.HardwareType)
moel@176
   656
          return x.HardwareType.CompareTo(y.HardwareType);
moel@176
   657
moel@184
   658
        return x.Identifier.CompareTo(y.Identifier);
moel@176
   659
      }
moel@176
   660
    }
moel@176
   661
  }
moel@176
   662
}
moel@176
   663