GUI/MainForm.cs
author moel.mich
Tue, 25 May 2010 18:57:28 +0000
changeset 127 76aaf45a01c7
parent 125 b1278888d9a9
child 128 cea5477b4d72
permissions -rw-r--r--
Added a workaround for the "You must keep the stream open for the lifetime of the Image." problem of the Image.FromStream method. This also reduced the overall memory usage (private working set).
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     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
     8  
     9   http://www.mozilla.org/MPL/
    10 
    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.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    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.
    21 
    22   Contributor(s):
    23 
    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.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.ComponentModel;
    41 using System.Configuration;
    42 using System.Drawing;
    43 using System.IO;
    44 using System.Text;
    45 using System.Windows.Forms;
    46 using Aga.Controls.Tree;
    47 using Aga.Controls.Tree.NodeControls;
    48 using OpenHardwareMonitor.Hardware;
    49 using OpenHardwareMonitor.Utilities;
    50 
    51 namespace OpenHardwareMonitor.GUI {
    52   public partial class MainForm : Form {
    53 
    54     private Computer computer = new Computer();
    55     private Node root;
    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();
    63     private UpdateVisitor updateVisitor = new UpdateVisitor();
    64 
    65     public MainForm() {      
    66       InitializeComponent();
    67       this.Font = SystemFonts.MessageBoxFont;
    68       treeView.Font = SystemFonts.MessageBoxFont;
    69       plotPanel.Font = SystemFonts.MessageBoxFont;
    70       
    71       nodeCheckBox.IsVisibleValueNeeded += 
    72         new EventHandler<NodeControlValueEventArgs>(
    73           nodeCheckBox_IsVisibleValueNeeded);
    74       nodeCheckBox.CheckStateChanged += 
    75         new EventHandler<TreePathEventArgs>(UpdatePlotSelection);
    76       nodeTextBoxText.DrawText += 
    77         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
    78       nodeTextBoxValue.DrawText +=
    79         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
    80       nodeTextBoxMin.DrawText +=
    81         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
    82       nodeTextBoxMax.DrawText +=
    83         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
    84       nodeTextBoxLimit.DrawText += 
    85         new EventHandler<DrawEventArgs>(nodeTextBoxLimit_DrawText);
    86 
    87       if (Utilities.Config.Contains("mainForm.Location.X")) {
    88         int x = Utilities.Config.Get("mainForm.Location.X", Location.X);
    89         x = x < 0 ? 0 : x;
    90         int y = Utilities.Config.Get("mainForm.Location.Y", Location.Y);
    91         y = y < 0 ? 0 : y;
    92         this.Location = new Point(x, y);
    93       } else {
    94         StartPosition = FormStartPosition.CenterScreen;
    95       }
    96 
    97       Width = Utilities.Config.Get("mainForm.Width", Width);
    98       Height = Utilities.Config.Get("mainForm.Height", Height);
    99 
   100       foreach (TreeColumn column in treeView.Columns) 
   101         column.Width = Math.Max(20, Math.Min(400, 
   102           Config.Get("treeView.Columns." + column.Header + ".Width",
   103           column.Width)));
   104 
   105       treeModel = new TreeModel();
   106       root = new Node(System.Environment.MachineName);
   107       root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
   108       
   109       treeModel.Nodes.Add(root);
   110       treeView.Model = treeModel;
   111       
   112       notifyIcon = new NotifyIcon();
   113       notifyIcon.ContextMenuStrip = this.notifyContextMenuStrip;
   114       notifyIcon.Icon = EmbeddedResources.GetIcon("smallicon.ico");
   115       notifyIcon.Text = "Open Hardware Monitor";      
   116       notifyIcon.DoubleClick += new EventHandler(this.hideShowClick);
   117 
   118       sensorSystemTray = new SensorSystemTray(computer);
   119 
   120       computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
   121       computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
   122       computer.Open();
   123 
   124       timer.Enabled = true;
   125 
   126       plotColorPalette = new Color[13];
   127       plotColorPalette[0] = Color.Blue;
   128       plotColorPalette[1] = Color.OrangeRed;
   129       plotColorPalette[2] = Color.Green;
   130       plotColorPalette[3] = Color.LightSeaGreen;
   131       plotColorPalette[4] = Color.Goldenrod;
   132       plotColorPalette[5] = Color.DarkViolet;
   133       plotColorPalette[6] = Color.YellowGreen;
   134       plotColorPalette[7] = Color.SaddleBrown;
   135       plotColorPalette[8] = Color.RoyalBlue;
   136       plotColorPalette[9] = Color.DeepPink;
   137       plotColorPalette[10] = Color.MediumSeaGreen;
   138       plotColorPalette[11] = Color.Olive;
   139       plotColorPalette[12] = Color.Firebrick;
   140 
   141       hiddenMenuItem.Checked = Config.Get(hiddenMenuItem.Name, false);
   142       plotMenuItem.Checked = Config.Get(plotMenuItem.Name, false);
   143 
   144       valueMenuItem.Checked = Config.Get(valueMenuItem.Name, true);
   145       minMenuItem.Checked = Config.Get(minMenuItem.Name, false);
   146       maxMenuItem.Checked = Config.Get(maxMenuItem.Name, true);
   147       limitMenuItem.Checked = Config.Get(limitMenuItem.Name, false);
   148 
   149       startMinMenuItem.Checked = Config.Get(startMinMenuItem.Name, false); 
   150       minTrayMenuItem.Checked = Config.Get(minTrayMenuItem.Name, true);
   151       startupMenuItem.Checked = startupManager.Startup;
   152       hddMenuItem.Checked = Config.Get(hddMenuItem.Name, true);
   153 
   154       celciusToolStripMenuItem.Checked = 
   155         UnitManager.TemperatureUnit == TemperatureUnit.Celcius;
   156       fahrenheitToolStripMenuItem.Checked = !celciusToolStripMenuItem.Checked;
   157 
   158       // Hide the system tray and auto startup menu items on Unix
   159       int p = (int)System.Environment.OSVersion.Platform;
   160       if ((p == 4) || (p == 128)) {
   161         minTrayMenuItem.Visible = false;
   162         startupMenuItem.Visible = false;
   163       }
   164       
   165       if (startMinMenuItem.Checked) {
   166         if (!minTrayMenuItem.Checked) {
   167           WindowState = FormWindowState.Minimized;
   168           Show();
   169         }
   170       } else {
   171         Show();
   172       }
   173 
   174       // Create a handle, otherwise calling Close() does not fire FormClosed     
   175       IntPtr handle = Handle;
   176     }
   177 
   178     private void SubHardwareAdded(IHardware hardware, Node node) {
   179       Node hardwareNode = new HardwareNode(hardware);
   180       node.Nodes.Add(hardwareNode);
   181       foreach (IHardware subHardware in hardware.SubHardware)
   182         SubHardwareAdded(subHardware, hardwareNode);  
   183     }
   184 
   185     private void HardwareAdded(IHardware hardware) {
   186       Node hardwareNode = new HardwareNode(hardware);
   187       root.Nodes.Add(hardwareNode);
   188       foreach (IHardware subHardware in hardware.SubHardware)
   189         SubHardwareAdded(subHardware, hardwareNode);     
   190     }
   191 
   192     private void HardwareRemoved(IHardware hardware) {      
   193       List<Node> nodesToRemove = new List<Node>();
   194       foreach (Node node in root.Nodes) {
   195         HardwareNode hardwareNode = node as HardwareNode;
   196         if (hardwareNode != null && hardwareNode.Hardware == hardware)
   197           nodesToRemove.Add(node);
   198       }
   199       foreach (Node node in nodesToRemove)
   200         root.Nodes.Remove(node);
   201     }
   202 
   203     private void nodeTextBoxLimit_DrawText(object sender, DrawEventArgs e) {
   204       SensorNode sensorNode = e.Node.Tag as SensorNode;
   205       if (sensorNode != null) 
   206         e.Text = sensorNode.ValueToString(sensorNode.Sensor.Limit);
   207     }
   208 
   209     private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {       
   210       Node node = e.Node.Tag as Node;
   211       if (node != null) {
   212         Color color;
   213         if (node.IsVisible) {
   214           SensorNode sensorNode = node as SensorNode;
   215           if (plotMenuItem.Checked && sensorNode != null &&
   216             sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
   217             e.TextColor = color;
   218         } else {
   219           e.TextColor = Color.DarkGray;
   220         }
   221       }
   222     }
   223 
   224     private void UpdatePlotSelection(object sender, 
   225       TreePathEventArgs e) 
   226     {
   227       List<ISensor> selected = new List<ISensor>();
   228       IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
   229       int colorIndex = 0;
   230       foreach (TreeNodeAdv node in treeView.AllNodes) {
   231         SensorNode sensorNode = node.Tag as SensorNode;
   232         if (sensorNode != null && 
   233           sensorNode.Sensor.SensorType == SensorType.Temperature) {
   234           if (sensorNode.Plot) {
   235             colors.Add(sensorNode.Sensor,
   236               plotColorPalette[colorIndex % plotColorPalette.Length]);
   237             selected.Add(sensorNode.Sensor);
   238           }
   239           colorIndex++;
   240         }
   241       }
   242       sensorPlotColors = colors;
   243       plotPanel.SetSensors(selected, colors);
   244     }
   245 
   246     private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
   247       NodeControlValueEventArgs e) {
   248       SensorNode node = e.Node.Tag as SensorNode;
   249       e.Value = (node != null) && 
   250         (node.Sensor.SensorType == SensorType.Temperature) && 
   251         plotMenuItem.Checked;
   252     }
   253 
   254     private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
   255       Close();      
   256     }
   257 
   258     private void timer_Tick(object sender, EventArgs e) {
   259       computer.Accept(updateVisitor);
   260       treeView.Invalidate();
   261       plotPanel.Invalidate();
   262       sensorSystemTray.Redraw();
   263     }
   264 
   265     private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
   266       
   267       Config.Set(hiddenMenuItem.Name, hiddenMenuItem.Checked);
   268       Config.Set(plotMenuItem.Name, plotMenuItem.Checked);
   269 
   270       Config.Set(valueMenuItem.Name, valueMenuItem.Checked);
   271       Config.Set(minMenuItem.Name, minMenuItem.Checked);
   272       Config.Set(maxMenuItem.Name, maxMenuItem.Checked);
   273       Config.Set(limitMenuItem.Name, limitMenuItem.Checked);
   274 
   275       Config.Set(startMinMenuItem.Name, startMinMenuItem.Checked);
   276       Config.Set(minTrayMenuItem.Name, minTrayMenuItem.Checked);
   277       Config.Set(hddMenuItem.Name, hddMenuItem.Checked);   
   278 
   279       if (WindowState != FormWindowState.Minimized) {
   280         Config.Set("mainForm.Location.X", Location.X);
   281         Config.Set("mainForm.Location.Y", Location.Y);
   282         Config.Set("mainForm.Width", Width);
   283         Config.Set("mainForm.Height", Height);
   284       }
   285 
   286       foreach (TreeColumn column in treeView.Columns) 
   287         Config.Set("treeView.Columns." + column.Header + ".Width", 
   288           column.Width);
   289 
   290       timer.Enabled = false;
   291 
   292       sensorSystemTray.Dispose();
   293       notifyIcon.Dispose();
   294       computer.Close();
   295     }
   296 
   297     private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
   298       new AboutBox().ShowDialog();
   299     }
   300 
   301     private void plotToolStripMenuItem_CheckedChanged(object sender, 
   302       EventArgs e) 
   303     {
   304       splitContainer.Panel2Collapsed = !plotMenuItem.Checked;
   305       treeView.Invalidate();
   306     }
   307 
   308     private void treeView_Click(object sender, EventArgs e) {
   309       
   310       MouseEventArgs m = e as MouseEventArgs;
   311       if (m == null || m.Button != MouseButtons.Right)
   312         return;
   313 
   314       NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
   315       if (info.Control != null) {
   316         SensorNode node = info.Node.Tag as SensorNode;
   317         if (node != null && node.Sensor != null) {
   318 
   319           sensorContextMenuStrip.Items.Clear();
   320           if (node.Sensor.Parameters.Length > 0) {
   321             ToolStripMenuItem item = new ToolStripMenuItem("Parameters...");
   322             item.Click += delegate(object obj, EventArgs args) {
   323               ShowParameterForm(node.Sensor);
   324             };
   325             sensorContextMenuStrip.Items.Add(item);
   326           }
   327           if (node.IsVisible) {
   328             ToolStripMenuItem item = new ToolStripMenuItem("Hide");
   329             item.Click += delegate(object obj, EventArgs args) {
   330               node.IsVisible = false;
   331             };
   332             sensorContextMenuStrip.Items.Add(item);
   333           } else {
   334             ToolStripMenuItem item = new ToolStripMenuItem("Unhide");
   335             item.Click += delegate(object obj, EventArgs args) {
   336               node.IsVisible = true;
   337             };
   338             sensorContextMenuStrip.Items.Add(item);
   339           }         
   340           if (sensorSystemTray.Contains(node.Sensor)) {
   341             ToolStripMenuItem item = new ToolStripMenuItem("Remove From Tray");
   342             item.Click += delegate(object obj, EventArgs args) {
   343               sensorSystemTray.Remove(node.Sensor);
   344             };
   345             sensorContextMenuStrip.Items.Add(item);
   346           } else {
   347             ToolStripMenuItem item = new ToolStripMenuItem("Add To Tray");
   348             item.Click += delegate(object obj, EventArgs args) {
   349               sensorSystemTray.Add(node.Sensor, true);
   350             };
   351             sensorContextMenuStrip.Items.Add(item);
   352           }
   353           sensorContextMenuStrip.Show(treeView, m.X, m.Y);
   354         }
   355       }
   356     }
   357 
   358     private void saveReportToolStripMenuItem_Click(object sender, EventArgs e) {
   359       string report = computer.GetReport();
   360       if (saveFileDialog.ShowDialog() == DialogResult.OK) {
   361         using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
   362           w.Write(report);
   363         }
   364       }
   365     }
   366 
   367     private void hddsensorsToolStripMenuItem_CheckedChanged(object sender, 
   368       EventArgs e) 
   369     {
   370       computer.HDDEnabled = hddMenuItem.Checked;
   371       UpdatePlotSelection(null, null);      
   372     }
   373 
   374     private void SysTrayHideShow() {
   375       Visible = !Visible;
   376       if (Visible)
   377         Activate();    
   378     }
   379 
   380     protected override void WndProc(ref Message m) {
   381       const int WM_SYSCOMMAND = 0x112;
   382       const int SC_MINIMIZE = 0xF020;
   383       if (minTrayMenuItem.Checked && 
   384         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
   385         SysTrayHideShow();
   386       } else {      
   387         base.WndProc(ref m);
   388       }
   389     }
   390 
   391     private void hideShowClick(object sender, EventArgs e) {
   392       SysTrayHideShow();
   393     }
   394 
   395     private void removeToolStripMenuItem_Click(object sender, EventArgs e) {
   396       ToolStripMenuItem item = sender as ToolStripMenuItem;
   397       if (item == null)
   398         return;
   399 
   400       ISensor sensor = item.Owner.Tag as ISensor;
   401       if (sensor == null)
   402         return;
   403 
   404       sensorSystemTray.Remove(sensor);
   405     }
   406 
   407     private void ShowParameterForm(ISensor sensor) {
   408       ParameterForm form = new ParameterForm();
   409       form.Parameters = sensor.Parameters;
   410       form.captionLabel.Text = sensor.Name;
   411       form.ShowDialog();
   412     }
   413 
   414     private void treeView_NodeMouseDoubleClick(object sender, 
   415       TreeNodeAdvMouseEventArgs e) {
   416       SensorNode node = e.Node.Tag as SensorNode;
   417       if (node != null && node.Sensor != null && 
   418         node.Sensor.Parameters.Length > 0) {
   419         ShowParameterForm(node.Sensor);
   420       }
   421     }
   422 
   423     private void runOnWindowsStartupToolStripMenuItem_CheckedChanged(
   424       object sender, EventArgs e) 
   425     {
   426       startupManager.Startup = startupMenuItem.Checked;
   427     }
   428 
   429     private void minTrayMenuItem_CheckedChanged(object sender, EventArgs e) {
   430       notifyIcon.Visible = minTrayMenuItem.Checked;
   431     }
   432 
   433     private void hiddenSensorsMenuItem_CheckedChanged(object sender, 
   434       EventArgs e) {
   435       treeModel.ForceVisible = hiddenMenuItem.Checked;
   436     }
   437 
   438     private void valueMenuItem_CheckedChanged(object sender, EventArgs e) {
   439       treeView.Columns[1].IsVisible = valueMenuItem.Checked;
   440     }
   441 
   442     private void minMenuItem_CheckedChanged(object sender, EventArgs e) {
   443       treeView.Columns[2].IsVisible = minMenuItem.Checked;
   444     }
   445 
   446     private void maxMenuItem_CheckedChanged(object sender, EventArgs e) {
   447       treeView.Columns[3].IsVisible = maxMenuItem.Checked;
   448     }
   449 
   450     private void limitMenuItem_CheckedChanged(object sender, EventArgs e) {
   451       treeView.Columns[4].IsVisible = limitMenuItem.Checked;
   452     }
   453 
   454     private void celciusToolStripMenuItem_Click(object sender, EventArgs e) {
   455       celciusToolStripMenuItem.Checked = true;
   456       fahrenheitToolStripMenuItem.Checked = false;
   457       UnitManager.TemperatureUnit = TemperatureUnit.Celcius;
   458     }
   459 
   460     private void fahrenheitToolStripMenuItem_Click(object sender, EventArgs e) {
   461       celciusToolStripMenuItem.Checked = false;
   462       fahrenheitToolStripMenuItem.Checked = true;
   463       UnitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
   464     }
   465   }
   466 }