GUI/MainForm.cs
author moel.mich
Sun, 08 May 2011 22:10:13 +0000
changeset 279 6bce967ba1b5
parent 269 38cd90779aad
child 284 075a1822ef34
permissions -rw-r--r--
Fixed the bus and core clock reading on AMD family 10h model Ah CPUs. The new "Core Performance Boost" feature of these CPUs resulted in very low accuracy of the bus speed (and as a consequence also an inaccurate TSC multiplier). This fixed Issue 205.
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@1
    43
using System.Windows.Forms;
moel@1
    44
using Aga.Controls.Tree;
moel@1
    45
using Aga.Controls.Tree.NodeControls;
moel@1
    46
using OpenHardwareMonitor.Hardware;
paulwerelds@227
    47
using OpenHardwareMonitor.WMI;
moel@1
    48
moel@1
    49
namespace OpenHardwareMonitor.GUI {
moel@1
    50
  public partial class MainForm : Form {
moel@1
    51
moel@165
    52
    private PersistentSettings settings;
moel@165
    53
    private UnitManager unitManager;
moel@165
    54
    private Computer computer;
moel@1
    55
    private Node root;
moel@1
    56
    private TreeModel treeModel;
moel@1
    57
    private IDictionary<ISensor, Color> sensorPlotColors = 
moel@1
    58
      new Dictionary<ISensor, Color>();
moel@1
    59
    private Color[] plotColorPalette;
moel@133
    60
    private SystemTray systemTray;    
moel@82
    61
    private StartupManager startupManager = new StartupManager();
moel@110
    62
    private UpdateVisitor updateVisitor = new UpdateVisitor();
moel@176
    63
    private SensorGadget gadget;
moel@1
    64
moel@156
    65
    private UserOption showHiddenSensors;
moel@156
    66
    private UserOption showPlot;
moel@156
    67
    private UserOption showValue;
moel@156
    68
    private UserOption showMin;
moel@156
    69
    private UserOption showMax;
moel@156
    70
    private UserOption startMinimized;
moel@156
    71
    private UserOption minimizeToTray;
paulwerelds@198
    72
    private UserOption minimizeOnClose;
moel@156
    73
    private UserOption autoStart;
moel@156
    74
    private UserOption readHddSensors;
moel@176
    75
    private UserOption showGadget;
paulwerelds@223
    76
paulwerelds@223
    77
    private WmiProvider wmiProvider;
moel@156
    78
moel@28
    79
    public MainForm() {      
moel@1
    80
      InitializeComponent();
moel@156
    81
moel@165
    82
      this.settings = new PersistentSettings();      
moel@165
    83
      this.settings.Load(Path.ChangeExtension(
paulwerelds@198
    84
        Application.ExecutablePath, ".config"));
moel@165
    85
moel@165
    86
      this.unitManager = new UnitManager(settings);
moel@165
    87
moel@156
    88
      // set the DockStyle here, to avoid conflicts with the MainMenu
moel@156
    89
      this.splitContainer.Dock = DockStyle.Fill;
moel@202
    90
            
moel@1
    91
      this.Font = SystemFonts.MessageBoxFont;
moel@1
    92
      treeView.Font = SystemFonts.MessageBoxFont;
moel@267
    93
      plotPanel.Font = SystemFonts.MessageBoxFont;           
moel@1
    94
      
moel@133
    95
      nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
moel@133
    96
      nodeCheckBox.CheckStateChanged += UpdatePlotSelection;
moel@133
    97
      nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
moel@133
    98
      nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
moel@133
    99
      nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
moel@133
   100
      nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
moel@141
   101
      nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
moel@1
   102
moel@113
   103
      foreach (TreeColumn column in treeView.Columns) 
moel@165
   104
        column.Width = Math.Max(20, Math.Min(400,
moel@166
   105
          settings.GetValue("treeView.Columns." + column.Header + ".Width",
moel@113
   106
          column.Width)));
moel@113
   107
moel@1
   108
      treeModel = new TreeModel();
moel@1
   109
      root = new Node(System.Environment.MachineName);
moel@1
   110
      root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
moel@1
   111
      
moel@1
   112
      treeModel.Nodes.Add(root);
moel@165
   113
      treeView.Model = treeModel;
moel@40
   114
moel@165
   115
      this.computer = new Computer(settings);
moel@165
   116
moel@165
   117
      systemTray = new SystemTray(computer, settings);
moel@133
   118
      systemTray.HideShowCommand += hideShowClick;
moel@133
   119
      systemTray.ExitCommand += exitClick;
moel@1
   120
moel@202
   121
      int p = (int)Environment.OSVersion.Platform;
moel@202
   122
      if ((p == 4) || (p == 128)) { // Unix
moel@267
   123
        treeView.RowHeight = Math.Max(treeView.RowHeight, 17); 
moel@202
   124
        splitContainer.BorderStyle = BorderStyle.None;
moel@202
   125
        splitContainer.Border3DStyle = Border3DStyle.Adjust;
moel@202
   126
        splitContainer.SplitterWidth = 4;
moel@202
   127
        treeView.BorderStyle = BorderStyle.Fixed3D;
moel@202
   128
        plotPanel.BorderStyle = BorderStyle.Fixed3D;
moel@202
   129
        gadgetMenuItem.Visible = false;
moel@202
   130
        minCloseMenuItem.Visible = false;
moel@269
   131
        minTrayMenuItem.Visible = false;
moel@269
   132
        startMinMenuItem.Visible = false;
moel@202
   133
      } else { // Windows
moel@267
   134
        treeView.RowHeight = Math.Max(treeView.Font.Height + 1, 17); 
moel@267
   135
moel@202
   136
        gadget = new SensorGadget(computer, settings, unitManager);
moel@244
   137
        gadget.HideShowCommand += hideShowClick;
moel@244
   138
moel@232
   139
        wmiProvider = new WmiProvider(computer);
moel@202
   140
      }          
moel@176
   141
moel@28
   142
      computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
moel@232
   143
      computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);        
paulwerelds@223
   144
moel@28
   145
      computer.Open();
moel@28
   146
moel@86
   147
      timer.Enabled = true;
moel@86
   148
moel@111
   149
      plotColorPalette = new Color[13];
moel@1
   150
      plotColorPalette[0] = Color.Blue;
moel@1
   151
      plotColorPalette[1] = Color.OrangeRed;
moel@1
   152
      plotColorPalette[2] = Color.Green;
moel@1
   153
      plotColorPalette[3] = Color.LightSeaGreen;
moel@1
   154
      plotColorPalette[4] = Color.Goldenrod;
moel@1
   155
      plotColorPalette[5] = Color.DarkViolet;
moel@1
   156
      plotColorPalette[6] = Color.YellowGreen;
moel@1
   157
      plotColorPalette[7] = Color.SaddleBrown;
moel@111
   158
      plotColorPalette[8] = Color.RoyalBlue;
moel@111
   159
      plotColorPalette[9] = Color.DeepPink;
moel@111
   160
      plotColorPalette[10] = Color.MediumSeaGreen;
moel@111
   161
      plotColorPalette[11] = Color.Olive;
moel@111
   162
      plotColorPalette[12] = Color.Firebrick;
moel@1
   163
paulwerelds@223
   164
      showHiddenSensors = new UserOption("hiddenMenuItem", false,
paulwerelds@223
   165
        hiddenMenuItem, settings);
moel@156
   166
      showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
moel@156
   167
        treeModel.ForceVisible = showHiddenSensors.Value;
moel@156
   168
      };
moel@111
   169
moel@165
   170
      showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
moel@156
   171
      showPlot.Changed += delegate(object sender, EventArgs e) {
moel@156
   172
        splitContainer.Panel2Collapsed = !showPlot.Value;
moel@156
   173
        treeView.Invalidate();
moel@156
   174
      };
moel@1
   175
paulwerelds@223
   176
      showValue = new UserOption("valueMenuItem", true, valueMenuItem,
paulwerelds@223
   177
        settings);
moel@156
   178
      showValue.Changed += delegate(object sender, EventArgs e) {
moel@156
   179
        treeView.Columns[1].IsVisible = showValue.Value;
moel@156
   180
      };
moel@122
   181
moel@165
   182
      showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
moel@156
   183
      showMin.Changed += delegate(object sender, EventArgs e) {
moel@156
   184
        treeView.Columns[2].IsVisible = showMin.Value;
moel@156
   185
      };
moel@156
   186
moel@165
   187
      showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
moel@156
   188
      showMax.Changed += delegate(object sender, EventArgs e) {
moel@156
   189
        treeView.Columns[3].IsVisible = showMax.Value;
moel@156
   190
      };
moel@156
   191
paulwerelds@223
   192
      startMinimized = new UserOption("startMinMenuItem", false,
paulwerelds@223
   193
        startMinMenuItem, settings);
moel@156
   194
paulwerelds@223
   195
      minimizeToTray = new UserOption("minTrayMenuItem", true,
paulwerelds@223
   196
        minTrayMenuItem, settings);
moel@156
   197
      minimizeToTray.Changed += delegate(object sender, EventArgs e) {
moel@156
   198
        systemTray.IsMainIconEnabled = minimizeToTray.Value;
moel@156
   199
      };
moel@156
   200
paulwerelds@223
   201
      minimizeOnClose = new UserOption("minCloseMenuItem", false,
paulwerelds@223
   202
        minCloseMenuItem, settings);
paulwerelds@198
   203
paulwerelds@223
   204
      autoStart = new UserOption(null, startupManager.Startup,
paulwerelds@223
   205
        startupMenuItem, settings);
moel@156
   206
      autoStart.Changed += delegate(object sender, EventArgs e) {
moel@185
   207
        try {
moel@185
   208
          startupManager.Startup = autoStart.Value;
moel@185
   209
        } catch (InvalidOperationException) {
moel@185
   210
          MessageBox.Show("Updating the auto-startup option failed.", "Error", 
moel@185
   211
            MessageBoxButtons.OK, MessageBoxIcon.Error);
moel@185
   212
          autoStart.Value = startupManager.Startup;
moel@185
   213
        }
moel@156
   214
      };
moel@156
   215
paulwerelds@223
   216
      readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem,
paulwerelds@223
   217
        settings);
moel@156
   218
      readHddSensors.Changed += delegate(object sender, EventArgs e) {
moel@156
   219
        computer.HDDEnabled = readHddSensors.Value;
moel@156
   220
        UpdatePlotSelection(null, null);
moel@156
   221
      };
moel@156
   222
paulwerelds@223
   223
      showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem,
paulwerelds@223
   224
        settings);
moel@176
   225
      showGadget.Changed += delegate(object sender, EventArgs e) {
moel@202
   226
        if (gadget != null) 
moel@202
   227
          gadget.Visible = showGadget.Value;
moel@176
   228
      };
moel@176
   229
moel@156
   230
      celciusMenuItem.Checked = 
moel@165
   231
        unitManager.TemperatureUnit == TemperatureUnit.Celcius;
moel@156
   232
      fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
moel@55
   233
moel@142
   234
      startupMenuItem.Visible = startupManager.IsAvailable;
moel@125
   235
      
moel@55
   236
      if (startMinMenuItem.Checked) {
moel@82
   237
        if (!minTrayMenuItem.Checked) {
moel@55
   238
          WindowState = FormWindowState.Minimized;
moel@55
   239
          Show();
moel@55
   240
        }
moel@55
   241
      } else {
moel@55
   242
        Show();
moel@55
   243
      }
moel@70
   244
moel@71
   245
      // Create a handle, otherwise calling Close() does not fire FormClosed     
moel@71
   246
      IntPtr handle = Handle;
moel@128
   247
moel@128
   248
      // Make sure the settings are saved when the user logs off
paulwerelds@223
   249
      Microsoft.Win32.SystemEvents.SessionEnded += delegate {
paulwerelds@223
   250
        SaveConfiguration();
paulwerelds@223
   251
      };  
moel@1
   252
    }
moel@128
   253
    
moel@64
   254
    private void SubHardwareAdded(IHardware hardware, Node node) {
moel@165
   255
      Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
moel@64
   256
      node.Nodes.Add(hardwareNode);
moel@64
   257
      foreach (IHardware subHardware in hardware.SubHardware)
moel@64
   258
        SubHardwareAdded(subHardware, hardwareNode);  
moel@64
   259
    }
moel@64
   260
moel@28
   261
    private void HardwareAdded(IHardware hardware) {
moel@165
   262
      Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
moel@64
   263
      root.Nodes.Add(hardwareNode);
moel@64
   264
      foreach (IHardware subHardware in hardware.SubHardware)
moel@64
   265
        SubHardwareAdded(subHardware, hardwareNode);     
moel@1
   266
    }
moel@1
   267
moel@28
   268
    private void HardwareRemoved(IHardware hardware) {      
moel@1
   269
      List<Node> nodesToRemove = new List<Node>();
moel@28
   270
      foreach (Node node in root.Nodes) {
moel@28
   271
        HardwareNode hardwareNode = node as HardwareNode;
moel@28
   272
        if (hardwareNode != null && hardwareNode.Hardware == hardware)
moel@28
   273
          nodesToRemove.Add(node);
moel@28
   274
      }
moel@1
   275
      foreach (Node node in nodesToRemove)
moel@1
   276
        root.Nodes.Remove(node);
moel@1
   277
    }
moel@1
   278
moel@111
   279
    private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {       
moel@111
   280
      Node node = e.Node.Tag as Node;
moel@111
   281
      if (node != null) {
moel@1
   282
        Color color;
moel@111
   283
        if (node.IsVisible) {
moel@111
   284
          SensorNode sensorNode = node as SensorNode;
moel@111
   285
          if (plotMenuItem.Checked && sensorNode != null &&
moel@111
   286
            sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
moel@111
   287
            e.TextColor = color;
moel@111
   288
        } else {
moel@111
   289
          e.TextColor = Color.DarkGray;
moel@111
   290
        }
moel@1
   291
      }
moel@1
   292
    }
moel@1
   293
moel@1
   294
    private void UpdatePlotSelection(object sender, 
moel@1
   295
      TreePathEventArgs e) 
moel@1
   296
    {
moel@1
   297
      List<ISensor> selected = new List<ISensor>();
moel@1
   298
      IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
moel@1
   299
      int colorIndex = 0;
moel@1
   300
      foreach (TreeNodeAdv node in treeView.AllNodes) {
moel@1
   301
        SensorNode sensorNode = node.Tag as SensorNode;
moel@1
   302
        if (sensorNode != null && 
moel@1
   303
          sensorNode.Sensor.SensorType == SensorType.Temperature) {
moel@1
   304
          if (sensorNode.Plot) {
moel@1
   305
            colors.Add(sensorNode.Sensor,
moel@1
   306
              plotColorPalette[colorIndex % plotColorPalette.Length]);
moel@1
   307
            selected.Add(sensorNode.Sensor);
moel@1
   308
          }
moel@1
   309
          colorIndex++;
moel@1
   310
        }
moel@1
   311
      }
moel@1
   312
      sensorPlotColors = colors;
moel@1
   313
      plotPanel.SetSensors(selected, colors);
moel@1
   314
    }
moel@1
   315
paulwerelds@223
   316
    private void nodeTextBoxText_EditorShowing(object sender,
paulwerelds@223
   317
      CancelEventArgs e) 
moel@141
   318
    {
moel@141
   319
      e.Cancel = !(treeView.CurrentNode != null &&
moel@275
   320
        (treeView.CurrentNode.Tag is SensorNode || 
moel@275
   321
         treeView.CurrentNode.Tag is HardwareNode));
moel@141
   322
    }
moel@141
   323
moel@1
   324
    private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
moel@1
   325
      NodeControlValueEventArgs e) {
moel@1
   326
      SensorNode node = e.Node.Tag as SensorNode;
moel@1
   327
      e.Value = (node != null) && 
moel@1
   328
        (node.Sensor.SensorType == SensorType.Temperature) && 
moel@1
   329
        plotMenuItem.Checked;
moel@1
   330
    }
moel@1
   331
moel@133
   332
    private void exitClick(object sender, EventArgs e) {
paulwerelds@198
   333
      Close();
moel@1
   334
    }
moel@1
   335
moel@86
   336
    private void timer_Tick(object sender, EventArgs e) {
moel@110
   337
      computer.Accept(updateVisitor);
moel@1
   338
      treeView.Invalidate();
moel@1
   339
      plotPanel.Invalidate();
paulwerelds@223
   340
      systemTray.Redraw();
moel@202
   341
      if (gadget != null)
moel@202
   342
        gadget.Redraw();
paulwerelds@223
   343
paulwerelds@223
   344
      if (wmiProvider != null)
paulwerelds@223
   345
        wmiProvider.Update();
moel@1
   346
    }
moel@1
   347
moel@128
   348
    private void SaveConfiguration() {
moel@128
   349
      foreach (TreeColumn column in treeView.Columns)
moel@166
   350
        settings.SetValue("treeView.Columns." + column.Header + ".Width",
moel@113
   351
          column.Width);
moel@113
   352
moel@212
   353
      string fileName = Path.ChangeExtension(
moel@212
   354
          System.Windows.Forms.Application.ExecutablePath, ".config");
moel@212
   355
      try {
moel@212
   356
        settings.Save(fileName);
moel@212
   357
      } catch (UnauthorizedAccessException) {
paulwerelds@214
   358
        MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
moel@212
   359
          "The current seetings could not be saved.", 
moel@212
   360
          "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
moel@212
   361
      }
moel@128
   362
    }
moel@128
   363
paulwerelds@214
   364
    private void MainForm_Load(object sender, EventArgs e) {
paulwerelds@214
   365
      Rectangle newBounds = new Rectangle {
paulwerelds@214
   366
        X = settings.GetValue("mainForm.Location.X", Location.X),
paulwerelds@214
   367
        Y = settings.GetValue("mainForm.Location.Y", Location.Y),
paulwerelds@214
   368
        Width = settings.GetValue("mainForm.Width", 470),
paulwerelds@214
   369
        Height = settings.GetValue("mainForm.Height", 640)
paulwerelds@214
   370
      };
paulwerelds@214
   371
paulwerelds@223
   372
      Rectangle fullWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
paulwerelds@214
   373
        int.MinValue, int.MinValue);
paulwerelds@214
   374
paulwerelds@214
   375
      foreach (Screen screen in Screen.AllScreens)
paulwerelds@223
   376
        fullWorkingArea = Rectangle.Union(fullWorkingArea, screen.Bounds);
paulwerelds@214
   377
paulwerelds@223
   378
      Rectangle intersection = Rectangle.Intersect(fullWorkingArea, newBounds);
paulwerelds@214
   379
      if (intersection.Width < 20 || intersection.Height < 20 ||
paulwerelds@214
   380
        !settings.Contains("mainForm.Location.X")
paulwerelds@214
   381
      ) {
paulwerelds@214
   382
        newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) -
paulwerelds@214
   383
                      (newBounds.Width/2);
paulwerelds@214
   384
paulwerelds@214
   385
        newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) -
paulwerelds@214
   386
                      (newBounds.Height / 2);
paulwerelds@214
   387
      }
paulwerelds@214
   388
paulwerelds@214
   389
      this.Bounds = newBounds;
paulwerelds@214
   390
    }
paulwerelds@214
   391
    
paulwerelds@214
   392
    private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
moel@156
   393
      Visible = false;
moel@128
   394
      SaveConfiguration();
moel@128
   395
moel@262
   396
      systemTray.IsMainIconEnabled = false;
moel@262
   397
      timer.Enabled = false;            
moel@28
   398
      computer.Close();
moel@262
   399
      systemTray.Dispose();
moel@1
   400
    }
moel@1
   401
moel@156
   402
    private void aboutMenuItem_Click(object sender, EventArgs e) {
moel@1
   403
      new AboutBox().ShowDialog();
moel@1
   404
    }
moel@1
   405
moel@1
   406
    private void treeView_Click(object sender, EventArgs e) {
moel@275
   407
moel@1
   408
      MouseEventArgs m = e as MouseEventArgs;
moel@1
   409
      if (m == null || m.Button != MouseButtons.Right)
moel@1
   410
        return;
moel@1
   411
paulwerelds@223
   412
      NodeControlInfo info = treeView.GetNodeControlInfoAt(
paulwerelds@223
   413
        new Point(m.X, m.Y)
paulwerelds@223
   414
      );
moel@156
   415
      treeView.SelectedNode = info.Node;
moel@156
   416
      if (info.Node != null) {
moel@40
   417
        SensorNode node = info.Node.Tag as SensorNode;
moel@40
   418
        if (node != null && node.Sensor != null) {
moel@275
   419
          treeContextMenu.MenuItems.Clear();
moel@63
   420
          if (node.Sensor.Parameters.Length > 0) {
moel@156
   421
            MenuItem item = new MenuItem("Parameters...");
moel@63
   422
            item.Click += delegate(object obj, EventArgs args) {
moel@63
   423
              ShowParameterForm(node.Sensor);
moel@63
   424
            };
moel@275
   425
            treeContextMenu.MenuItems.Add(item);
moel@63
   426
          }
moel@156
   427
          if (nodeTextBoxText.EditEnabled) {
moel@156
   428
            MenuItem item = new MenuItem("Rename");
moel@141
   429
            item.Click += delegate(object obj, EventArgs args) {
moel@156
   430
              nodeTextBoxText.BeginEdit();
moel@141
   431
            };
moel@275
   432
            treeContextMenu.MenuItems.Add(item);
moel@176
   433
          }
moel@111
   434
          if (node.IsVisible) {
moel@156
   435
            MenuItem item = new MenuItem("Hide");
moel@111
   436
            item.Click += delegate(object obj, EventArgs args) {
moel@111
   437
              node.IsVisible = false;
moel@111
   438
            };
moel@275
   439
            treeContextMenu.MenuItems.Add(item);
moel@111
   440
          } else {
moel@156
   441
            MenuItem item = new MenuItem("Unhide");
moel@111
   442
            item.Click += delegate(object obj, EventArgs args) {
moel@111
   443
              node.IsVisible = true;
moel@111
   444
            };
moel@275
   445
            treeContextMenu.MenuItems.Add(item);
moel@176
   446
          }
moel@275
   447
          treeContextMenu.MenuItems.Add(new MenuItem("-"));
moel@178
   448
          {
moel@178
   449
            MenuItem item = new MenuItem("Show in Tray");
moel@178
   450
            item.Checked = systemTray.Contains(node.Sensor);
moel@178
   451
            item.Click += delegate(object obj, EventArgs args) {
moel@178
   452
              if (item.Checked)
moel@178
   453
                systemTray.Remove(node.Sensor);
moel@178
   454
              else
moel@178
   455
                systemTray.Add(node.Sensor, true);
moel@178
   456
            };
moel@275
   457
            treeContextMenu.MenuItems.Add(item);
moel@178
   458
          }
moel@211
   459
          if (gadget != null) {
moel@178
   460
            MenuItem item = new MenuItem("Show in Gadget");
moel@178
   461
            item.Checked = gadget.Contains(node.Sensor);
moel@178
   462
            item.Click += delegate(object obj, EventArgs args) {
moel@178
   463
              if (item.Checked) {
moel@178
   464
                gadget.Remove(node.Sensor);
moel@178
   465
              } else {
moel@178
   466
                gadget.Add(node.Sensor);
moel@178
   467
              }
moel@178
   468
            };
moel@275
   469
            treeContextMenu.MenuItems.Add(item);
moel@178
   470
          }
moel@247
   471
          if (node.Sensor.Control != null) {
moel@275
   472
            treeContextMenu.MenuItems.Add(new MenuItem("-"));
moel@247
   473
            IControl control = node.Sensor.Control;
moel@247
   474
            MenuItem controlItem = new MenuItem("Control");
moel@247
   475
            MenuItem defaultItem = new MenuItem("Default");
moel@247
   476
            defaultItem.Checked = control.ControlMode == ControlMode.Default;
moel@247
   477
            controlItem.MenuItems.Add(defaultItem);
moel@247
   478
            defaultItem.Click += delegate(object obj, EventArgs args) {
moel@247
   479
              control.SetDefault();
moel@247
   480
            };
moel@275
   481
            MenuItem manualItem = new MenuItem("Manual");
moel@247
   482
            controlItem.MenuItems.Add(manualItem);
moel@247
   483
            manualItem.Checked = control.ControlMode == ControlMode.Software;
moel@247
   484
            for (int i = 0; i <= 100; i += 5) {
moel@247
   485
              if (i <= control.MaxSoftwareValue &&
moel@275
   486
                  i >= control.MinSoftwareValue) {
moel@247
   487
                MenuItem item = new MenuItem(i + " %");
moel@247
   488
                manualItem.MenuItems.Add(item);
moel@247
   489
                item.Checked = control.ControlMode == ControlMode.Software &&
moel@247
   490
                  Math.Round(control.SoftwareValue) == i;
moel@247
   491
                int softwareValue = i;
moel@247
   492
                item.Click += delegate(object obj, EventArgs args) {
moel@247
   493
                  control.SetSoftware(softwareValue);
moel@247
   494
                };
moel@247
   495
              }
moel@247
   496
            }
moel@275
   497
            treeContextMenu.MenuItems.Add(controlItem);
moel@247
   498
          }
moel@176
   499
moel@275
   500
          treeContextMenu.Show(treeView, new Point(m.X, m.Y));
moel@275
   501
        }
moel@275
   502
moel@275
   503
        HardwareNode hardwareNode = info.Node.Tag as HardwareNode;
moel@275
   504
        if (hardwareNode != null && hardwareNode.Hardware != null) {
moel@275
   505
          treeContextMenu.MenuItems.Clear();
moel@275
   506
moel@275
   507
          if (nodeTextBoxText.EditEnabled) {
moel@275
   508
            MenuItem item = new MenuItem("Rename");
moel@275
   509
            item.Click += delegate(object obj, EventArgs args) {
moel@275
   510
              nodeTextBoxText.BeginEdit();
moel@275
   511
            };
moel@275
   512
            treeContextMenu.MenuItems.Add(item);
moel@275
   513
          }
moel@275
   514
moel@275
   515
          treeContextMenu.Show(treeView, new Point(m.X, m.Y));
moel@40
   516
        }
moel@40
   517
      }
moel@1
   518
    }
moel@1
   519
moel@156
   520
    private void saveReportMenuItem_Click(object sender, EventArgs e) {
moel@83
   521
      string report = computer.GetReport();
moel@83
   522
      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
moel@83
   523
        using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
moel@83
   524
          w.Write(report);
moel@83
   525
        }
moel@83
   526
      }
moel@1
   527
    }
moel@1
   528
moel@82
   529
    private void SysTrayHideShow() {
moel@82
   530
      Visible = !Visible;
moel@82
   531
      if (Visible)
moel@82
   532
        Activate();    
moel@27
   533
    }
moel@27
   534
moel@27
   535
    protected override void WndProc(ref Message m) {
moel@27
   536
      const int WM_SYSCOMMAND = 0x112;
moel@27
   537
      const int SC_MINIMIZE = 0xF020;
paulwerelds@198
   538
      const int SC_CLOSE = 0xF060;
paulwerelds@198
   539
moel@156
   540
      if (minimizeToTray.Value && 
moel@28
   541
        m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
moel@82
   542
        SysTrayHideShow();
paulwerelds@198
   543
      } else if(minimizeOnClose.Value && 
paulwerelds@198
   544
        m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
paulwerelds@198
   545
        /*
paulwerelds@198
   546
         * Apparently the user wants to minimize rather than close
paulwerelds@198
   547
         * Now we still need to check if we're going to the tray or not
paulwerelds@198
   548
         * 
paulwerelds@198
   549
         * Note: the correct way to do this would be to send out SC_MINIMIZE,
paulwerelds@198
   550
         * but since the code here is so simple,
paulwerelds@198
   551
         * that would just be a waste of time.
paulwerelds@198
   552
         */
paulwerelds@198
   553
        if (minimizeToTray.Value)
paulwerelds@198
   554
          SysTrayHideShow();
paulwerelds@198
   555
        else
paulwerelds@198
   556
          WindowState = FormWindowState.Minimized;
moel@27
   557
      } else {      
moel@27
   558
        base.WndProc(ref m);
moel@27
   559
      }
moel@27
   560
    }
moel@27
   561
moel@82
   562
    private void hideShowClick(object sender, EventArgs e) {
moel@82
   563
      SysTrayHideShow();
moel@27
   564
    }
moel@27
   565
moel@63
   566
    private void ShowParameterForm(ISensor sensor) {
moel@63
   567
      ParameterForm form = new ParameterForm();
moel@63
   568
      form.Parameters = sensor.Parameters;
moel@63
   569
      form.captionLabel.Text = sensor.Name;
moel@63
   570
      form.ShowDialog();
moel@63
   571
    }
moel@63
   572
moel@63
   573
    private void treeView_NodeMouseDoubleClick(object sender, 
moel@63
   574
      TreeNodeAdvMouseEventArgs e) {
moel@63
   575
      SensorNode node = e.Node.Tag as SensorNode;
moel@63
   576
      if (node != null && node.Sensor != null && 
moel@63
   577
        node.Sensor.Parameters.Length > 0) {
moel@63
   578
        ShowParameterForm(node.Sensor);
moel@63
   579
      }
moel@63
   580
    }
moel@82
   581
moel@156
   582
    private void celciusMenuItem_Click(object sender, EventArgs e) {
moel@156
   583
      celciusMenuItem.Checked = true;
moel@156
   584
      fahrenheitMenuItem.Checked = false;
moel@165
   585
      unitManager.TemperatureUnit = TemperatureUnit.Celcius;
moel@122
   586
    }
moel@122
   587
moel@156
   588
    private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
moel@156
   589
      celciusMenuItem.Checked = false;
moel@156
   590
      fahrenheitMenuItem.Checked = true;
moel@165
   591
      unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
moel@122
   592
    }
moel@150
   593
moel@156
   594
    private void sumbitReportMenuItem_Click(object sender, EventArgs e) 
moel@150
   595
    {
moel@150
   596
      ReportForm form = new ReportForm();
moel@150
   597
      form.Report = computer.GetReport();
moel@150
   598
      form.ShowDialog();      
moel@150
   599
    }
moel@151
   600
moel@151
   601
    private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
moel@159
   602
      computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
moel@159
   603
        sensor.ResetMin();
moel@159
   604
        sensor.ResetMax();
moel@159
   605
      }));
moel@151
   606
    }
moel@241
   607
moel@241
   608
    private void MainForm_MoveOrResize(object sender, EventArgs e) {
moel@241
   609
      if (WindowState != FormWindowState.Minimized) {
moel@241
   610
        settings.SetValue("mainForm.Location.X", Bounds.X);
moel@241
   611
        settings.SetValue("mainForm.Location.Y", Bounds.Y);
moel@241
   612
        settings.SetValue("mainForm.Width", Bounds.Width);
moel@241
   613
        settings.SetValue("mainForm.Height", Bounds.Height);
moel@241
   614
      }
moel@241
   615
    }
moel@262
   616
moel@262
   617
    private void resetClick(object sender, EventArgs e) {
moel@262
   618
      // disable the fallback MainIcon during reset, otherwise icon visibility
moel@262
   619
      // might be lost 
moel@262
   620
      systemTray.IsMainIconEnabled = false;
moel@262
   621
      computer.Close();
moel@262
   622
      computer.Open();
moel@262
   623
      // restore the MainIcon setting
moel@262
   624
      systemTray.IsMainIconEnabled = minimizeToTray.Value;
moel@262
   625
    }
moel@1
   626
  }
moel@1
   627
}