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