GUI/MainForm.cs
author StephaneLenclud
Thu, 18 Apr 2013 23:25:10 +0200
branchMiniDisplay
changeset 444 9b09e2ee0968
parent 442 782b48689513
child 445 fe4c711fd7f8
permissions -rw-r--r--
Front View plug-in does not init if no sensor added.
Fixing some format to make strings shorter.
Now trying to start SoundGraphAccess.exe process from same directory.
Packed mode now can display three sensors along with the current time.
     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     private UserOption frontViewPacked; //Tells whether FrontView should cycle or pack sensors
    59     private UserOption frontViewDisplayTime; //Tells whether or not FrontView should display current time
    60 
    61     private UserOption readMainboardSensors;
    62     private UserOption readCpuSensors;
    63     private UserOption readRamSensors;
    64     private UserOption readGpuSensors;
    65     private UserOption readFanControllersSensors;
    66     private UserOption readHddSensors;
    67 
    68     private UserOption showGadget;
    69     private UserRadioGroup plotLocation;
    70     private WmiProvider wmiProvider;
    71 
    72     private UserOption runWebServer;
    73     private HttpServer server;
    74 
    75     private UserOption logSensors;
    76     private UserRadioGroup loggingInterval;
    77     private Logger logger;
    78 
    79     private bool selectionDragging = false;
    80 
    81     public MainForm() {      
    82       InitializeComponent();
    83 
    84       // check if the OpenHardwareMonitorLib assembly has the correct version
    85       if (Assembly.GetAssembly(typeof(Computer)).GetName().Version !=
    86         Assembly.GetExecutingAssembly().GetName().Version) {
    87         MessageBox.Show(
    88           "The version of the file OpenHardwareMonitorLib.dll is incompatible.",
    89           "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
    90         Environment.Exit(0);
    91       }
    92 
    93       this.settings = new PersistentSettings();      
    94       this.settings.Load(Path.ChangeExtension(
    95         Application.ExecutablePath, ".config"));
    96 
    97       this.unitManager = new UnitManager(settings);
    98 
    99       // make sure the buffers used for double buffering are not disposed 
   100       // after each draw call
   101       BufferedGraphicsManager.Current.MaximumBuffer =
   102         Screen.PrimaryScreen.Bounds.Size;  
   103 
   104       // set the DockStyle here, to avoid conflicts with the MainMenu
   105       this.splitContainer.Dock = DockStyle.Fill;
   106             
   107       this.Font = SystemFonts.MessageBoxFont;
   108       treeView.Font = SystemFonts.MessageBoxFont;
   109 
   110       plotPanel = new PlotPanel(settings, unitManager);
   111       plotPanel.Font = SystemFonts.MessageBoxFont;
   112       plotPanel.Dock = DockStyle.Fill;
   113       
   114       nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
   115       nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
   116       nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
   117       nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
   118       nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
   119       nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
   120 
   121       foreach (TreeColumn column in treeView.Columns) 
   122         column.Width = Math.Max(20, Math.Min(400,
   123           settings.GetValue("treeView.Columns." + column.Header + ".Width",
   124           column.Width)));
   125 
   126       treeModel = new TreeModel();
   127       root = new Node(System.Environment.MachineName);
   128       root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
   129       
   130       treeModel.Nodes.Add(root);
   131       treeView.Model = treeModel;
   132 
   133       this.computer = new Computer(settings);
   134 
   135       systemTray = new SystemTray(computer, settings, unitManager);
   136       systemTray.HideShowCommand += hideShowClick;
   137       systemTray.ExitCommand += exitClick;
   138   
   139       soundGraphDisplay = new SoundGraphDisplay(computer, settings, unitManager);
   140  
   141 
   142       int p = (int)Environment.OSVersion.Platform;
   143       if ((p == 4) || (p == 128)) { // Unix
   144         treeView.RowHeight = Math.Max(treeView.RowHeight, 18); 
   145         splitContainer.BorderStyle = BorderStyle.None;
   146         splitContainer.Border3DStyle = Border3DStyle.Adjust;
   147         splitContainer.SplitterWidth = 4;
   148         treeView.BorderStyle = BorderStyle.Fixed3D;
   149         plotPanel.BorderStyle = BorderStyle.Fixed3D;
   150         gadgetMenuItem.Visible = false;
   151         minCloseMenuItem.Visible = false;
   152         minTrayMenuItem.Visible = false;
   153         startMinMenuItem.Visible = false;
   154       } else { // Windows
   155         treeView.RowHeight = Math.Max(treeView.Font.Height + 1, 18); 
   156 
   157         gadget = new SensorGadget(computer, settings, unitManager);
   158         gadget.HideShowCommand += hideShowClick;
   159 
   160         wmiProvider = new WmiProvider(computer);
   161       }
   162 
   163       logger = new Logger(computer);
   164 
   165       plotColorPalette = new Color[13];
   166       plotColorPalette[0] = Color.Blue;
   167       plotColorPalette[1] = Color.OrangeRed;
   168       plotColorPalette[2] = Color.Green;
   169       plotColorPalette[3] = Color.LightSeaGreen;
   170       plotColorPalette[4] = Color.Goldenrod;
   171       plotColorPalette[5] = Color.DarkViolet;
   172       plotColorPalette[6] = Color.YellowGreen;
   173       plotColorPalette[7] = Color.SaddleBrown;
   174       plotColorPalette[8] = Color.RoyalBlue;
   175       plotColorPalette[9] = Color.DeepPink;
   176       plotColorPalette[10] = Color.MediumSeaGreen;
   177       plotColorPalette[11] = Color.Olive;
   178       plotColorPalette[12] = Color.Firebrick;
   179       
   180       computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
   181       computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);        
   182 
   183       computer.Open();
   184 
   185       timer.Enabled = true;
   186 
   187       showHiddenSensors = new UserOption("hiddenMenuItem", false,
   188         hiddenMenuItem, settings);
   189       showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
   190         treeModel.ForceVisible = showHiddenSensors.Value;
   191       };
   192 
   193       showValue = new UserOption("valueMenuItem", true, valueMenuItem,
   194         settings);
   195       showValue.Changed += delegate(object sender, EventArgs e) {
   196         treeView.Columns[1].IsVisible = showValue.Value;
   197       };
   198 
   199       showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
   200       showMin.Changed += delegate(object sender, EventArgs e) {
   201         treeView.Columns[2].IsVisible = showMin.Value;
   202       };
   203 
   204       showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
   205       showMax.Changed += delegate(object sender, EventArgs e) {
   206         treeView.Columns[3].IsVisible = showMax.Value;
   207       };
   208 
   209       startMinimized = new UserOption("startMinMenuItem", false,
   210         startMinMenuItem, settings);
   211 
   212       minimizeToTray = new UserOption("minTrayMenuItem", true,
   213         minTrayMenuItem, settings);
   214       minimizeToTray.Changed += delegate(object sender, EventArgs e) {
   215         systemTray.IsMainIconEnabled = minimizeToTray.Value;
   216       };
   217 
   218       minimizeOnClose = new UserOption("minCloseMenuItem", false,
   219         minCloseMenuItem, settings);
   220 
   221       autoStart = new UserOption(null, startupManager.Startup,
   222         startupMenuItem, settings);
   223       autoStart.Changed += delegate(object sender, EventArgs e) {
   224         try {
   225           startupManager.Startup = autoStart.Value;
   226         } catch (InvalidOperationException) {
   227           MessageBox.Show("Updating the auto-startup option failed.", "Error", 
   228             MessageBoxButtons.OK, MessageBoxIcon.Error);
   229           autoStart.Value = startupManager.Startup;
   230         }
   231       };
   232 
   233       frontViewPacked = new UserOption("frontViewPackedMenuItem", false, frontViewPackedMenuItem, settings);
   234       frontViewDisplayTime = new UserOption("frontViewDisplayTimeMenuItem", false, frontViewDisplayTimeMenuItem, settings);
   235 
   236       readMainboardSensors = new UserOption("mainboardMenuItem", true, 
   237         mainboardMenuItem, settings);
   238       readMainboardSensors.Changed += delegate(object sender, EventArgs e) {
   239         computer.MainboardEnabled = readMainboardSensors.Value;
   240       };
   241 
   242       readCpuSensors = new UserOption("cpuMenuItem", true,
   243         cpuMenuItem, settings);
   244       readCpuSensors.Changed += delegate(object sender, EventArgs e) {
   245         computer.CPUEnabled = readCpuSensors.Value;
   246       };
   247 
   248       readRamSensors = new UserOption("ramMenuItem", true,
   249         ramMenuItem, settings);
   250       readRamSensors.Changed += delegate(object sender, EventArgs e) {
   251         computer.RAMEnabled = readRamSensors.Value;
   252       };
   253 
   254       readGpuSensors = new UserOption("gpuMenuItem", true,
   255         gpuMenuItem, settings);
   256       readGpuSensors.Changed += delegate(object sender, EventArgs e) {
   257         computer.GPUEnabled = readGpuSensors.Value;
   258       };
   259 
   260       readFanControllersSensors = new UserOption("fanControllerMenuItem", true,
   261         fanControllerMenuItem, settings);
   262       readFanControllersSensors.Changed += delegate(object sender, EventArgs e) {
   263         computer.FanControllerEnabled = readFanControllersSensors.Value;
   264       };
   265 
   266       readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem,
   267         settings);
   268       readHddSensors.Changed += delegate(object sender, EventArgs e) {
   269         computer.HDDEnabled = readHddSensors.Value;
   270       };
   271 
   272       showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem,
   273         settings);
   274       showGadget.Changed += delegate(object sender, EventArgs e) {
   275         if (gadget != null) 
   276           gadget.Visible = showGadget.Value;
   277       };
   278 
   279       celsiusMenuItem.Checked = 
   280         unitManager.TemperatureUnit == TemperatureUnit.Celsius;
   281       fahrenheitMenuItem.Checked = !celsiusMenuItem.Checked;
   282 
   283       server = new HttpServer(root, this.settings.GetValue("listenerPort", 8085));
   284       if (server.PlatformNotSupported) {
   285         webMenuItemSeparator.Visible = false;
   286         webMenuItem.Visible = false;
   287       }
   288 
   289       runWebServer = new UserOption("runWebServerMenuItem", false,
   290         runWebServerMenuItem, settings);
   291       runWebServer.Changed += delegate(object sender, EventArgs e) {
   292         if (runWebServer.Value)
   293           server.StartHTTPListener();
   294         else
   295           server.StopHTTPListener();
   296       };
   297 
   298       logSensors = new UserOption("logSensorsMenuItem", false, logSensorsMenuItem,
   299         settings);
   300 
   301       loggingInterval = new UserRadioGroup("loggingInterval", 0,
   302         new[] { log1sMenuItem, log2sMenuItem, log5sMenuItem, log10sMenuItem,
   303         log30sMenuItem, log1minMenuItem, log2minMenuItem, log5minMenuItem, 
   304         log10minMenuItem, log30minMenuItem, log1hMenuItem, log2hMenuItem, 
   305         log6hMenuItem},
   306         settings);
   307       loggingInterval.Changed += (sender, e) => {
   308         switch (loggingInterval.Value) {
   309           case 0: logger.LoggingInterval = new TimeSpan(0, 0, 1); break;
   310           case 1: logger.LoggingInterval = new TimeSpan(0, 0, 2); break;
   311           case 2: logger.LoggingInterval = new TimeSpan(0, 0, 5); break;
   312           case 3: logger.LoggingInterval = new TimeSpan(0, 0, 10); break;
   313           case 4: logger.LoggingInterval = new TimeSpan(0, 0, 30); break;
   314           case 5: logger.LoggingInterval = new TimeSpan(0, 1, 0); break;
   315           case 6: logger.LoggingInterval = new TimeSpan(0, 2, 0); break;
   316           case 7: logger.LoggingInterval = new TimeSpan(0, 5, 0); break;
   317           case 8: logger.LoggingInterval = new TimeSpan(0, 10, 0); break;
   318           case 9: logger.LoggingInterval = new TimeSpan(0, 30, 0); break;
   319           case 10: logger.LoggingInterval = new TimeSpan(1, 0, 0); break;
   320           case 11: logger.LoggingInterval = new TimeSpan(2, 0, 0); break;
   321           case 12: logger.LoggingInterval = new TimeSpan(6, 0, 0); break;
   322         }
   323       };
   324 
   325       InitializePlotForm();
   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(frontViewPacked.Value,frontViewDisplayTime.Value);
   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 }