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