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