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