Fixed Issue 43.
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
     5   The contents of this file are subject to the Mozilla Public License Version
 
     6   1.1 (the "License"); you may not use this file except in compliance with
 
     7   the License. You may obtain a copy of the License at
 
     9   http://www.mozilla.org/MPL/
 
    11   Software distributed under the License is distributed on an "AS IS" basis,
 
    12   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
    13   for the specific language governing rights and limitations under the License.
 
    15   The Original Code is the Open Hardware Monitor code.
 
    17   The Initial Developer of the Original Code is 
 
    18   Michael Möller <m.moeller@gmx.ch>.
 
    19   Portions created by the Initial Developer are Copyright (C) 2009-2010
 
    20   the Initial Developer. All Rights Reserved.
 
    24   Alternatively, the contents of this file may be used under the terms of
 
    25   either the GNU General Public License Version 2 or later (the "GPL"), or
 
    26   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
    27   in which case the provisions of the GPL or the LGPL are applicable instead
 
    28   of those above. If you wish to allow use of your version of this file only
 
    29   under the terms of either the GPL or the LGPL, and not to allow others to
 
    30   use your version of this file under the terms of the MPL, indicate your
 
    31   decision by deleting the provisions above and replace them with the notice
 
    32   and other provisions required by the GPL or the LGPL. If you do not delete
 
    33   the provisions above, a recipient may use your version of this file under
 
    34   the terms of any one of the MPL, the GPL or the LGPL.
 
    39 using System.Collections.Generic;
 
    40 using System.ComponentModel;
 
    41 using System.Configuration;
 
    45 using System.Windows.Forms;
 
    46 using Aga.Controls.Tree;
 
    47 using Aga.Controls.Tree.NodeControls;
 
    48 using OpenHardwareMonitor.Hardware;
 
    49 using OpenHardwareMonitor.Utilities;
 
    51 namespace OpenHardwareMonitor.GUI {
 
    52   public partial class MainForm : Form {
 
    54     private Computer computer = new Computer();
 
    56     private TreeModel treeModel;
 
    57     private IDictionary<ISensor, Color> sensorPlotColors = 
 
    58       new Dictionary<ISensor, Color>();
 
    59     private Color[] plotColorPalette;
 
    60     private SensorSystemTray sensorSystemTray;
 
    61     private NotifyIcon notifyIcon;
 
    62     private StartupManager startupManager = new StartupManager();
 
    65       InitializeComponent();
 
    66       this.Font = SystemFonts.MessageBoxFont;
 
    67       treeView.Font = SystemFonts.MessageBoxFont;
 
    68       plotPanel.Font = SystemFonts.MessageBoxFont;
 
    70       nodeCheckBox.IsVisibleValueNeeded += 
 
    71         new EventHandler<NodeControlValueEventArgs>(
 
    72           nodeCheckBox_IsVisibleValueNeeded);
 
    73       nodeCheckBox.CheckStateChanged += 
 
    74         new EventHandler<TreePathEventArgs>(UpdatePlotSelection);
 
    75       nodeTextBoxText.DrawText += 
 
    76         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
 
    77       nodeTextBoxValue.DrawText +=
 
    78         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
 
    79       nodeTextBoxMin.DrawText +=
 
    80         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
 
    81       nodeTextBoxMax.DrawText +=
 
    82         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
 
    83       nodeTextBoxLimit.DrawText += 
 
    84         new EventHandler<DrawEventArgs>(nodeTextBoxLimit_DrawText);
 
    86       if (Utilities.Config.Contains("mainForm.Location.X")) {
 
    87         int x = Utilities.Config.Get("mainForm.Location.X", Location.X);
 
    89         int y = Utilities.Config.Get("mainForm.Location.Y", Location.Y);
 
    91         this.Location = new Point(x, y);
 
    93         StartPosition = FormStartPosition.CenterScreen;
 
    96       Width = Utilities.Config.Get("mainForm.Width", Width);
 
    97       Height = Utilities.Config.Get("mainForm.Height", Height);
 
    99       treeModel = new TreeModel();
 
   100       root = new Node(System.Environment.MachineName);
 
   101       root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
 
   103       treeModel.Nodes.Add(root);
 
   104       treeView.Model = treeModel;
 
   106       notifyIcon = new NotifyIcon();
 
   107       notifyIcon.ContextMenuStrip = this.notifyContextMenuStrip;
 
   108       notifyIcon.Icon = EmbeddedResources.GetIcon("smallicon.ico");
 
   109       notifyIcon.Text = "Open Hardware Monitor";      
 
   110       notifyIcon.DoubleClick += new EventHandler(this.hideShowClick);
 
   112       sensorSystemTray = new SensorSystemTray(computer);
 
   114       computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
 
   115       computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
 
   118       timer.Enabled = true;
 
   120       plotColorPalette = new Color[14];
 
   121       plotColorPalette[0] = Color.Blue;
 
   122       plotColorPalette[1] = Color.OrangeRed;
 
   123       plotColorPalette[2] = Color.Green;
 
   124       plotColorPalette[3] = Color.LightSeaGreen;
 
   125       plotColorPalette[4] = Color.Goldenrod;
 
   126       plotColorPalette[5] = Color.DarkViolet;
 
   127       plotColorPalette[6] = Color.YellowGreen;
 
   128       plotColorPalette[7] = Color.SaddleBrown;
 
   129       plotColorPalette[8] = Color.Gray;
 
   130       plotColorPalette[9] = Color.RoyalBlue;
 
   131       plotColorPalette[10] = Color.DeepPink;
 
   132       plotColorPalette[11] = Color.MediumSeaGreen;
 
   133       plotColorPalette[12] = Color.Olive;
 
   134       plotColorPalette[13] = Color.Firebrick;
 
   136       plotMenuItem.Checked = Config.Get(plotMenuItem.Name, false);
 
   137       minMenuItem.Checked = Config.Get(minMenuItem.Name, false);
 
   138       maxMenuItem.Checked = Config.Get(maxMenuItem.Name, true);
 
   139       limitMenuItem.Checked = Config.Get(limitMenuItem.Name, false);
 
   141       startMinMenuItem.Checked = Config.Get(startMinMenuItem.Name, false); 
 
   142       minTrayMenuItem.Checked = Config.Get(minTrayMenuItem.Name, true);
 
   143       startupMenuItem.Checked = startupManager.Startup;
 
   144       hddMenuItem.Checked = Config.Get(hddMenuItem.Name, true);
 
   146       voltMenuItem.Checked = Config.Get(voltMenuItem.Name, true);
 
   147       clocksMenuItem.Checked = Config.Get(clocksMenuItem.Name, true);
 
   148       loadMenuItem.Checked = Config.Get(loadMenuItem.Name, true);
 
   149       tempMenuItem.Checked = Config.Get(tempMenuItem.Name, true);
 
   150       fansMenuItem.Checked = Config.Get(fansMenuItem.Name, true);
 
   151       flowsMenuItem.Checked = Config.Get(flowsMenuItem.Name, true);    
 
   153       if (startMinMenuItem.Checked) {
 
   154         if (!minTrayMenuItem.Checked) {
 
   155           WindowState = FormWindowState.Minimized;
 
   162       // Create a handle, otherwise calling Close() does not fire FormClosed     
 
   163       IntPtr handle = Handle;
 
   166     private void SubHardwareAdded(IHardware hardware, Node node) {
 
   167       Node hardwareNode = new HardwareNode(hardware);
 
   168       node.Nodes.Add(hardwareNode);
 
   169       foreach (IHardware subHardware in hardware.SubHardware)
 
   170         SubHardwareAdded(subHardware, hardwareNode);  
 
   173     private void HardwareAdded(IHardware hardware) {
 
   174       Node hardwareNode = new HardwareNode(hardware);
 
   175       root.Nodes.Add(hardwareNode);
 
   176       foreach (IHardware subHardware in hardware.SubHardware)
 
   177         SubHardwareAdded(subHardware, hardwareNode);     
 
   180     private void HardwareRemoved(IHardware hardware) {      
 
   181       List<Node> nodesToRemove = new List<Node>();
 
   182       foreach (Node node in root.Nodes) {
 
   183         HardwareNode hardwareNode = node as HardwareNode;
 
   184         if (hardwareNode != null && hardwareNode.Hardware == hardware)
 
   185           nodesToRemove.Add(node);
 
   187       foreach (Node node in nodesToRemove)
 
   188         root.Nodes.Remove(node);
 
   191     private void nodeTextBoxLimit_DrawText(object sender, DrawEventArgs e) {
 
   192       SensorNode sensorNode = e.Node.Tag as SensorNode;
 
   193       if (sensorNode != null) 
 
   194         e.Text = sensorNode.ValueToString(sensorNode.Sensor.Limit);
 
   197     private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
 
   198       if (!plotMenuItem.Checked)
 
   201       SensorNode sensorNode = e.Node.Tag as SensorNode;
 
   202       if (sensorNode != null) {
 
   204         if (sensorPlotColors.TryGetValue(sensorNode.Sensor, out color)) 
 
   209     private void UpdatePlotSelection(object sender, 
 
   212       List<ISensor> selected = new List<ISensor>();
 
   213       IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
 
   215       foreach (TreeNodeAdv node in treeView.AllNodes) {
 
   216         SensorNode sensorNode = node.Tag as SensorNode;
 
   217         if (sensorNode != null && 
 
   218           sensorNode.Sensor.SensorType == SensorType.Temperature) {
 
   219           if (sensorNode.Plot) {
 
   220             colors.Add(sensorNode.Sensor,
 
   221               plotColorPalette[colorIndex % plotColorPalette.Length]);
 
   222             selected.Add(sensorNode.Sensor);
 
   227       sensorPlotColors = colors;
 
   228       plotPanel.SetSensors(selected, colors);
 
   231     private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
 
   232       NodeControlValueEventArgs e) {
 
   233       SensorNode node = e.Node.Tag as SensorNode;
 
   234       e.Value = (node != null) && 
 
   235         (node.Sensor.SensorType == SensorType.Temperature) && 
 
   236         plotMenuItem.Checked;
 
   239     private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
 
   243     private void timer_Tick(object sender, EventArgs e) {
 
   245       treeView.Invalidate();
 
   246       plotPanel.Invalidate();
 
   247       sensorSystemTray.Redraw();
 
   250     private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
 
   252       Config.Set(plotMenuItem.Name, plotMenuItem.Checked);
 
   253       Config.Set(minMenuItem.Name, minMenuItem.Checked);
 
   254       Config.Set(maxMenuItem.Name, maxMenuItem.Checked);
 
   255       Config.Set(limitMenuItem.Name, limitMenuItem.Checked);
 
   257       Config.Set(startMinMenuItem.Name, startMinMenuItem.Checked);
 
   258       Config.Set(minTrayMenuItem.Name, minTrayMenuItem.Checked);
 
   259       Config.Set(hddMenuItem.Name, hddMenuItem.Checked);
 
   261       Config.Set(voltMenuItem.Name, voltMenuItem.Checked);
 
   262       Config.Set(clocksMenuItem.Name, clocksMenuItem.Checked);
 
   263       Config.Set(loadMenuItem.Name, loadMenuItem.Checked);
 
   264       Config.Set(tempMenuItem.Name, tempMenuItem.Checked);
 
   265       Config.Set(fansMenuItem.Name, fansMenuItem.Checked);
 
   266       Config.Set(flowsMenuItem.Name, flowsMenuItem.Checked);      
 
   268       if (WindowState != FormWindowState.Minimized) {
 
   269         Config.Set("mainForm.Location.X", Location.X);
 
   270         Config.Set("mainForm.Location.Y", Location.Y);
 
   271         Config.Set("mainForm.Width", Width);
 
   272         Config.Set("mainForm.Height", Height);
 
   275       timer.Enabled = false;
 
   277       sensorSystemTray.Dispose();
 
   278       notifyIcon.Dispose();
 
   282     private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
 
   283       new AboutBox().ShowDialog();
 
   286     private void plotToolStripMenuItem_CheckedChanged(object sender, 
 
   289       splitContainer.Panel2Collapsed = !plotMenuItem.Checked;
 
   290       treeView.Invalidate();
 
   293     private void valueToolStripMenuItem_CheckedChanged(object sender, 
 
   296       treeView.Columns[1].IsVisible = valueToolStripMenuItem.Checked;
 
   299     private void minToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
 
   301       treeView.Columns[2].IsVisible = minMenuItem.Checked;
 
   304     private void maxToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
 
   306       treeView.Columns[3].IsVisible = maxMenuItem.Checked;
 
   309     private void limitToolStripMenuItem_CheckedChanged(object sender, 
 
   311       treeView.Columns[4].IsVisible = limitMenuItem.Checked;
 
   314     private void treeView_Click(object sender, EventArgs e) {
 
   316       MouseEventArgs m = e as MouseEventArgs;
 
   317       if (m == null || m.Button != MouseButtons.Right)
 
   320       NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
 
   321       if (info.Control == null) {
 
   322         columnsContextMenuStrip.Show(treeView, m.X, m.Y);
 
   324         SensorNode node = info.Node.Tag as SensorNode;
 
   325         if (node != null && node.Sensor != null) {
 
   327           sensorContextMenuStrip.Items.Clear();
 
   328           if (node.Sensor.Parameters.Length > 0) {
 
   329             ToolStripMenuItem item = new ToolStripMenuItem("Parameters...");
 
   330             item.Click += delegate(object obj, EventArgs args) {
 
   331               ShowParameterForm(node.Sensor);
 
   333             sensorContextMenuStrip.Items.Add(item);
 
   335           if (sensorSystemTray.Contains(node.Sensor)) {
 
   336             ToolStripMenuItem item = new ToolStripMenuItem("Remove From Tray");
 
   337             item.Click += delegate(object obj, EventArgs args) {
 
   338               sensorSystemTray.Remove(node.Sensor);
 
   340             sensorContextMenuStrip.Items.Add(item);
 
   342             ToolStripMenuItem item = new ToolStripMenuItem("Add To Tray");
 
   343             item.Click += delegate(object obj, EventArgs args) {
 
   344               sensorSystemTray.Add(node.Sensor, true);
 
   346             sensorContextMenuStrip.Items.Add(item);
 
   348           sensorContextMenuStrip.Show(treeView, m.X, m.Y);
 
   353     private void saveReportToolStripMenuItem_Click(object sender, EventArgs e) {
 
   354       string report = computer.GetReport();
 
   355       if (saveFileDialog.ShowDialog() == DialogResult.OK) {
 
   356         using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
 
   362     private void hddsensorsToolStripMenuItem_CheckedChanged(object sender, 
 
   365       computer.HDDEnabled = hddMenuItem.Checked;
 
   366       UpdateSensorTypeChecked(null, null);
 
   367       UpdatePlotSelection(null, null);      
 
   370     private void UpdateSensorTypeVisible(Node node) {
 
   371       HardwareNode hardwareNode = node as HardwareNode;
 
   372       if (hardwareNode == null)
 
   375       hardwareNode.SetVisible(SensorType.Voltage, voltMenuItem.Checked);
 
   376       hardwareNode.SetVisible(SensorType.Clock, clocksMenuItem.Checked);
 
   377       hardwareNode.SetVisible(SensorType.Load, loadMenuItem.Checked);
 
   378       hardwareNode.SetVisible(SensorType.Temperature, tempMenuItem.Checked);
 
   379       hardwareNode.SetVisible(SensorType.Fan, fansMenuItem.Checked);
 
   380       hardwareNode.SetVisible(SensorType.Flow, flowsMenuItem.Checked);
 
   382       foreach (Node n in node.Nodes)
 
   383         UpdateSensorTypeVisible(n);
 
   386     private void UpdateSensorTypeChecked(object sender, EventArgs e) {          
 
   387       foreach (HardwareNode node in root.Nodes) 
 
   388         UpdateSensorTypeVisible(node);
 
   391     private void SysTrayHideShow() {
 
   397     protected override void WndProc(ref Message m) {
 
   398       const int WM_SYSCOMMAND = 0x112;
 
   399       const int SC_MINIMIZE = 0xF020;
 
   400       if (minTrayMenuItem.Checked && 
 
   401         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
 
   408     private void hideShowClick(object sender, EventArgs e) {
 
   412     private void removeToolStripMenuItem_Click(object sender, EventArgs e) {
 
   413       ToolStripMenuItem item = sender as ToolStripMenuItem;
 
   417       ISensor sensor = item.Owner.Tag as ISensor;
 
   421       sensorSystemTray.Remove(sensor);
 
   424     private void ShowParameterForm(ISensor sensor) {
 
   425       ParameterForm form = new ParameterForm();
 
   426       form.Parameters = sensor.Parameters;
 
   427       form.captionLabel.Text = sensor.Name;
 
   431     private void treeView_NodeMouseDoubleClick(object sender, 
 
   432       TreeNodeAdvMouseEventArgs e) {
 
   433       SensorNode node = e.Node.Tag as SensorNode;
 
   434       if (node != null && node.Sensor != null && 
 
   435         node.Sensor.Parameters.Length > 0) {
 
   436         ShowParameterForm(node.Sensor);
 
   440     private void runOnWindowsStartupToolStripMenuItem_CheckedChanged(
 
   441       object sender, EventArgs e) 
 
   443       startupManager.Startup = startupMenuItem.Checked;
 
   446     private void minTrayMenuItem_CheckedChanged(object sender, EventArgs e) {
 
   447       notifyIcon.Visible = minTrayMenuItem.Checked;