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