GUI/MainForm.cs
author moel.mich
Sun, 08 Aug 2010 13:57:26 +0000
changeset 165 813d8bc3192f
parent 159 eda3e3458cf4
child 166 fa9dfbfc4145
permissions -rw-r--r--
Refactored the hardware monitoring code into a library (Issue 101).
     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 PersistentSettings settings;
    55     private UnitManager unitManager;
    56     private Computer computer;
    57     private Node root;
    58     private TreeModel treeModel;
    59     private IDictionary<ISensor, Color> sensorPlotColors = 
    60       new Dictionary<ISensor, Color>();
    61     private Color[] plotColorPalette;
    62     private SystemTray systemTray;    
    63     private StartupManager startupManager = new StartupManager();
    64     private UpdateVisitor updateVisitor = new UpdateVisitor();
    65 
    66     private UserOption showHiddenSensors;
    67     private UserOption showPlot;
    68     private UserOption showValue;
    69     private UserOption showMin;
    70     private UserOption showMax;
    71     private UserOption startMinimized;
    72     private UserOption minimizeToTray;
    73     private UserOption autoStart;
    74     private UserOption readHddSensors;
    75 
    76     public MainForm() {      
    77       InitializeComponent();
    78 
    79       this.settings = new PersistentSettings();      
    80       this.settings.Load(Path.ChangeExtension(
    81         System.Windows.Forms.Application.ExecutablePath, ".config"));
    82 
    83       this.unitManager = new UnitManager(settings);
    84 
    85       // set the DockStyle here, to avoid conflicts with the MainMenu
    86       this.splitContainer.Dock = DockStyle.Fill;
    87       
    88       int p = (int)System.Environment.OSVersion.Platform;
    89       if ((p == 4) || (p == 128)) {
    90         splitContainer.BorderStyle = BorderStyle.None;
    91         splitContainer.Border3DStyle = Border3DStyle.Adjust;
    92         splitContainer.SplitterWidth = 4;
    93         treeView.BorderStyle = BorderStyle.Fixed3D;
    94         plotPanel.BorderStyle = BorderStyle.Fixed3D;
    95       }
    96       
    97       this.Font = SystemFonts.MessageBoxFont;
    98       treeView.Font = SystemFonts.MessageBoxFont;
    99       plotPanel.Font = SystemFonts.MessageBoxFont;
   100       
   101       nodeCheckBox.IsVisibleValueNeeded += nodeCheckBox_IsVisibleValueNeeded;
   102       nodeCheckBox.CheckStateChanged += UpdatePlotSelection;
   103       nodeTextBoxText.DrawText += nodeTextBoxText_DrawText;
   104       nodeTextBoxValue.DrawText += nodeTextBoxText_DrawText;
   105       nodeTextBoxMin.DrawText += nodeTextBoxText_DrawText;
   106       nodeTextBoxMax.DrawText += nodeTextBoxText_DrawText;
   107       nodeTextBoxText.EditorShowing += nodeTextBoxText_EditorShowing;
   108 
   109       if (settings.Contains("mainForm.Location.X")) {
   110         int x = settings.Get("mainForm.Location.X", Location.X);
   111         x = x < 0 ? 0 : x;
   112         int y = settings.Get("mainForm.Location.Y", Location.Y);
   113         y = y < 0 ? 0 : y;
   114         this.Location = new Point(x, y);
   115       } else {
   116         StartPosition = FormStartPosition.CenterScreen;
   117       }
   118 
   119       ClientSize = new Size(
   120         settings.Get("mainForm.Width", 470),
   121         settings.Get("mainForm.Height", 640));
   122 
   123       foreach (TreeColumn column in treeView.Columns) 
   124         column.Width = Math.Max(20, Math.Min(400,
   125           settings.Get("treeView.Columns." + column.Header + ".Width",
   126           column.Width)));
   127 
   128       treeModel = new TreeModel();
   129       root = new Node(System.Environment.MachineName);
   130       root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
   131       
   132       treeModel.Nodes.Add(root);
   133       treeView.Model = treeModel;
   134 
   135       this.computer = new Computer(settings);
   136 
   137       systemTray = new SystemTray(computer, settings);
   138       systemTray.HideShowCommand += hideShowClick;
   139       systemTray.ExitCommand += exitClick;
   140 
   141       computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
   142       computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
   143       computer.Open();
   144 
   145       timer.Enabled = true;
   146 
   147       plotColorPalette = new Color[13];
   148       plotColorPalette[0] = Color.Blue;
   149       plotColorPalette[1] = Color.OrangeRed;
   150       plotColorPalette[2] = Color.Green;
   151       plotColorPalette[3] = Color.LightSeaGreen;
   152       plotColorPalette[4] = Color.Goldenrod;
   153       plotColorPalette[5] = Color.DarkViolet;
   154       plotColorPalette[6] = Color.YellowGreen;
   155       plotColorPalette[7] = Color.SaddleBrown;
   156       plotColorPalette[8] = Color.RoyalBlue;
   157       plotColorPalette[9] = Color.DeepPink;
   158       plotColorPalette[10] = Color.MediumSeaGreen;
   159       plotColorPalette[11] = Color.Olive;
   160       plotColorPalette[12] = Color.Firebrick;
   161 
   162       showHiddenSensors = new UserOption("hiddenMenuItem", false, hiddenMenuItem, settings);
   163       showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
   164         treeModel.ForceVisible = showHiddenSensors.Value;
   165       };
   166 
   167       showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
   168       showPlot.Changed += delegate(object sender, EventArgs e) {
   169         splitContainer.Panel2Collapsed = !showPlot.Value;
   170         treeView.Invalidate();
   171       };
   172 
   173       showValue = new UserOption("valueMenuItem", true, valueMenuItem, settings);
   174       showValue.Changed += delegate(object sender, EventArgs e) {
   175         treeView.Columns[1].IsVisible = showValue.Value;
   176       };
   177 
   178       showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
   179       showMin.Changed += delegate(object sender, EventArgs e) {
   180         treeView.Columns[2].IsVisible = showMin.Value;
   181       };
   182 
   183       showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
   184       showMax.Changed += delegate(object sender, EventArgs e) {
   185         treeView.Columns[3].IsVisible = showMax.Value;
   186       };
   187 
   188       startMinimized = new UserOption("startMinMenuItem", false, startMinMenuItem, settings);
   189 
   190       minimizeToTray = new UserOption("minTrayMenuItem", true, minTrayMenuItem, settings);
   191       minimizeToTray.Changed += delegate(object sender, EventArgs e) {
   192         systemTray.IsMainIconEnabled = minimizeToTray.Value;
   193       };
   194 
   195       autoStart = new UserOption(null, startupManager.Startup, startupMenuItem, settings);
   196       autoStart.Changed += delegate(object sender, EventArgs e) {
   197         startupManager.Startup = autoStart.Value; ;
   198       };
   199 
   200       readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem, settings);
   201       readHddSensors.Changed += delegate(object sender, EventArgs e) {
   202         computer.HDDEnabled = readHddSensors.Value;
   203         UpdatePlotSelection(null, null);
   204       };
   205 
   206       celciusMenuItem.Checked = 
   207         unitManager.TemperatureUnit == TemperatureUnit.Celcius;
   208       fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
   209 
   210       startupMenuItem.Visible = startupManager.IsAvailable;
   211       
   212       if (startMinMenuItem.Checked) {
   213         if (!minTrayMenuItem.Checked) {
   214           WindowState = FormWindowState.Minimized;
   215           Show();
   216         }
   217       } else {
   218         Show();
   219       }
   220 
   221       // Create a handle, otherwise calling Close() does not fire FormClosed     
   222       IntPtr handle = Handle;
   223 
   224       // Make sure the settings are saved when the user logs off
   225       Microsoft.Win32.SystemEvents.SessionEnded +=
   226         delegate(object sender, Microsoft.Win32.SessionEndedEventArgs e) {
   227           SaveConfiguration();
   228         };
   229     }
   230     
   231     private void SubHardwareAdded(IHardware hardware, Node node) {
   232       Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
   233       node.Nodes.Add(hardwareNode);
   234       foreach (IHardware subHardware in hardware.SubHardware)
   235         SubHardwareAdded(subHardware, hardwareNode);  
   236     }
   237 
   238     private void HardwareAdded(IHardware hardware) {
   239       Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
   240       root.Nodes.Add(hardwareNode);
   241       foreach (IHardware subHardware in hardware.SubHardware)
   242         SubHardwareAdded(subHardware, hardwareNode);     
   243     }
   244 
   245     private void HardwareRemoved(IHardware hardware) {      
   246       List<Node> nodesToRemove = new List<Node>();
   247       foreach (Node node in root.Nodes) {
   248         HardwareNode hardwareNode = node as HardwareNode;
   249         if (hardwareNode != null && hardwareNode.Hardware == hardware)
   250           nodesToRemove.Add(node);
   251       }
   252       foreach (Node node in nodesToRemove)
   253         root.Nodes.Remove(node);
   254     }
   255 
   256     private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {       
   257       Node node = e.Node.Tag as Node;
   258       if (node != null) {
   259         Color color;
   260         if (node.IsVisible) {
   261           SensorNode sensorNode = node as SensorNode;
   262           if (plotMenuItem.Checked && sensorNode != null &&
   263             sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
   264             e.TextColor = color;
   265         } else {
   266           e.TextColor = Color.DarkGray;
   267         }
   268       }
   269     }
   270 
   271     private void UpdatePlotSelection(object sender, 
   272       TreePathEventArgs e) 
   273     {
   274       List<ISensor> selected = new List<ISensor>();
   275       IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
   276       int colorIndex = 0;
   277       foreach (TreeNodeAdv node in treeView.AllNodes) {
   278         SensorNode sensorNode = node.Tag as SensorNode;
   279         if (sensorNode != null && 
   280           sensorNode.Sensor.SensorType == SensorType.Temperature) {
   281           if (sensorNode.Plot) {
   282             colors.Add(sensorNode.Sensor,
   283               plotColorPalette[colorIndex % plotColorPalette.Length]);
   284             selected.Add(sensorNode.Sensor);
   285           }
   286           colorIndex++;
   287         }
   288       }
   289       sensorPlotColors = colors;
   290       plotPanel.SetSensors(selected, colors);
   291     }
   292 
   293     private void nodeTextBoxText_EditorShowing(object sender, CancelEventArgs e) 
   294     {
   295       e.Cancel = !(treeView.CurrentNode != null &&
   296         treeView.CurrentNode.Tag is SensorNode);
   297     }
   298 
   299     private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
   300       NodeControlValueEventArgs e) {
   301       SensorNode node = e.Node.Tag as SensorNode;
   302       e.Value = (node != null) && 
   303         (node.Sensor.SensorType == SensorType.Temperature) && 
   304         plotMenuItem.Checked;
   305     }
   306 
   307     private void exitClick(object sender, EventArgs e) {
   308       Close();      
   309     }
   310 
   311     private void timer_Tick(object sender, EventArgs e) {
   312       computer.Accept(updateVisitor);
   313       treeView.Invalidate();
   314       plotPanel.Invalidate();
   315       systemTray.Redraw();
   316     }
   317 
   318     private void SaveConfiguration() {
   319       if (WindowState != FormWindowState.Minimized) {
   320         settings.Set("mainForm.Location.X", Location.X);
   321         settings.Set("mainForm.Location.Y", Location.Y);
   322         settings.Set("mainForm.Width", ClientSize.Width);
   323         settings.Set("mainForm.Height", ClientSize.Height);
   324       }
   325 
   326       foreach (TreeColumn column in treeView.Columns)
   327         settings.Set("treeView.Columns." + column.Header + ".Width",
   328           column.Width);
   329 
   330       settings.Save(Path.ChangeExtension(
   331         System.Windows.Forms.Application.ExecutablePath, ".config"));
   332     }
   333 
   334     private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
   335       Visible = false;
   336       SaveConfiguration();
   337 
   338       timer.Enabled = false;
   339       systemTray.Dispose();      
   340       computer.Close();
   341     }
   342 
   343     private void aboutMenuItem_Click(object sender, EventArgs e) {
   344       new AboutBox().ShowDialog();
   345     }
   346 
   347     private void treeView_Click(object sender, EventArgs e) {
   348       
   349       MouseEventArgs m = e as MouseEventArgs;
   350       if (m == null || m.Button != MouseButtons.Right)
   351         return;
   352 
   353       NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
   354       treeView.SelectedNode = info.Node;
   355       if (info.Node != null) {
   356         SensorNode node = info.Node.Tag as SensorNode;
   357         if (node != null && node.Sensor != null) {
   358           sensorContextMenu.MenuItems.Clear();
   359           if (node.Sensor.Parameters.Length > 0) {
   360             MenuItem item = new MenuItem("Parameters...");
   361             item.Click += delegate(object obj, EventArgs args) {
   362               ShowParameterForm(node.Sensor);
   363             };
   364             sensorContextMenu.MenuItems.Add(item);
   365           }
   366           if (nodeTextBoxText.EditEnabled) {
   367             MenuItem item = new MenuItem("Rename");
   368             item.Click += delegate(object obj, EventArgs args) {
   369               nodeTextBoxText.BeginEdit();
   370             };
   371             sensorContextMenu.MenuItems.Add(item);
   372           }          
   373           if (node.IsVisible) {
   374             MenuItem item = new MenuItem("Hide");
   375             item.Click += delegate(object obj, EventArgs args) {
   376               node.IsVisible = false;
   377             };
   378             sensorContextMenu.MenuItems.Add(item);
   379           } else {
   380             MenuItem item = new MenuItem("Unhide");
   381             item.Click += delegate(object obj, EventArgs args) {
   382               node.IsVisible = true;
   383             };
   384             sensorContextMenu.MenuItems.Add(item);
   385           }         
   386           if (systemTray.Contains(node.Sensor)) {
   387             MenuItem item = new MenuItem("Remove From Tray");
   388             item.Click += delegate(object obj, EventArgs args) {
   389               systemTray.Remove(node.Sensor);
   390             };
   391             sensorContextMenu.MenuItems.Add(item);
   392           } else {
   393             MenuItem item = new MenuItem("Add To Tray");
   394             item.Click += delegate(object obj, EventArgs args) {
   395               systemTray.Add(node.Sensor, true);
   396             };
   397             sensorContextMenu.MenuItems.Add(item);
   398           }
   399           sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
   400         }
   401       }
   402     }
   403 
   404     private void saveReportMenuItem_Click(object sender, EventArgs e) {
   405       string report = computer.GetReport();
   406       if (saveFileDialog.ShowDialog() == DialogResult.OK) {
   407         using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
   408           w.Write(report);
   409         }
   410       }
   411     }
   412 
   413     private void SysTrayHideShow() {
   414       Visible = !Visible;
   415       if (Visible)
   416         Activate();    
   417     }
   418 
   419     protected override void WndProc(ref Message m) {
   420       const int WM_SYSCOMMAND = 0x112;
   421       const int SC_MINIMIZE = 0xF020;
   422       if (minimizeToTray.Value && 
   423         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
   424         SysTrayHideShow();
   425       } else {      
   426         base.WndProc(ref m);
   427       }
   428     }
   429 
   430     private void hideShowClick(object sender, EventArgs e) {
   431       SysTrayHideShow();
   432     }
   433 
   434     private void removeMenuItem_Click(object sender, EventArgs e) {
   435       MenuItem item = sender as MenuItem;
   436       if (item == null)
   437         return;
   438 
   439       ISensor sensor = item.Parent.Tag as ISensor;
   440       if (sensor == null)
   441         return;
   442 
   443       systemTray.Remove(sensor);
   444     }
   445 
   446     private void ShowParameterForm(ISensor sensor) {
   447       ParameterForm form = new ParameterForm();
   448       form.Parameters = sensor.Parameters;
   449       form.captionLabel.Text = sensor.Name;
   450       form.ShowDialog();
   451     }
   452 
   453     private void treeView_NodeMouseDoubleClick(object sender, 
   454       TreeNodeAdvMouseEventArgs e) {
   455       SensorNode node = e.Node.Tag as SensorNode;
   456       if (node != null && node.Sensor != null && 
   457         node.Sensor.Parameters.Length > 0) {
   458         ShowParameterForm(node.Sensor);
   459       }
   460     }
   461 
   462     private void celciusMenuItem_Click(object sender, EventArgs e) {
   463       celciusMenuItem.Checked = true;
   464       fahrenheitMenuItem.Checked = false;
   465       unitManager.TemperatureUnit = TemperatureUnit.Celcius;
   466     }
   467 
   468     private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
   469       celciusMenuItem.Checked = false;
   470       fahrenheitMenuItem.Checked = true;
   471       unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
   472     }
   473 
   474     private void sumbitReportMenuItem_Click(object sender, EventArgs e) 
   475     {
   476       ReportForm form = new ReportForm();
   477       form.Report = computer.GetReport();
   478       form.ShowDialog();      
   479     }
   480 
   481     private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
   482       computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
   483         sensor.ResetMin();
   484         sensor.ResetMax();
   485       }));
   486     }
   487   }
   488 }