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