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