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