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