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