GUI/MainForm.cs
author StephaneLenclud
Wed, 17 Apr 2013 17:09:21 +0200
branchMiniDisplay
changeset 441 2a02ad86a776
parent 440 f43bab5fc81e
child 442 782b48689513
permissions -rw-r--r--
Adding FrontView menu with persistent options for time display and packed mode.
Adding support for editorconfig and rebracer.
     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 
   328       soundGraphDisplay.Init();
   329 
   330 
   331 
   332       startupMenuItem.Visible = startupManager.IsAvailable;
   333       
   334       if (startMinMenuItem.Checked) {
   335         if (!minTrayMenuItem.Checked) {
   336           WindowState = FormWindowState.Minimized;
   337           Show();
   338         }
   339       } else {
   340         Show();
   341       }
   342 
   343       // Create a handle, otherwise calling Close() does not fire FormClosed     
   344       IntPtr handle = Handle;
   345 
   346       // Make sure the settings are saved when the user logs off
   347       Microsoft.Win32.SystemEvents.SessionEnded += delegate {
   348         computer.Close();
   349         SaveConfiguration();
   350         if (runWebServer.Value) 
   351           server.Quit();
   352       };
   353     }
   354 
   355     private void InitializePlotForm() {
   356       plotForm = new Form();
   357       plotForm.FormBorderStyle = FormBorderStyle.SizableToolWindow;
   358       plotForm.ShowInTaskbar = false;
   359       plotForm.StartPosition = FormStartPosition.Manual;
   360       this.AddOwnedForm(plotForm);
   361       plotForm.Bounds = new Rectangle {
   362         X = settings.GetValue("plotForm.Location.X", -100000),
   363         Y = settings.GetValue("plotForm.Location.Y", 100),
   364         Width = settings.GetValue("plotForm.Width", 600),
   365         Height = settings.GetValue("plotForm.Height", 400)
   366       };
   367 
   368       showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
   369       plotLocation = new UserRadioGroup("plotLocation", 0,
   370         new[] { plotWindowMenuItem, plotBottomMenuItem, plotRightMenuItem },
   371         settings);
   372 
   373       showPlot.Changed += delegate(object sender, EventArgs e) {
   374         if (plotLocation.Value == 0) {
   375           if (showPlot.Value && this.Visible)
   376             plotForm.Show();
   377           else
   378             plotForm.Hide();
   379         } else {
   380           splitContainer.Panel2Collapsed = !showPlot.Value;
   381         }
   382         treeView.Invalidate();
   383       };
   384       plotLocation.Changed += delegate(object sender, EventArgs e) {
   385         switch (plotLocation.Value) {
   386           case 0:
   387             splitContainer.Panel2.Controls.Clear();
   388             splitContainer.Panel2Collapsed = true;
   389             plotForm.Controls.Add(plotPanel);
   390             if (showPlot.Value && this.Visible)
   391               plotForm.Show();
   392             break;
   393           case 1:
   394             plotForm.Controls.Clear();
   395             plotForm.Hide();
   396             splitContainer.Orientation = Orientation.Horizontal;
   397             splitContainer.Panel2.Controls.Add(plotPanel);
   398             splitContainer.Panel2Collapsed = !showPlot.Value;
   399             break;
   400           case 2:
   401             plotForm.Controls.Clear();
   402             plotForm.Hide();
   403             splitContainer.Orientation = Orientation.Vertical;
   404             splitContainer.Panel2.Controls.Add(plotPanel);
   405             splitContainer.Panel2Collapsed = !showPlot.Value;
   406             break;
   407         }
   408       };
   409 
   410       plotForm.FormClosing += delegate(object sender, FormClosingEventArgs e) {
   411         if (e.CloseReason == CloseReason.UserClosing) {
   412           // just switch off the plotting when the user closes the form
   413           if (plotLocation.Value == 0) {
   414             showPlot.Value = false;
   415           }
   416           e.Cancel = true;
   417         }
   418       };
   419 
   420       EventHandler moveOrResizePlotForm = delegate(object sender, EventArgs e) {
   421         if (plotForm.WindowState != FormWindowState.Minimized) {
   422           settings.SetValue("plotForm.Location.X", plotForm.Bounds.X);
   423           settings.SetValue("plotForm.Location.Y", plotForm.Bounds.Y);
   424           settings.SetValue("plotForm.Width", plotForm.Bounds.Width);
   425           settings.SetValue("plotForm.Height", plotForm.Bounds.Height);
   426         }
   427       };
   428       plotForm.Move += moveOrResizePlotForm;
   429       plotForm.Resize += moveOrResizePlotForm;
   430 
   431       plotForm.VisibleChanged += delegate(object sender, EventArgs e) {
   432         Rectangle bounds = new Rectangle(plotForm.Location, plotForm.Size);
   433         Screen screen = Screen.FromRectangle(bounds);
   434         Rectangle intersection =
   435           Rectangle.Intersect(screen.WorkingArea, bounds);
   436         if (intersection.Width < Math.Min(16, bounds.Width) ||
   437             intersection.Height < Math.Min(16, bounds.Height)) {
   438           plotForm.Location = new Point(
   439             screen.WorkingArea.Width / 2 - bounds.Width / 2,
   440             screen.WorkingArea.Height / 2 - bounds.Height / 2);
   441         }
   442       };
   443 
   444       this.VisibleChanged += delegate(object sender, EventArgs e) {
   445         if (this.Visible && showPlot.Value && plotLocation.Value == 0)
   446           plotForm.Show();
   447         else
   448           plotForm.Hide();
   449       };
   450     }
   451 
   452     private void InsertSorted(Collection<Node> nodes, HardwareNode node) {
   453       int i = 0;
   454       while (i < nodes.Count && nodes[i] is HardwareNode &&
   455         ((HardwareNode)nodes[i]).Hardware.HardwareType < 
   456           node.Hardware.HardwareType)
   457         i++;
   458       nodes.Insert(i, node);
   459     }
   460     
   461     private void SubHardwareAdded(IHardware hardware, Node node) {
   462       HardwareNode hardwareNode = 
   463         new HardwareNode(hardware, settings, unitManager);
   464       hardwareNode.PlotSelectionChanged += PlotSelectionChanged;
   465 
   466       InsertSorted(node.Nodes, hardwareNode);
   467 
   468       foreach (IHardware subHardware in hardware.SubHardware)
   469         SubHardwareAdded(subHardware, hardwareNode);  
   470     }
   471 
   472     private void HardwareAdded(IHardware hardware) {      
   473       SubHardwareAdded(hardware, root);
   474       PlotSelectionChanged(this, null);
   475     }
   476 
   477     private void HardwareRemoved(IHardware hardware) {
   478       List<HardwareNode> nodesToRemove = new List<HardwareNode>();
   479       foreach (Node node in root.Nodes) {
   480         HardwareNode hardwareNode = node as HardwareNode;
   481         if (hardwareNode != null && hardwareNode.Hardware == hardware)
   482           nodesToRemove.Add(hardwareNode);
   483       }
   484       foreach (HardwareNode hardwareNode in nodesToRemove) {
   485         root.Nodes.Remove(hardwareNode);
   486         hardwareNode.PlotSelectionChanged -= PlotSelectionChanged;
   487       }
   488       PlotSelectionChanged(this, null);
   489     }
   490 
   491     private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {       
   492       Node node = e.Node.Tag as Node;
   493       if (node != null) {
   494         Color color;
   495         if (node.IsVisible) {
   496           SensorNode sensorNode = node as SensorNode;
   497           if (plotMenuItem.Checked && sensorNode != null &&
   498             sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
   499             e.TextColor = color;
   500 
   501           //If displayed in FrontView draw background in green
   502           if (sensorNode != null && settings.GetValue(new Identifier(sensorNode.Sensor.Identifier, "FrontView").ToString(), false))
   503           {
   504               SolidBrush greenBrush = new SolidBrush(Color.FromName("mediumspringgreen"));
   505               e.BackgroundBrush = greenBrush;
   506           }
   507         } else {
   508 
   509           e.TextColor = Color.DarkGray;
   510         }
   511       }
   512     }
   513 
   514     private void PlotSelectionChanged(object sender, EventArgs e) {
   515       List<ISensor> selected = new List<ISensor>();
   516       IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
   517       int colorIndex = 0;
   518       foreach (TreeNodeAdv node in treeView.AllNodes) {
   519         SensorNode sensorNode = node.Tag as SensorNode;
   520         if (sensorNode != null) {
   521           if (sensorNode.Plot) {
   522             colors.Add(sensorNode.Sensor,
   523               plotColorPalette[colorIndex % plotColorPalette.Length]);
   524             selected.Add(sensorNode.Sensor);
   525           }
   526           colorIndex++;
   527         }
   528       }
   529       sensorPlotColors = colors;
   530       plotPanel.SetSensors(selected, colors);
   531     }
   532 
   533     private void nodeTextBoxText_EditorShowing(object sender,
   534       CancelEventArgs e) 
   535     {
   536       e.Cancel = !(treeView.CurrentNode != null &&
   537         (treeView.CurrentNode.Tag is SensorNode || 
   538          treeView.CurrentNode.Tag is HardwareNode));
   539     }
   540 
   541     private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
   542       NodeControlValueEventArgs e) {
   543       SensorNode node = e.Node.Tag as SensorNode;
   544       e.Value = (node != null) && plotMenuItem.Checked;
   545     }
   546 
   547     private void exitClick(object sender, EventArgs e) {
   548       Close();
   549     }
   550 
   551     private int delayCount = 0;
   552     private void timer_Tick(object sender, EventArgs e) {
   553       computer.Accept(updateVisitor);
   554       treeView.Invalidate();
   555       plotPanel.InvalidatePlot();
   556       systemTray.Redraw();
   557       if (gadget != null)
   558         gadget.Redraw();
   559 
   560       if (wmiProvider != null)
   561         wmiProvider.Update();
   562 
   563       if (soundGraphDisplay != null)
   564       {
   565           soundGraphDisplay.Redraw();
   566           /*
   567           displayTick=!displayTick;
   568           if (displayTick)
   569           {
   570               soundGraphDisplay.SetText("       ---", "");
   571           }
   572           else
   573           {
   574               soundGraphDisplay.SetText("       -+-", "");
   575           }
   576           */
   577       }  
   578 
   579 
   580       if (logSensors != null && logSensors.Value && delayCount >= 4)
   581         logger.Log();
   582 
   583       if (delayCount < 4)
   584         delayCount++;
   585     }
   586 
   587     private void SaveConfiguration() {
   588       plotPanel.SetCurrentSettings();
   589       foreach (TreeColumn column in treeView.Columns)
   590         settings.SetValue("treeView.Columns." + column.Header + ".Width",
   591           column.Width);
   592 
   593       this.settings.SetValue("listenerPort", server.ListenerPort);
   594 
   595       string fileName = Path.ChangeExtension(
   596           System.Windows.Forms.Application.ExecutablePath, ".config");
   597       try {
   598         settings.Save(fileName);
   599       } catch (UnauthorizedAccessException) {
   600         MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
   601           "The current settings could not be saved.",
   602           "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
   603       } catch (IOException) {
   604         MessageBox.Show("The path '" + fileName + "' is not writeable. " +
   605           "The current settings could not be saved.",
   606           "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
   607       }
   608     }
   609 
   610     private void MainForm_Load(object sender, EventArgs e) {
   611       Rectangle newBounds = new Rectangle {
   612         X = settings.GetValue("mainForm.Location.X", Location.X),
   613         Y = settings.GetValue("mainForm.Location.Y", Location.Y),
   614         Width = settings.GetValue("mainForm.Width", 470),
   615         Height = settings.GetValue("mainForm.Height", 640)
   616       };
   617 
   618       Rectangle fullWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
   619         int.MinValue, int.MinValue);
   620 
   621       foreach (Screen screen in Screen.AllScreens)
   622         fullWorkingArea = Rectangle.Union(fullWorkingArea, screen.Bounds);
   623 
   624       Rectangle intersection = Rectangle.Intersect(fullWorkingArea, newBounds);
   625       if (intersection.Width < 20 || intersection.Height < 20 ||
   626         !settings.Contains("mainForm.Location.X")
   627       ) {
   628         newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) -
   629                       (newBounds.Width/2);
   630 
   631         newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) -
   632                       (newBounds.Height / 2);
   633       }
   634 
   635       this.Bounds = newBounds;
   636     }
   637     
   638     private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
   639       Visible = false;      
   640       systemTray.IsMainIconEnabled = false;
   641       timer.Enabled = false;            
   642       computer.Close();
   643       SaveConfiguration();
   644       if (runWebServer.Value)
   645           server.Quit();
   646       systemTray.Dispose();
   647       soundGraphDisplay.Dispose();
   648     }
   649 
   650     private void aboutMenuItem_Click(object sender, EventArgs e) {
   651       new AboutBox().ShowDialog();
   652     }
   653 
   654     private void treeView_Click(object sender, EventArgs e) {
   655 
   656       MouseEventArgs m = e as MouseEventArgs;
   657       if (m == null || m.Button != MouseButtons.Right)
   658         return;
   659 
   660       NodeControlInfo info = treeView.GetNodeControlInfoAt(
   661         new Point(m.X, m.Y)
   662       );
   663       treeView.SelectedNode = info.Node;
   664       if (info.Node != null) {
   665         SensorNode node = info.Node.Tag as SensorNode;
   666         if (node != null && node.Sensor != null) {
   667           treeContextMenu.MenuItems.Clear();
   668           if (node.Sensor.Parameters.Length > 0) {
   669             MenuItem item = new MenuItem("Parameters...");
   670             item.Click += delegate(object obj, EventArgs args) {
   671               ShowParameterForm(node.Sensor);
   672             };
   673             treeContextMenu.MenuItems.Add(item);
   674           }
   675           if (nodeTextBoxText.EditEnabled) {
   676             MenuItem item = new MenuItem("Rename");
   677             item.Click += delegate(object obj, EventArgs args) {
   678               nodeTextBoxText.BeginEdit();
   679             };
   680             treeContextMenu.MenuItems.Add(item);
   681           }
   682           if (node.IsVisible) {
   683             MenuItem item = new MenuItem("Hide");
   684             item.Click += delegate(object obj, EventArgs args) {
   685               node.IsVisible = false;
   686             };
   687             treeContextMenu.MenuItems.Add(item);
   688           } else {
   689             MenuItem item = new MenuItem("Unhide");
   690             item.Click += delegate(object obj, EventArgs args) {
   691               node.IsVisible = true;
   692             };
   693             treeContextMenu.MenuItems.Add(item);
   694           }
   695           treeContextMenu.MenuItems.Add(new MenuItem("-"));
   696           {
   697             MenuItem item = new MenuItem("Show in Tray");
   698             item.Checked = systemTray.Contains(node.Sensor);
   699             item.Click += delegate(object obj, EventArgs args) {
   700               if (item.Checked)
   701                 systemTray.Remove(node.Sensor);
   702               else
   703                 systemTray.Add(node.Sensor, true);
   704             };
   705             treeContextMenu.MenuItems.Add(item);
   706           }
   707           {
   708               MenuItem item = new MenuItem("Show in iMON FrontView");
   709               item.Checked = soundGraphDisplay.Contains(node.Sensor);
   710               item.Click += delegate(object obj, EventArgs args)
   711               {
   712                   if (item.Checked)
   713                       soundGraphDisplay.Remove(node.Sensor);
   714                   else
   715                       soundGraphDisplay.Add(node.Sensor, true);
   716               };
   717               treeContextMenu.MenuItems.Add(item);
   718           }
   719           if (gadget != null) {
   720             MenuItem item = new MenuItem("Show in Gadget");
   721             item.Checked = gadget.Contains(node.Sensor);
   722             item.Click += delegate(object obj, EventArgs args) {
   723               if (item.Checked) {
   724                 gadget.Remove(node.Sensor);
   725               } else {
   726                 gadget.Add(node.Sensor);
   727               }
   728             };
   729             treeContextMenu.MenuItems.Add(item);
   730           }
   731           if (node.Sensor.Control != null) {
   732             treeContextMenu.MenuItems.Add(new MenuItem("-"));
   733             IControl control = node.Sensor.Control;
   734             MenuItem controlItem = new MenuItem("Control");
   735             MenuItem defaultItem = new MenuItem("Default");
   736             defaultItem.Checked = control.ControlMode == ControlMode.Default;
   737             controlItem.MenuItems.Add(defaultItem);
   738             defaultItem.Click += delegate(object obj, EventArgs args) {
   739               control.SetDefault();
   740             };
   741             MenuItem manualItem = new MenuItem("Manual");
   742             controlItem.MenuItems.Add(manualItem);
   743             manualItem.Checked = control.ControlMode == ControlMode.Software;
   744             for (int i = 0; i <= 100; i += 5) {
   745               if (i <= control.MaxSoftwareValue &&
   746                   i >= control.MinSoftwareValue) {
   747                 MenuItem item = new MenuItem(i + " %");
   748                 item.RadioCheck = true;
   749                 manualItem.MenuItems.Add(item);
   750                 item.Checked = control.ControlMode == ControlMode.Software &&
   751                   Math.Round(control.SoftwareValue) == i;
   752                 int softwareValue = i;
   753                 item.Click += delegate(object obj, EventArgs args) {
   754                   control.SetSoftware(softwareValue);
   755                 };
   756               }
   757             }
   758             treeContextMenu.MenuItems.Add(controlItem);
   759           }
   760 
   761           treeContextMenu.Show(treeView, new Point(m.X, m.Y));
   762         }
   763 
   764         HardwareNode hardwareNode = info.Node.Tag as HardwareNode;
   765         if (hardwareNode != null && hardwareNode.Hardware != null) {
   766           treeContextMenu.MenuItems.Clear();
   767 
   768           if (nodeTextBoxText.EditEnabled) {
   769             MenuItem item = new MenuItem("Rename");
   770             item.Click += delegate(object obj, EventArgs args) {
   771               nodeTextBoxText.BeginEdit();
   772             };
   773             treeContextMenu.MenuItems.Add(item);
   774           }
   775 
   776           treeContextMenu.Show(treeView, new Point(m.X, m.Y));
   777         }
   778       }
   779     }
   780 
   781     private void saveReportMenuItem_Click(object sender, EventArgs e) {
   782       string report = computer.GetReport();
   783       if (saveFileDialog.ShowDialog() == DialogResult.OK) {
   784         using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
   785           w.Write(report);
   786         }
   787       }
   788     }
   789 
   790     private void SysTrayHideShow() {
   791       Visible = !Visible;
   792       if (Visible)
   793         Activate();    
   794     }
   795 
   796     protected override void WndProc(ref Message m) {
   797       const int WM_SYSCOMMAND = 0x112;
   798       const int SC_MINIMIZE = 0xF020;
   799       const int SC_CLOSE = 0xF060;
   800 
   801  
   802       if (minimizeToTray.Value &&
   803         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt64() == SC_MINIMIZE)
   804       {
   805           SysTrayHideShow();
   806       }
   807       else if (minimizeOnClose.Value &&
   808       m.Msg == WM_SYSCOMMAND && m.WParam.ToInt64() == SC_CLOSE)
   809       {
   810           /*
   811            * Apparently the user wants to minimize rather than close
   812            * Now we still need to check if we're going to the tray or not
   813            * 
   814            * Note: the correct way to do this would be to send out SC_MINIMIZE,
   815            * but since the code here is so simple,
   816            * that would just be a waste of time.
   817            */
   818           if (minimizeToTray.Value)
   819               SysTrayHideShow();
   820           else
   821               WindowState = FormWindowState.Minimized;
   822       }
   823       else
   824       {
   825           base.WndProc(ref m);
   826       }
   827     }
   828 
   829     private void hideShowClick(object sender, EventArgs e) {
   830       SysTrayHideShow();
   831     }
   832 
   833     private void ShowParameterForm(ISensor sensor) {
   834       ParameterForm form = new ParameterForm();
   835       form.Parameters = sensor.Parameters;
   836       form.captionLabel.Text = sensor.Name;
   837       form.ShowDialog();
   838     }
   839 
   840     private void treeView_NodeMouseDoubleClick(object sender, 
   841       TreeNodeAdvMouseEventArgs e) {
   842       SensorNode node = e.Node.Tag as SensorNode;
   843       if (node != null && node.Sensor != null && 
   844         node.Sensor.Parameters.Length > 0) {
   845         ShowParameterForm(node.Sensor);
   846       }
   847     }
   848 
   849     private void celsiusMenuItem_Click(object sender, EventArgs e) {
   850       celsiusMenuItem.Checked = true;
   851       fahrenheitMenuItem.Checked = false;
   852       unitManager.TemperatureUnit = TemperatureUnit.Celsius;
   853     }
   854 
   855     private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
   856       celsiusMenuItem.Checked = false;
   857       fahrenheitMenuItem.Checked = true;
   858       unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
   859     }
   860 
   861     private void sumbitReportMenuItem_Click(object sender, EventArgs e) 
   862     {
   863       ReportForm form = new ReportForm();
   864       form.Report = computer.GetReport();
   865       form.ShowDialog();      
   866     }
   867 
   868     private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
   869       computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
   870         sensor.ResetMin();
   871         sensor.ResetMax();
   872       }));
   873     }
   874 
   875     private void MainForm_MoveOrResize(object sender, EventArgs e) {
   876       if (WindowState != FormWindowState.Minimized) {
   877         settings.SetValue("mainForm.Location.X", Bounds.X);
   878         settings.SetValue("mainForm.Location.Y", Bounds.Y);
   879         settings.SetValue("mainForm.Width", Bounds.Width);
   880         settings.SetValue("mainForm.Height", Bounds.Height);
   881       }
   882     }
   883 
   884     private void resetClick(object sender, EventArgs e) {
   885       // disable the fallback MainIcon during reset, otherwise icon visibility
   886       // might be lost 
   887       systemTray.IsMainIconEnabled = false;
   888       computer.Close();
   889       computer.Open();
   890       // restore the MainIcon setting
   891       systemTray.IsMainIconEnabled = minimizeToTray.Value;
   892     }
   893 
   894     private void treeView_MouseMove(object sender, MouseEventArgs e) {
   895       selectionDragging = selectionDragging &
   896         (e.Button & (MouseButtons.Left | MouseButtons.Right)) > 0; 
   897 
   898       if (selectionDragging)
   899         treeView.SelectedNode = treeView.GetNodeAt(e.Location);     
   900     }
   901 
   902     private void treeView_MouseDown(object sender, MouseEventArgs e) {
   903       selectionDragging = true;
   904     }
   905 
   906     private void treeView_MouseUp(object sender, MouseEventArgs e) {
   907       selectionDragging = false;
   908     }
   909 
   910     private void serverPortMenuItem_Click(object sender, EventArgs e) {
   911       new PortForm(this).ShowDialog();
   912     }
   913 
   914     public HttpServer Server {
   915       get { return server; }
   916     }
   917 
   918   }
   919 }