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