GUI/MainForm.cs
author moel.mich
Sat, 31 Dec 2011 17:31:04 +0000
changeset 324 c6ee430d6995
parent 299 072989c22a87
child 326 a41745e3828d
permissions -rw-r--r--
Modified and extended version of the patch v4 by Roland Reinl (see Issue 256). Main differences to the original patch: DeviceIoControl refactorings removed, SmartAttribute is now descriptive only and does not hold any state, report is written as one 80 columns table, sensors are created only for meaningful values and without duplicates (remaining life, temperatures, host writes and reads). Also the current implementation should really preserve all the functionality of the old system. Additionally there is now a simple SMART devices emulation class (DebugSmart) that can be used in place of WindowsSmart for testing with reported data.
moel@1
     1
/*
moel@1
     2
  
moel@1
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1
     4
moel@1
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@1
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@1
     7
  the License. You may obtain a copy of the License at
moel@1
     8
 
moel@1
     9
  http://www.mozilla.org/MPL/
moel@1
    10
moel@1
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@1
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1
    13
  for the specific language governing rights and limitations under the License.
moel@1
    14
moel@1
    15
  The Original Code is the Open Hardware Monitor code.
moel@1
    16
moel@1
    17
  The Initial Developer of the Original Code is 
moel@1
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@275
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2011
moel@1
    20
  the Initial Developer. All Rights Reserved.
moel@1
    21
paulwerelds@223
    22
  Contributor(s): Paul Werelds
moel@1
    23
moel@1
    24
  Alternatively, the contents of this file may be used under the terms of
moel@1
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@1
    28
  of those above. If you wish to allow use of your version of this file only
moel@1
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@1
    30
  use your version of this file under the terms of the MPL, indicate your
moel@1
    31
  decision by deleting the provisions above and replace them with the notice
moel@1
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@1
    33
  the provisions above, a recipient may use your version of this file under
moel@1
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@1
    35
 
moel@1
    36
*/
moel@1
    37
moel@1
    38
using System;
moel@1
    39
using System.Collections.Generic;
moel@1
    40
using System.ComponentModel;
moel@1
    41
using System.Drawing;
moel@83
    42
using System.IO;
moel@291
    43
using System.Reflection;
moel@1
    44
using System.Windows.Forms;
moel@1
    45
using Aga.Controls.Tree;
moel@1
    46
using Aga.Controls.Tree.NodeControls;
moel@1
    47
using OpenHardwareMonitor.Hardware;
paulwerelds@227
    48
using OpenHardwareMonitor.WMI;
moel@1
    49
moel@1
    50
namespace OpenHardwareMonitor.GUI {
moel@1
    51
  public partial class MainForm : Form {
moel@1
    52
moel@165
    53
    private PersistentSettings settings;
moel@165
    54
    private UnitManager unitManager;
moel@165
    55
    private Computer computer;
moel@1
    56
    private Node root;
moel@1
    57
    private TreeModel treeModel;
moel@1
    58
    private IDictionary<ISensor, Color> sensorPlotColors = 
moel@1
    59
      new Dictionary<ISensor, Color>();
moel@1
    60
    private Color[] plotColorPalette;
moel@133
    61
    private SystemTray systemTray;    
moel@82
    62
    private StartupManager startupManager = new StartupManager();
moel@110
    63
    private UpdateVisitor updateVisitor = new UpdateVisitor();
moel@176
    64
    private SensorGadget gadget;
moel@295
    65
    private Form plotForm;
moel@1
    66
moel@156
    67
    private UserOption showHiddenSensors;
moel@156
    68
    private UserOption showPlot;
moel@156
    69
    private UserOption showValue;
moel@156
    70
    private UserOption showMin;
moel@156
    71
    private UserOption showMax;
moel@156
    72
    private UserOption startMinimized;
moel@156
    73
    private UserOption minimizeToTray;
paulwerelds@198
    74
    private UserOption minimizeOnClose;
moel@156
    75
    private UserOption autoStart;
moel@156
    76
    private UserOption readHddSensors;
moel@176
    77
    private UserOption showGadget;
moel@295
    78
    private UserRadioGroup plotLocation;
paulwerelds@223
    79
paulwerelds@223
    80
    private WmiProvider wmiProvider;
moel@156
    81
moel@288
    82
    private bool selectionDragging = false;
moel@288
    83
moel@28
    84
    public MainForm() {      
moel@1
    85
      InitializeComponent();
moel@156
    86
moel@291
    87
      // check if the OpenHardwareMonitorLib assembly has the correct version
moel@291
    88
      if (Assembly.GetAssembly(typeof(Computer)).GetName().Version !=
moel@291
    89
        Assembly.GetExecutingAssembly().GetName().Version) {
moel@291
    90
        MessageBox.Show(
moel@291
    91
          "The version of the file OpenHardwareMonitorLib.dll is incompatible.",
moel@291
    92
          "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
moel@291
    93
        Environment.Exit(0);
moel@291
    94
      }
moel@291
    95
moel@165
    96
      this.settings = new PersistentSettings();      
moel@165
    97
      this.settings.Load(Path.ChangeExtension(
paulwerelds@198
    98
        Application.ExecutablePath, ".config"));
moel@165
    99
moel@165
   100
      this.unitManager = new UnitManager(settings);
moel@165
   101
moel@304
   102
      // make sure the buffers used for double buffering are not disposed 
moel@304
   103
      // after each draw call
moel@304
   104
      BufferedGraphicsManager.Current.MaximumBuffer =
moel@304
   105
        Screen.PrimaryScreen.Bounds.Size;  
moel@304
   106
moel@156
   107
      // set the DockStyle here, to avoid conflicts with the MainMenu
moel@156
   108
      this.splitContainer.Dock = DockStyle.Fill;
moel@202
   109
            
moel@1
   110
      this.Font = SystemFonts.MessageBoxFont;
moel@1
   111
      treeView.Font = SystemFonts.MessageBoxFont;
moel@267
   112
      plotPanel.Font = SystemFonts.MessageBoxFont;           
moel@1
   113
      
moel@133
   114
      nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
moel@133
   115
      nodeCheckBox.CheckStateChanged += UpdatePlotSelection;
moel@133
   116
      nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
moel@133
   117
      nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
moel@133
   118
      nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
moel@133
   119
      nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
moel@141
   120
      nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
moel@1
   121
moel@113
   122
      foreach (TreeColumn column in treeView.Columns) 
moel@165
   123
        column.Width = Math.Max(20, Math.Min(400,
moel@166
   124
          settings.GetValue("treeView.Columns." + column.Header + ".Width",
moel@113
   125
          column.Width)));
moel@113
   126
moel@1
   127
      treeModel = new TreeModel();
moel@1
   128
      root = new Node(System.Environment.MachineName);
moel@1
   129
      root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
moel@1
   130
      
moel@1
   131
      treeModel.Nodes.Add(root);
moel@165
   132
      treeView.Model = treeModel;
moel@40
   133
moel@165
   134
      this.computer = new Computer(settings);
moel@165
   135
moel@165
   136
      systemTray = new SystemTray(computer, settings);
moel@133
   137
      systemTray.HideShowCommand += hideShowClick;
moel@133
   138
      systemTray.ExitCommand += exitClick;
moel@1
   139
moel@202
   140
      int p = (int)Environment.OSVersion.Platform;
moel@202
   141
      if ((p == 4) || (p == 128)) { // Unix
moel@287
   142
        treeView.RowHeight = Math.Max(treeView.RowHeight, 18); 
moel@202
   143
        splitContainer.BorderStyle = BorderStyle.None;
moel@202
   144
        splitContainer.Border3DStyle = Border3DStyle.Adjust;
moel@202
   145
        splitContainer.SplitterWidth = 4;
moel@202
   146
        treeView.BorderStyle = BorderStyle.Fixed3D;
moel@202
   147
        plotPanel.BorderStyle = BorderStyle.Fixed3D;
moel@202
   148
        gadgetMenuItem.Visible = false;
moel@202
   149
        minCloseMenuItem.Visible = false;
moel@269
   150
        minTrayMenuItem.Visible = false;
moel@269
   151
        startMinMenuItem.Visible = false;
moel@202
   152
      } else { // Windows
moel@287
   153
        treeView.RowHeight = Math.Max(treeView.Font.Height + 1, 18); 
moel@267
   154
moel@202
   155
        gadget = new SensorGadget(computer, settings, unitManager);
moel@244
   156
        gadget.HideShowCommand += hideShowClick;
moel@244
   157
moel@232
   158
        wmiProvider = new WmiProvider(computer);
moel@295
   159
      }    
moel@295
   160
      
moel@28
   161
      computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
moel@232
   162
      computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);        
paulwerelds@223
   163
moel@28
   164
      computer.Open();
moel@28
   165
moel@86
   166
      timer.Enabled = true;
moel@86
   167
moel@111
   168
      plotColorPalette = new Color[13];
moel@1
   169
      plotColorPalette[0] = Color.Blue;
moel@1
   170
      plotColorPalette[1] = Color.OrangeRed;
moel@1
   171
      plotColorPalette[2] = Color.Green;
moel@1
   172
      plotColorPalette[3] = Color.LightSeaGreen;
moel@1
   173
      plotColorPalette[4] = Color.Goldenrod;
moel@1
   174
      plotColorPalette[5] = Color.DarkViolet;
moel@1
   175
      plotColorPalette[6] = Color.YellowGreen;
moel@1
   176
      plotColorPalette[7] = Color.SaddleBrown;
moel@111
   177
      plotColorPalette[8] = Color.RoyalBlue;
moel@111
   178
      plotColorPalette[9] = Color.DeepPink;
moel@111
   179
      plotColorPalette[10] = Color.MediumSeaGreen;
moel@111
   180
      plotColorPalette[11] = Color.Olive;
moel@111
   181
      plotColorPalette[12] = Color.Firebrick;
moel@1
   182
paulwerelds@223
   183
      showHiddenSensors = new UserOption("hiddenMenuItem", false,
paulwerelds@223
   184
        hiddenMenuItem, settings);
moel@156
   185
      showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
moel@156
   186
        treeModel.ForceVisible = showHiddenSensors.Value;
moel@156
   187
      };
moel@111
   188
paulwerelds@223
   189
      showValue = new UserOption("valueMenuItem", true, valueMenuItem,
paulwerelds@223
   190
        settings);
moel@156
   191
      showValue.Changed += delegate(object sender, EventArgs e) {
moel@156
   192
        treeView.Columns[1].IsVisible = showValue.Value;
moel@156
   193
      };
moel@122
   194
moel@165
   195
      showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
moel@156
   196
      showMin.Changed += delegate(object sender, EventArgs e) {
moel@156
   197
        treeView.Columns[2].IsVisible = showMin.Value;
moel@156
   198
      };
moel@156
   199
moel@165
   200
      showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
moel@156
   201
      showMax.Changed += delegate(object sender, EventArgs e) {
moel@156
   202
        treeView.Columns[3].IsVisible = showMax.Value;
moel@156
   203
      };
moel@156
   204
paulwerelds@223
   205
      startMinimized = new UserOption("startMinMenuItem", false,
paulwerelds@223
   206
        startMinMenuItem, settings);
moel@156
   207
paulwerelds@223
   208
      minimizeToTray = new UserOption("minTrayMenuItem", true,
paulwerelds@223
   209
        minTrayMenuItem, settings);
moel@156
   210
      minimizeToTray.Changed += delegate(object sender, EventArgs e) {
moel@156
   211
        systemTray.IsMainIconEnabled = minimizeToTray.Value;
moel@156
   212
      };
moel@156
   213
paulwerelds@223
   214
      minimizeOnClose = new UserOption("minCloseMenuItem", false,
paulwerelds@223
   215
        minCloseMenuItem, settings);
paulwerelds@198
   216
paulwerelds@223
   217
      autoStart = new UserOption(null, startupManager.Startup,
paulwerelds@223
   218
        startupMenuItem, settings);
moel@156
   219
      autoStart.Changed += delegate(object sender, EventArgs e) {
moel@185
   220
        try {
moel@185
   221
          startupManager.Startup = autoStart.Value;
moel@185
   222
        } catch (InvalidOperationException) {
moel@185
   223
          MessageBox.Show("Updating the auto-startup option failed.", "Error", 
moel@185
   224
            MessageBoxButtons.OK, MessageBoxIcon.Error);
moel@185
   225
          autoStart.Value = startupManager.Startup;
moel@185
   226
        }
moel@156
   227
      };
moel@156
   228
paulwerelds@223
   229
      readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem,
paulwerelds@223
   230
        settings);
moel@156
   231
      readHddSensors.Changed += delegate(object sender, EventArgs e) {
moel@156
   232
        computer.HDDEnabled = readHddSensors.Value;
moel@156
   233
        UpdatePlotSelection(null, null);
moel@156
   234
      };
moel@156
   235
paulwerelds@223
   236
      showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem,
paulwerelds@223
   237
        settings);
moel@176
   238
      showGadget.Changed += delegate(object sender, EventArgs e) {
moel@202
   239
        if (gadget != null) 
moel@202
   240
          gadget.Visible = showGadget.Value;
moel@176
   241
      };
moel@176
   242
moel@299
   243
      celsiusMenuItem.Checked = 
moel@299
   244
        unitManager.TemperatureUnit == TemperatureUnit.Celsius;
moel@299
   245
      fahrenheitMenuItem.Checked = !celsiusMenuItem.Checked;
moel@55
   246
moel@295
   247
      InitializePlotForm();
moel@295
   248
moel@142
   249
      startupMenuItem.Visible = startupManager.IsAvailable;
moel@125
   250
      
moel@55
   251
      if (startMinMenuItem.Checked) {
moel@82
   252
        if (!minTrayMenuItem.Checked) {
moel@55
   253
          WindowState = FormWindowState.Minimized;
moel@55
   254
          Show();
moel@55
   255
        }
moel@55
   256
      } else {
moel@55
   257
        Show();
moel@55
   258
      }
moel@70
   259
moel@71
   260
      // Create a handle, otherwise calling Close() does not fire FormClosed     
moel@71
   261
      IntPtr handle = Handle;
moel@128
   262
moel@128
   263
      // Make sure the settings are saved when the user logs off
paulwerelds@223
   264
      Microsoft.Win32.SystemEvents.SessionEnded += delegate {
paulwerelds@223
   265
        SaveConfiguration();
moel@304
   266
      };
moel@1
   267
    }
moel@295
   268
moel@295
   269
    private void InitializePlotForm() {
moel@295
   270
      plotForm = new Form();
moel@295
   271
      plotForm.FormBorderStyle = FormBorderStyle.SizableToolWindow;
moel@295
   272
      plotForm.ShowInTaskbar = false;
moel@295
   273
      plotForm.StartPosition = FormStartPosition.Manual;
moel@295
   274
      this.AddOwnedForm(plotForm);
moel@295
   275
      plotForm.Bounds = new Rectangle {
moel@295
   276
        X = settings.GetValue("plotForm.Location.X", -100000),
moel@295
   277
        Y = settings.GetValue("plotForm.Location.Y", 100),
moel@295
   278
        Width = settings.GetValue("plotForm.Width", 600),
moel@295
   279
        Height = settings.GetValue("plotForm.Height", 400)
moel@295
   280
      };
moel@295
   281
moel@295
   282
      showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
moel@295
   283
      plotLocation = new UserRadioGroup("plotLocation", 0,
moel@295
   284
        new[] { plotWindowMenuItem, plotBottomMenuItem, plotRightMenuItem },
moel@295
   285
        settings);
moel@295
   286
moel@295
   287
      showPlot.Changed += delegate(object sender, EventArgs e) {
moel@295
   288
        if (plotLocation.Value == 0) {
moel@295
   289
          if (showPlot.Value && this.Visible)
moel@295
   290
            plotForm.Show();
moel@295
   291
          else
moel@295
   292
            plotForm.Hide();
moel@295
   293
        } else {
moel@295
   294
          splitContainer.Panel2Collapsed = !showPlot.Value;
moel@295
   295
        }
moel@295
   296
        treeView.Invalidate();
moel@295
   297
      };
moel@295
   298
      plotLocation.Changed += delegate(object sender, EventArgs e) {
moel@295
   299
        switch (plotLocation.Value) {
moel@295
   300
          case 0:
moel@295
   301
            splitContainer.Panel2.Controls.Clear();
moel@295
   302
            splitContainer.Panel2Collapsed = true;
moel@295
   303
            plotForm.Controls.Add(plotPanel);
moel@295
   304
            if (showPlot.Value && this.Visible)
moel@295
   305
              plotForm.Show();
moel@295
   306
            break;
moel@295
   307
          case 1:
moel@295
   308
            plotForm.Controls.Clear();
moel@295
   309
            plotForm.Hide();
moel@295
   310
            splitContainer.Orientation = Orientation.Horizontal;
moel@295
   311
            splitContainer.Panel2.Controls.Add(plotPanel);
moel@295
   312
            splitContainer.Panel2Collapsed = !showPlot.Value;
moel@295
   313
            break;
moel@295
   314
          case 2:
moel@295
   315
            plotForm.Controls.Clear();
moel@295
   316
            plotForm.Hide();
moel@295
   317
            splitContainer.Orientation = Orientation.Vertical;
moel@295
   318
            splitContainer.Panel2.Controls.Add(plotPanel);
moel@295
   319
            splitContainer.Panel2Collapsed = !showPlot.Value;
moel@295
   320
            break;
moel@295
   321
        }
moel@295
   322
      };
moel@297
   323
moel@297
   324
      plotForm.FormClosing += delegate(object sender, FormClosingEventArgs e) {
moel@297
   325
        if (e.CloseReason == CloseReason.UserClosing) {
moel@297
   326
          // just switch off the plotting when the user closes the form
moel@297
   327
          if (plotLocation.Value == 0) {
moel@297
   328
            showPlot.Value = false;
moel@297
   329
          }
moel@297
   330
          e.Cancel = true;
moel@295
   331
        }
moel@295
   332
      };
moel@297
   333
moel@295
   334
      EventHandler moveOrResizePlotForm = delegate(object sender, EventArgs e) {
moel@295
   335
        if (plotForm.WindowState != FormWindowState.Minimized) {
moel@295
   336
          settings.SetValue("plotForm.Location.X", plotForm.Bounds.X);
moel@295
   337
          settings.SetValue("plotForm.Location.Y", plotForm.Bounds.Y);
moel@295
   338
          settings.SetValue("plotForm.Width", plotForm.Bounds.Width);
moel@295
   339
          settings.SetValue("plotForm.Height", plotForm.Bounds.Height);
moel@295
   340
        }
moel@295
   341
      };
moel@295
   342
      plotForm.Move += moveOrResizePlotForm;
moel@295
   343
      plotForm.Resize += moveOrResizePlotForm;
moel@295
   344
moel@295
   345
      plotForm.VisibleChanged += delegate(object sender, EventArgs e) {
moel@295
   346
        Rectangle bounds = new Rectangle(plotForm.Location, plotForm.Size);
moel@295
   347
        Screen screen = Screen.FromRectangle(bounds);
moel@295
   348
        Rectangle intersection =
moel@295
   349
          Rectangle.Intersect(screen.WorkingArea, bounds);
moel@295
   350
        if (intersection.Width < Math.Min(16, bounds.Width) ||
moel@295
   351
            intersection.Height < Math.Min(16, bounds.Height)) {
moel@295
   352
          plotForm.Location = new Point(
moel@295
   353
            screen.WorkingArea.Width / 2 - bounds.Width / 2,
moel@295
   354
            screen.WorkingArea.Height / 2 - bounds.Height / 2);
moel@295
   355
        }
moel@295
   356
      };
moel@295
   357
moel@295
   358
      this.VisibleChanged += delegate(object sender, EventArgs e) {
moel@295
   359
        if (this.Visible && showPlot.Value && plotLocation.Value == 0)
moel@295
   360
          plotForm.Show();
moel@295
   361
        else
moel@295
   362
          plotForm.Hide();
moel@295
   363
      };
moel@295
   364
    }
moel@128
   365
    
moel@64
   366
    private void SubHardwareAdded(IHardware hardware, Node node) {
moel@165
   367
      Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
moel@64
   368
      node.Nodes.Add(hardwareNode);
moel@64
   369
      foreach (IHardware subHardware in hardware.SubHardware)
moel@64
   370
        SubHardwareAdded(subHardware, hardwareNode);  
moel@64
   371
    }
moel@64
   372
moel@28
   373
    private void HardwareAdded(IHardware hardware) {
moel@165
   374
      Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
moel@64
   375
      root.Nodes.Add(hardwareNode);
moel@64
   376
      foreach (IHardware subHardware in hardware.SubHardware)
moel@64
   377
        SubHardwareAdded(subHardware, hardwareNode);     
moel@1
   378
    }
moel@1
   379
moel@28
   380
    private void HardwareRemoved(IHardware hardware) {      
moel@1
   381
      List<Node> nodesToRemove = new List<Node>();
moel@28
   382
      foreach (Node node in root.Nodes) {
moel@28
   383
        HardwareNode hardwareNode = node as HardwareNode;
moel@28
   384
        if (hardwareNode != null && hardwareNode.Hardware == hardware)
moel@28
   385
          nodesToRemove.Add(node);
moel@28
   386
      }
moel@1
   387
      foreach (Node node in nodesToRemove)
moel@1
   388
        root.Nodes.Remove(node);
moel@1
   389
    }
moel@1
   390
moel@111
   391
    private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {       
moel@111
   392
      Node node = e.Node.Tag as Node;
moel@111
   393
      if (node != null) {
moel@1
   394
        Color color;
moel@111
   395
        if (node.IsVisible) {
moel@111
   396
          SensorNode sensorNode = node as SensorNode;
moel@111
   397
          if (plotMenuItem.Checked && sensorNode != null &&
moel@111
   398
            sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
moel@111
   399
            e.TextColor = color;
moel@111
   400
        } else {
moel@111
   401
          e.TextColor = Color.DarkGray;
moel@111
   402
        }
moel@1
   403
      }
moel@1
   404
    }
moel@1
   405
moel@1
   406
    private void UpdatePlotSelection(object sender, 
moel@1
   407
      TreePathEventArgs e) 
moel@1
   408
    {
moel@1
   409
      List<ISensor> selected = new List<ISensor>();
moel@1
   410
      IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
moel@1
   411
      int colorIndex = 0;
moel@1
   412
      foreach (TreeNodeAdv node in treeView.AllNodes) {
moel@1
   413
        SensorNode sensorNode = node.Tag as SensorNode;
moel@1
   414
        if (sensorNode != null && 
moel@1
   415
          sensorNode.Sensor.SensorType == SensorType.Temperature) {
moel@1
   416
          if (sensorNode.Plot) {
moel@1
   417
            colors.Add(sensorNode.Sensor,
moel@1
   418
              plotColorPalette[colorIndex % plotColorPalette.Length]);
moel@1
   419
            selected.Add(sensorNode.Sensor);
moel@1
   420
          }
moel@1
   421
          colorIndex++;
moel@1
   422
        }
moel@1
   423
      }
moel@1
   424
      sensorPlotColors = colors;
moel@1
   425
      plotPanel.SetSensors(selected, colors);
moel@1
   426
    }
moel@1
   427
paulwerelds@223
   428
    private void nodeTextBoxText_EditorShowing(object sender,
paulwerelds@223
   429
      CancelEventArgs e) 
moel@141
   430
    {
moel@141
   431
      e.Cancel = !(treeView.CurrentNode != null &&
moel@275
   432
        (treeView.CurrentNode.Tag is SensorNode || 
moel@275
   433
         treeView.CurrentNode.Tag is HardwareNode));
moel@141
   434
    }
moel@141
   435
moel@1
   436
    private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
moel@1
   437
      NodeControlValueEventArgs e) {
moel@1
   438
      SensorNode node = e.Node.Tag as SensorNode;
moel@1
   439
      e.Value = (node != null) && 
moel@1
   440
        (node.Sensor.SensorType == SensorType.Temperature) && 
moel@1
   441
        plotMenuItem.Checked;
moel@1
   442
    }
moel@1
   443
moel@133
   444
    private void exitClick(object sender, EventArgs e) {
paulwerelds@198
   445
      Close();
moel@1
   446
    }
moel@1
   447
moel@86
   448
    private void timer_Tick(object sender, EventArgs e) {
moel@110
   449
      computer.Accept(updateVisitor);
moel@1
   450
      treeView.Invalidate();
moel@1
   451
      plotPanel.Invalidate();
paulwerelds@223
   452
      systemTray.Redraw();
moel@202
   453
      if (gadget != null)
moel@202
   454
        gadget.Redraw();
paulwerelds@223
   455
paulwerelds@223
   456
      if (wmiProvider != null)
paulwerelds@223
   457
        wmiProvider.Update();
moel@1
   458
    }
moel@1
   459
moel@128
   460
    private void SaveConfiguration() {
moel@128
   461
      foreach (TreeColumn column in treeView.Columns)
moel@166
   462
        settings.SetValue("treeView.Columns." + column.Header + ".Width",
moel@113
   463
          column.Width);
moel@113
   464
moel@212
   465
      string fileName = Path.ChangeExtension(
moel@212
   466
          System.Windows.Forms.Application.ExecutablePath, ".config");
moel@212
   467
      try {
moel@212
   468
        settings.Save(fileName);
moel@212
   469
      } catch (UnauthorizedAccessException) {
paulwerelds@214
   470
        MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
moel@284
   471
          "The current settings could not be saved.",
moel@284
   472
          "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
moel@284
   473
      } catch (IOException) {
moel@284
   474
        MessageBox.Show("The path '" + fileName + "' is not writeable. " +
moel@284
   475
          "The current settings could not be saved.",
moel@212
   476
          "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
moel@212
   477
      }
moel@128
   478
    }
moel@128
   479
paulwerelds@214
   480
    private void MainForm_Load(object sender, EventArgs e) {
paulwerelds@214
   481
      Rectangle newBounds = new Rectangle {
paulwerelds@214
   482
        X = settings.GetValue("mainForm.Location.X", Location.X),
paulwerelds@214
   483
        Y = settings.GetValue("mainForm.Location.Y", Location.Y),
paulwerelds@214
   484
        Width = settings.GetValue("mainForm.Width", 470),
paulwerelds@214
   485
        Height = settings.GetValue("mainForm.Height", 640)
paulwerelds@214
   486
      };
paulwerelds@214
   487
paulwerelds@223
   488
      Rectangle fullWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
paulwerelds@214
   489
        int.MinValue, int.MinValue);
paulwerelds@214
   490
paulwerelds@214
   491
      foreach (Screen screen in Screen.AllScreens)
paulwerelds@223
   492
        fullWorkingArea = Rectangle.Union(fullWorkingArea, screen.Bounds);
paulwerelds@214
   493
paulwerelds@223
   494
      Rectangle intersection = Rectangle.Intersect(fullWorkingArea, newBounds);
paulwerelds@214
   495
      if (intersection.Width < 20 || intersection.Height < 20 ||
paulwerelds@214
   496
        !settings.Contains("mainForm.Location.X")
paulwerelds@214
   497
      ) {
paulwerelds@214
   498
        newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) -
paulwerelds@214
   499
                      (newBounds.Width/2);
paulwerelds@214
   500
paulwerelds@214
   501
        newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) -
paulwerelds@214
   502
                      (newBounds.Height / 2);
paulwerelds@214
   503
      }
paulwerelds@214
   504
paulwerelds@214
   505
      this.Bounds = newBounds;
paulwerelds@214
   506
    }
paulwerelds@214
   507
    
paulwerelds@214
   508
    private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
moel@298
   509
      Visible = false;      
moel@262
   510
      systemTray.IsMainIconEnabled = false;
moel@262
   511
      timer.Enabled = false;            
moel@28
   512
      computer.Close();
moel@298
   513
      SaveConfiguration();
moel@262
   514
      systemTray.Dispose();
moel@1
   515
    }
moel@1
   516
moel@156
   517
    private void aboutMenuItem_Click(object sender, EventArgs e) {
moel@1
   518
      new AboutBox().ShowDialog();
moel@1
   519
    }
moel@1
   520
moel@1
   521
    private void treeView_Click(object sender, EventArgs e) {
moel@275
   522
moel@1
   523
      MouseEventArgs m = e as MouseEventArgs;
moel@1
   524
      if (m == null || m.Button != MouseButtons.Right)
moel@1
   525
        return;
moel@1
   526
paulwerelds@223
   527
      NodeControlInfo info = treeView.GetNodeControlInfoAt(
paulwerelds@223
   528
        new Point(m.X, m.Y)
paulwerelds@223
   529
      );
moel@156
   530
      treeView.SelectedNode = info.Node;
moel@156
   531
      if (info.Node != null) {
moel@40
   532
        SensorNode node = info.Node.Tag as SensorNode;
moel@40
   533
        if (node != null && node.Sensor != null) {
moel@275
   534
          treeContextMenu.MenuItems.Clear();
moel@63
   535
          if (node.Sensor.Parameters.Length > 0) {
moel@156
   536
            MenuItem item = new MenuItem("Parameters...");
moel@63
   537
            item.Click += delegate(object obj, EventArgs args) {
moel@63
   538
              ShowParameterForm(node.Sensor);
moel@63
   539
            };
moel@275
   540
            treeContextMenu.MenuItems.Add(item);
moel@63
   541
          }
moel@156
   542
          if (nodeTextBoxText.EditEnabled) {
moel@156
   543
            MenuItem item = new MenuItem("Rename");
moel@141
   544
            item.Click += delegate(object obj, EventArgs args) {
moel@156
   545
              nodeTextBoxText.BeginEdit();
moel@141
   546
            };
moel@275
   547
            treeContextMenu.MenuItems.Add(item);
moel@176
   548
          }
moel@111
   549
          if (node.IsVisible) {
moel@156
   550
            MenuItem item = new MenuItem("Hide");
moel@111
   551
            item.Click += delegate(object obj, EventArgs args) {
moel@111
   552
              node.IsVisible = false;
moel@111
   553
            };
moel@275
   554
            treeContextMenu.MenuItems.Add(item);
moel@111
   555
          } else {
moel@156
   556
            MenuItem item = new MenuItem("Unhide");
moel@111
   557
            item.Click += delegate(object obj, EventArgs args) {
moel@111
   558
              node.IsVisible = true;
moel@111
   559
            };
moel@275
   560
            treeContextMenu.MenuItems.Add(item);
moel@176
   561
          }
moel@275
   562
          treeContextMenu.MenuItems.Add(new MenuItem("-"));
moel@178
   563
          {
moel@178
   564
            MenuItem item = new MenuItem("Show in Tray");
moel@178
   565
            item.Checked = systemTray.Contains(node.Sensor);
moel@178
   566
            item.Click += delegate(object obj, EventArgs args) {
moel@178
   567
              if (item.Checked)
moel@178
   568
                systemTray.Remove(node.Sensor);
moel@178
   569
              else
moel@178
   570
                systemTray.Add(node.Sensor, true);
moel@178
   571
            };
moel@275
   572
            treeContextMenu.MenuItems.Add(item);
moel@178
   573
          }
moel@211
   574
          if (gadget != null) {
moel@178
   575
            MenuItem item = new MenuItem("Show in Gadget");
moel@178
   576
            item.Checked = gadget.Contains(node.Sensor);
moel@178
   577
            item.Click += delegate(object obj, EventArgs args) {
moel@178
   578
              if (item.Checked) {
moel@178
   579
                gadget.Remove(node.Sensor);
moel@178
   580
              } else {
moel@178
   581
                gadget.Add(node.Sensor);
moel@178
   582
              }
moel@178
   583
            };
moel@275
   584
            treeContextMenu.MenuItems.Add(item);
moel@178
   585
          }
moel@247
   586
          if (node.Sensor.Control != null) {
moel@275
   587
            treeContextMenu.MenuItems.Add(new MenuItem("-"));
moel@247
   588
            IControl control = node.Sensor.Control;
moel@247
   589
            MenuItem controlItem = new MenuItem("Control");
moel@247
   590
            MenuItem defaultItem = new MenuItem("Default");
moel@247
   591
            defaultItem.Checked = control.ControlMode == ControlMode.Default;
moel@247
   592
            controlItem.MenuItems.Add(defaultItem);
moel@247
   593
            defaultItem.Click += delegate(object obj, EventArgs args) {
moel@247
   594
              control.SetDefault();
moel@247
   595
            };
moel@275
   596
            MenuItem manualItem = new MenuItem("Manual");
moel@247
   597
            controlItem.MenuItems.Add(manualItem);
moel@247
   598
            manualItem.Checked = control.ControlMode == ControlMode.Software;
moel@247
   599
            for (int i = 0; i <= 100; i += 5) {
moel@247
   600
              if (i <= control.MaxSoftwareValue &&
moel@275
   601
                  i >= control.MinSoftwareValue) {
moel@247
   602
                MenuItem item = new MenuItem(i + " %");
moel@247
   603
                manualItem.MenuItems.Add(item);
moel@247
   604
                item.Checked = control.ControlMode == ControlMode.Software &&
moel@247
   605
                  Math.Round(control.SoftwareValue) == i;
moel@247
   606
                int softwareValue = i;
moel@247
   607
                item.Click += delegate(object obj, EventArgs args) {
moel@247
   608
                  control.SetSoftware(softwareValue);
moel@247
   609
                };
moel@247
   610
              }
moel@247
   611
            }
moel@275
   612
            treeContextMenu.MenuItems.Add(controlItem);
moel@247
   613
          }
moel@176
   614
moel@275
   615
          treeContextMenu.Show(treeView, new Point(m.X, m.Y));
moel@275
   616
        }
moel@275
   617
moel@275
   618
        HardwareNode hardwareNode = info.Node.Tag as HardwareNode;
moel@275
   619
        if (hardwareNode != null && hardwareNode.Hardware != null) {
moel@275
   620
          treeContextMenu.MenuItems.Clear();
moel@275
   621
moel@275
   622
          if (nodeTextBoxText.EditEnabled) {
moel@275
   623
            MenuItem item = new MenuItem("Rename");
moel@275
   624
            item.Click += delegate(object obj, EventArgs args) {
moel@275
   625
              nodeTextBoxText.BeginEdit();
moel@275
   626
            };
moel@275
   627
            treeContextMenu.MenuItems.Add(item);
moel@275
   628
          }
moel@275
   629
moel@275
   630
          treeContextMenu.Show(treeView, new Point(m.X, m.Y));
moel@40
   631
        }
moel@40
   632
      }
moel@1
   633
    }
moel@1
   634
moel@156
   635
    private void saveReportMenuItem_Click(object sender, EventArgs e) {
moel@83
   636
      string report = computer.GetReport();
moel@83
   637
      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
moel@83
   638
        using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
moel@83
   639
          w.Write(report);
moel@83
   640
        }
moel@83
   641
      }
moel@1
   642
    }
moel@1
   643
moel@82
   644
    private void SysTrayHideShow() {
moel@82
   645
      Visible = !Visible;
moel@82
   646
      if (Visible)
moel@82
   647
        Activate();    
moel@27
   648
    }
moel@27
   649
moel@27
   650
    protected override void WndProc(ref Message m) {
moel@27
   651
      const int WM_SYSCOMMAND = 0x112;
moel@27
   652
      const int SC_MINIMIZE = 0xF020;
paulwerelds@198
   653
      const int SC_CLOSE = 0xF060;
paulwerelds@198
   654
moel@156
   655
      if (minimizeToTray.Value && 
moel@28
   656
        m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
moel@82
   657
        SysTrayHideShow();
paulwerelds@198
   658
      } else if(minimizeOnClose.Value && 
paulwerelds@198
   659
        m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
paulwerelds@198
   660
        /*
paulwerelds@198
   661
         * Apparently the user wants to minimize rather than close
paulwerelds@198
   662
         * Now we still need to check if we're going to the tray or not
paulwerelds@198
   663
         * 
paulwerelds@198
   664
         * Note: the correct way to do this would be to send out SC_MINIMIZE,
paulwerelds@198
   665
         * but since the code here is so simple,
paulwerelds@198
   666
         * that would just be a waste of time.
paulwerelds@198
   667
         */
paulwerelds@198
   668
        if (minimizeToTray.Value)
paulwerelds@198
   669
          SysTrayHideShow();
paulwerelds@198
   670
        else
paulwerelds@198
   671
          WindowState = FormWindowState.Minimized;
moel@27
   672
      } else {      
moel@27
   673
        base.WndProc(ref m);
moel@27
   674
      }
moel@27
   675
    }
moel@27
   676
moel@82
   677
    private void hideShowClick(object sender, EventArgs e) {
moel@82
   678
      SysTrayHideShow();
moel@27
   679
    }
moel@27
   680
moel@63
   681
    private void ShowParameterForm(ISensor sensor) {
moel@63
   682
      ParameterForm form = new ParameterForm();
moel@63
   683
      form.Parameters = sensor.Parameters;
moel@63
   684
      form.captionLabel.Text = sensor.Name;
moel@63
   685
      form.ShowDialog();
moel@63
   686
    }
moel@63
   687
moel@63
   688
    private void treeView_NodeMouseDoubleClick(object sender, 
moel@63
   689
      TreeNodeAdvMouseEventArgs e) {
moel@63
   690
      SensorNode node = e.Node.Tag as SensorNode;
moel@63
   691
      if (node != null && node.Sensor != null && 
moel@63
   692
        node.Sensor.Parameters.Length > 0) {
moel@63
   693
        ShowParameterForm(node.Sensor);
moel@63
   694
      }
moel@63
   695
    }
moel@82
   696
moel@299
   697
    private void celsiusMenuItem_Click(object sender, EventArgs e) {
moel@299
   698
      celsiusMenuItem.Checked = true;
moel@156
   699
      fahrenheitMenuItem.Checked = false;
moel@299
   700
      unitManager.TemperatureUnit = TemperatureUnit.Celsius;
moel@122
   701
    }
moel@122
   702
moel@156
   703
    private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
moel@299
   704
      celsiusMenuItem.Checked = false;
moel@156
   705
      fahrenheitMenuItem.Checked = true;
moel@165
   706
      unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
moel@122
   707
    }
moel@150
   708
moel@156
   709
    private void sumbitReportMenuItem_Click(object sender, EventArgs e) 
moel@150
   710
    {
moel@150
   711
      ReportForm form = new ReportForm();
moel@150
   712
      form.Report = computer.GetReport();
moel@150
   713
      form.ShowDialog();      
moel@150
   714
    }
moel@151
   715
moel@151
   716
    private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
moel@159
   717
      computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
moel@159
   718
        sensor.ResetMin();
moel@159
   719
        sensor.ResetMax();
moel@159
   720
      }));
moel@151
   721
    }
moel@241
   722
moel@241
   723
    private void MainForm_MoveOrResize(object sender, EventArgs e) {
moel@241
   724
      if (WindowState != FormWindowState.Minimized) {
moel@241
   725
        settings.SetValue("mainForm.Location.X", Bounds.X);
moel@241
   726
        settings.SetValue("mainForm.Location.Y", Bounds.Y);
moel@241
   727
        settings.SetValue("mainForm.Width", Bounds.Width);
moel@241
   728
        settings.SetValue("mainForm.Height", Bounds.Height);
moel@241
   729
      }
moel@241
   730
    }
moel@262
   731
moel@262
   732
    private void resetClick(object sender, EventArgs e) {
moel@262
   733
      // disable the fallback MainIcon during reset, otherwise icon visibility
moel@262
   734
      // might be lost 
moel@262
   735
      systemTray.IsMainIconEnabled = false;
moel@262
   736
      computer.Close();
moel@262
   737
      computer.Open();
moel@262
   738
      // restore the MainIcon setting
moel@262
   739
      systemTray.IsMainIconEnabled = minimizeToTray.Value;
moel@262
   740
    }
moel@287
   741
moel@287
   742
    private void treeView_MouseMove(object sender, MouseEventArgs e) {
moel@288
   743
      selectionDragging = selectionDragging &
moel@288
   744
        (e.Button & (MouseButtons.Left | MouseButtons.Right)) > 0; 
moel@288
   745
moel@288
   746
      if (selectionDragging)
moel@288
   747
        treeView.SelectedNode = treeView.GetNodeAt(e.Location);     
moel@288
   748
    }
moel@288
   749
moel@288
   750
    private void treeView_MouseDown(object sender, MouseEventArgs e) {
moel@288
   751
      selectionDragging = true;
moel@288
   752
    }
moel@288
   753
moel@288
   754
    private void treeView_MouseUp(object sender, MouseEventArgs e) {
moel@288
   755
      selectionDragging = false;
moel@287
   756
    }
moel@1
   757
  }
moel@1
   758
}