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