GUI/SensorGadget.cs
author StephaneLenclud
Sun, 03 Feb 2013 18:01:50 +0100
branchMiniDisplay
changeset 433 090259cfd699
parent 344 3145aadca3d2
permissions -rw-r--r--
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
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@362
   584
                  UnitManager.CelsiusToFahrenheit(sensor.Value));
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