GUI/MainForm.cs
author paulwerelds
Mon, 04 Oct 2010 16:56:42 +0000
changeset 209 dee42c887ab0
parent 198 d5de6fa31bc6
child 211 88131b86378b
permissions -rw-r--r--
Fixed the context menu positioning as well, following the previous fix to multimonitor setups.
     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       settings.Save(Path.ChangeExtension(
   354         System.Windows.Forms.Application.ExecutablePath, ".config"));
   355     }
   356 
   357    private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
   358       Visible = false;
   359       SaveConfiguration();
   360 
   361       timer.Enabled = false;
   362       systemTray.Dispose();      
   363       computer.Close();
   364     }
   365 
   366     private void aboutMenuItem_Click(object sender, EventArgs e) {
   367       new AboutBox().ShowDialog();
   368     }
   369 
   370     private void treeView_Click(object sender, EventArgs e) {
   371       
   372       MouseEventArgs m = e as MouseEventArgs;
   373       if (m == null || m.Button != MouseButtons.Right)
   374         return;
   375 
   376       NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
   377       treeView.SelectedNode = info.Node;
   378       if (info.Node != null) {
   379         SensorNode node = info.Node.Tag as SensorNode;
   380         if (node != null && node.Sensor != null) {
   381           sensorContextMenu.MenuItems.Clear();
   382           if (node.Sensor.Parameters.Length > 0) {
   383             MenuItem item = new MenuItem("Parameters...");
   384             item.Click += delegate(object obj, EventArgs args) {
   385               ShowParameterForm(node.Sensor);
   386             };
   387             sensorContextMenu.MenuItems.Add(item);
   388           }
   389           if (nodeTextBoxText.EditEnabled) {
   390             MenuItem item = new MenuItem("Rename");
   391             item.Click += delegate(object obj, EventArgs args) {
   392               nodeTextBoxText.BeginEdit();
   393             };
   394             sensorContextMenu.MenuItems.Add(item);
   395           }
   396           if (node.IsVisible) {
   397             MenuItem item = new MenuItem("Hide");
   398             item.Click += delegate(object obj, EventArgs args) {
   399               node.IsVisible = false;
   400             };
   401             sensorContextMenu.MenuItems.Add(item);
   402           } else {
   403             MenuItem item = new MenuItem("Unhide");
   404             item.Click += delegate(object obj, EventArgs args) {
   405               node.IsVisible = true;
   406             };
   407             sensorContextMenu.MenuItems.Add(item);
   408           }
   409           sensorContextMenu.MenuItems.Add(new MenuItem("-"));
   410           {
   411             MenuItem item = new MenuItem("Show in Tray");
   412             item.Checked = systemTray.Contains(node.Sensor);
   413             item.Click += delegate(object obj, EventArgs args) {
   414               if (item.Checked)
   415                 systemTray.Remove(node.Sensor);
   416               else
   417                 systemTray.Add(node.Sensor, true);
   418             };
   419             sensorContextMenu.MenuItems.Add(item);
   420           }
   421           {
   422             MenuItem item = new MenuItem("Show in Gadget");
   423             item.Checked = gadget.Contains(node.Sensor);
   424             item.Click += delegate(object obj, EventArgs args) {
   425               if (item.Checked) {
   426                 gadget.Remove(node.Sensor);
   427               } else {
   428                 gadget.Add(node.Sensor);
   429               }
   430             };
   431             sensorContextMenu.MenuItems.Add(item);
   432           }
   433 
   434           sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
   435         }
   436       }
   437     }
   438 
   439     private void saveReportMenuItem_Click(object sender, EventArgs e) {
   440       string report = computer.GetReport();
   441       if (saveFileDialog.ShowDialog() == DialogResult.OK) {
   442         using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
   443           w.Write(report);
   444         }
   445       }
   446     }
   447 
   448     private void SysTrayHideShow() {
   449       Visible = !Visible;
   450       if (Visible)
   451         Activate();    
   452     }
   453 
   454     protected override void WndProc(ref Message m) {
   455       const int WM_SYSCOMMAND = 0x112;
   456       const int SC_MINIMIZE = 0xF020;
   457       const int SC_CLOSE = 0xF060;
   458 
   459       if (minimizeToTray.Value && 
   460         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
   461         SysTrayHideShow();
   462       } else if(minimizeOnClose.Value && 
   463         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
   464         /*
   465          * Apparently the user wants to minimize rather than close
   466          * Now we still need to check if we're going to the tray or not
   467          * 
   468          * Note: the correct way to do this would be to send out SC_MINIMIZE,
   469          * but since the code here is so simple,
   470          * that would just be a waste of time.
   471          */
   472         if (minimizeToTray.Value)
   473           SysTrayHideShow();
   474         else
   475           WindowState = FormWindowState.Minimized;
   476       } else {      
   477         base.WndProc(ref m);
   478       }
   479     }
   480 
   481     private void hideShowClick(object sender, EventArgs e) {
   482       SysTrayHideShow();
   483     }
   484 
   485     private void ShowParameterForm(ISensor sensor) {
   486       ParameterForm form = new ParameterForm();
   487       form.Parameters = sensor.Parameters;
   488       form.captionLabel.Text = sensor.Name;
   489       form.ShowDialog();
   490     }
   491 
   492     private void treeView_NodeMouseDoubleClick(object sender, 
   493       TreeNodeAdvMouseEventArgs e) {
   494       SensorNode node = e.Node.Tag as SensorNode;
   495       if (node != null && node.Sensor != null && 
   496         node.Sensor.Parameters.Length > 0) {
   497         ShowParameterForm(node.Sensor);
   498       }
   499     }
   500 
   501     private void celciusMenuItem_Click(object sender, EventArgs e) {
   502       celciusMenuItem.Checked = true;
   503       fahrenheitMenuItem.Checked = false;
   504       unitManager.TemperatureUnit = TemperatureUnit.Celcius;
   505     }
   506 
   507     private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
   508       celciusMenuItem.Checked = false;
   509       fahrenheitMenuItem.Checked = true;
   510       unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
   511     }
   512 
   513     private void sumbitReportMenuItem_Click(object sender, EventArgs e) 
   514     {
   515       ReportForm form = new ReportForm();
   516       form.Report = computer.GetReport();
   517       form.ShowDialog();      
   518     }
   519 
   520     private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
   521       computer.Accept(new SensorVisitor(delegate(ISensor sensor) {
   522         sensor.ResetMin();
   523         sensor.ResetMax();
   524       }));
   525     }
   526   }
   527 }