moel@1: /*
moel@1:   
moel@1:   Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@1: 
moel@1:   The contents of this file are subject to the Mozilla Public License Version
moel@1:   1.1 (the "License"); you may not use this file except in compliance with
moel@1:   the License. You may obtain a copy of the License at
moel@1:  
moel@1:   http://www.mozilla.org/MPL/
moel@1: 
moel@1:   Software distributed under the License is distributed on an "AS IS" basis,
moel@1:   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@1:   for the specific language governing rights and limitations under the License.
moel@1: 
moel@1:   The Original Code is the Open Hardware Monitor code.
moel@1: 
moel@1:   The Initial Developer of the Original Code is 
moel@1:   Michael Möller <m.moeller@gmx.ch>.
moel@1:   Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@1:   the Initial Developer. All Rights Reserved.
moel@1: 
moel@1:   Contributor(s):
moel@1: 
moel@1:   Alternatively, the contents of this file may be used under the terms of
moel@1:   either the GNU General Public License Version 2 or later (the "GPL"), or
moel@1:   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@1:   in which case the provisions of the GPL or the LGPL are applicable instead
moel@1:   of those above. If you wish to allow use of your version of this file only
moel@1:   under the terms of either the GPL or the LGPL, and not to allow others to
moel@1:   use your version of this file under the terms of the MPL, indicate your
moel@1:   decision by deleting the provisions above and replace them with the notice
moel@1:   and other provisions required by the GPL or the LGPL. If you do not delete
moel@1:   the provisions above, a recipient may use your version of this file under
moel@1:   the terms of any one of the MPL, the GPL or the LGPL.
moel@1:  
moel@1: */
moel@1: 
moel@1: using System;
moel@1: using System.Collections.Generic;
moel@1: using System.ComponentModel;
moel@1: using System.Configuration;
moel@1: using System.Drawing;
moel@1: using System.Text;
moel@1: using System.Windows.Forms;
moel@1: using Aga.Controls.Tree;
moel@1: using Aga.Controls.Tree.NodeControls;
moel@1: using OpenHardwareMonitor.Hardware;
moel@28: using OpenHardwareMonitor.Utilities;
moel@1: 
moel@1: namespace OpenHardwareMonitor.GUI {
moel@1:   public partial class MainForm : Form {
moel@1: 
moel@28:     private Computer computer = new Computer();
moel@1:     private Node root;
moel@1:     private TreeModel treeModel;
moel@1:     private IDictionary<ISensor, Color> sensorPlotColors = 
moel@1:       new Dictionary<ISensor, Color>();
moel@1:     private Color[] plotColorPalette;
moel@40:     private SensorSystemTray sensorSystemTray;
moel@40:     private NotifyIcon notifyIcon;
moel@1: 
moel@28:     public MainForm() {      
moel@1:       InitializeComponent();
moel@1:       this.Font = SystemFonts.MessageBoxFont;
moel@1:       treeView.Font = SystemFonts.MessageBoxFont;
moel@1:       plotPanel.Font = SystemFonts.MessageBoxFont;      
moel@1:       
moel@1:       nodeCheckBox.IsVisibleValueNeeded += 
moel@1:         new EventHandler<NodeControlValueEventArgs>(
moel@1:           nodeCheckBox_IsVisibleValueNeeded);
moel@1:       nodeCheckBox.CheckStateChanged += 
moel@1:         new EventHandler<TreePathEventArgs>(UpdatePlotSelection);
moel@1:       nodeTextBoxText.DrawText += 
moel@1:         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1:       nodeTextBoxValue.DrawText +=
moel@1:         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1:       nodeTextBoxMin.DrawText +=
moel@1:         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1:       nodeTextBoxMax.DrawText +=
moel@1:         new EventHandler<DrawEventArgs>(nodeTextBoxText_DrawText);
moel@1:       nodeTextBoxLimit.DrawText += 
moel@1:         new EventHandler<DrawEventArgs>(nodeTextBoxLimit_DrawText);
moel@1: 
moel@1:       if (Utilities.Config.Contains("mainForm.Location.X")) {
moel@1:         int x = Utilities.Config.Get("mainForm.Location.X", Location.X);
moel@1:         x = x < 0 ? 0 : x;
moel@1:         int y = Utilities.Config.Get("mainForm.Location.Y", Location.Y);
moel@1:         y = y < 0 ? 0 : y;
moel@1:         this.Location = new Point(x, y);
moel@1:       } else {
moel@1:         StartPosition = FormStartPosition.CenterScreen;
moel@1:       }
moel@1: 
moel@1:       Width = Utilities.Config.Get("mainForm.Width", Width);
moel@1:       Height = Utilities.Config.Get("mainForm.Height", Height);
moel@1:          
moel@1:       treeModel = new TreeModel();
moel@1:       root = new Node(System.Environment.MachineName);
moel@1:       root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
moel@1:       
moel@1:       treeModel.Nodes.Add(root);
moel@1:       treeView.Model = treeModel;
moel@40:       
moel@40:       notifyIcon = new NotifyIcon();
moel@40:       notifyIcon.ContextMenuStrip = this.notifyContextMenuStrip;
moel@40:       notifyIcon.Icon = EmbeddedResources.GetIcon("smallicon.ico");
moel@40:       notifyIcon.Text = "Open Hardware Monitor";      
moel@40:       notifyIcon.DoubleClick += new EventHandler(this.restoreClick);
moel@40: 
moel@40:       sensorSystemTray = new SensorSystemTray(computer);
moel@1: 
moel@28:       computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
moel@28:       computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
moel@28:       computer.Open();
moel@28: 
moel@1:       plotColorPalette = new Color[14];
moel@1:       plotColorPalette[0] = Color.Blue;
moel@1:       plotColorPalette[1] = Color.OrangeRed;
moel@1:       plotColorPalette[2] = Color.Green;
moel@1:       plotColorPalette[3] = Color.LightSeaGreen;
moel@1:       plotColorPalette[4] = Color.Goldenrod;
moel@1:       plotColorPalette[5] = Color.DarkViolet;
moel@1:       plotColorPalette[6] = Color.YellowGreen;
moel@1:       plotColorPalette[7] = Color.SaddleBrown;
moel@1:       plotColorPalette[8] = Color.Gray;
moel@1:       plotColorPalette[9] = Color.RoyalBlue;
moel@1:       plotColorPalette[10] = Color.DeepPink;
moel@1:       plotColorPalette[11] = Color.MediumSeaGreen;
moel@1:       plotColorPalette[12] = Color.Olive;
moel@1:       plotColorPalette[13] = Color.Firebrick;
moel@1: 
moel@28:       plotMenuItem.Checked = Config.Get(plotMenuItem.Name, false);
moel@28:       minMenuItem.Checked = Config.Get(minMenuItem.Name, false);
moel@28:       maxMenuItem.Checked = Config.Get(maxMenuItem.Name, true);
moel@28:       limitMenuItem.Checked = Config.Get(limitMenuItem.Name, false);
moel@1: 
moel@28:       minTrayMenuItem.Checked = Config.Get(minTrayMenuItem.Name, true);
moel@28:       hddMenuItem.Checked = Config.Get(hddMenuItem.Name, true);
moel@1: 
moel@28:       voltMenuItem.Checked = Config.Get(voltMenuItem.Name, true);
moel@28:       clocksMenuItem.Checked = Config.Get(clocksMenuItem.Name, true);
moel@28:       loadMenuItem.Checked = Config.Get(loadMenuItem.Name, true);
moel@28:       tempMenuItem.Checked = Config.Get(tempMenuItem.Name, true);
moel@28:       fansMenuItem.Checked = Config.Get(fansMenuItem.Name, true);
moel@28:      
moel@28:       timer.Enabled = true;   
moel@1:     }
moel@1: 
moel@28:     private void HardwareAdded(IHardware hardware) {
moel@28:       root.Nodes.Add(new HardwareNode(hardware));
moel@1:     }
moel@1: 
moel@28:     private void HardwareRemoved(IHardware hardware) {      
moel@1:       List<Node> nodesToRemove = new List<Node>();
moel@28:       foreach (Node node in root.Nodes) {
moel@28:         HardwareNode hardwareNode = node as HardwareNode;
moel@28:         if (hardwareNode != null && hardwareNode.Hardware == hardware)
moel@28:           nodesToRemove.Add(node);
moel@28:       }
moel@1:       foreach (Node node in nodesToRemove)
moel@1:         root.Nodes.Remove(node);
moel@1:     }
moel@1: 
moel@1:     private void nodeTextBoxLimit_DrawText(object sender, DrawEventArgs e) {
moel@1:       SensorNode sensorNode = e.Node.Tag as SensorNode;
moel@1:       if (sensorNode != null) 
moel@1:         e.Text = sensorNode.ValueToString(sensorNode.Sensor.Limit);
moel@1:     }
moel@1: 
moel@1:     private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
moel@1:       if (!plotMenuItem.Checked)
moel@1:         return;      
moel@1: 
moel@1:       SensorNode sensorNode = e.Node.Tag as SensorNode;
moel@1:       if (sensorNode != null) {
moel@1:         Color color;
moel@1:         if (sensorPlotColors.TryGetValue(sensorNode.Sensor, out color)) 
moel@1:           e.TextColor = color;        
moel@1:       }
moel@1:     }
moel@1: 
moel@1:     private void UpdatePlotSelection(object sender, 
moel@1:       TreePathEventArgs e) 
moel@1:     {
moel@1:       List<ISensor> selected = new List<ISensor>();
moel@1:       IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
moel@1:       int colorIndex = 0;
moel@1:       foreach (TreeNodeAdv node in treeView.AllNodes) {
moel@1:         SensorNode sensorNode = node.Tag as SensorNode;
moel@1:         if (sensorNode != null && 
moel@1:           sensorNode.Sensor.SensorType == SensorType.Temperature) {
moel@1:           if (sensorNode.Plot) {
moel@1:             colors.Add(sensorNode.Sensor,
moel@1:               plotColorPalette[colorIndex % plotColorPalette.Length]);
moel@1:             selected.Add(sensorNode.Sensor);
moel@1:           }
moel@1:           colorIndex++;
moel@1:         }
moel@1:       }
moel@1:       sensorPlotColors = colors;
moel@1:       plotPanel.SetSensors(selected, colors);
moel@1:     }
moel@1: 
moel@1:     private void nodeCheckBox_IsVisibleValueNeeded(object sender, 
moel@1:       NodeControlValueEventArgs e) {
moel@1:       SensorNode node = e.Node.Tag as SensorNode;
moel@1:       e.Value = (node != null) && 
moel@1:         (node.Sensor.SensorType == SensorType.Temperature) && 
moel@1:         plotMenuItem.Checked;
moel@1:     }
moel@1: 
moel@1:     private void exitToolStripMenuItem_Click(object sender, EventArgs e) {
moel@1:       Close();
moel@1:     }
moel@1: 
moel@1:     private void timer_Tick(object sender, EventArgs e) {
moel@1:       
moel@1:       #if !DEBUG
moel@1:       try {
moel@1:       #endif
moel@28:         computer.Update();        
moel@1:       #if !DEBUG
moel@1:       } catch (Exception exception) {
moel@28:         CrashReport.Save(exception);
moel@1:         Close();
moel@1:       }
moel@1:       #endif
moel@1:             
moel@1:       treeView.Invalidate();
moel@1:       plotPanel.Invalidate();
moel@40:       sensorSystemTray.Redraw();
moel@1:     }
moel@1: 
moel@1:     private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
moel@28:             
moel@28:       Config.Set(plotMenuItem.Name, plotMenuItem.Checked);
moel@28:       Config.Set(minMenuItem.Name, minMenuItem.Checked);
moel@28:       Config.Set(maxMenuItem.Name, maxMenuItem.Checked);
moel@28:       Config.Set(limitMenuItem.Name, limitMenuItem.Checked);
moel@1: 
moel@28:       Config.Set(minTrayMenuItem.Name, minTrayMenuItem.Checked);
moel@28:       Config.Set(hddMenuItem.Name, hddMenuItem.Checked);
moel@28: 
moel@28:       Config.Set(voltMenuItem.Name, voltMenuItem.Checked);
moel@28:       Config.Set(clocksMenuItem.Name, clocksMenuItem.Checked);
moel@28:       Config.Set(loadMenuItem.Name, loadMenuItem.Checked);
moel@28:       Config.Set(tempMenuItem.Name, tempMenuItem.Checked);
moel@28:       Config.Set(fansMenuItem.Name, fansMenuItem.Checked);
moel@1: 
moel@14:       if (WindowState != FormWindowState.Minimized) {
moel@28:         Config.Set("mainForm.Location.X", Location.X);
moel@28:         Config.Set("mainForm.Location.Y", Location.Y);
moel@28:         Config.Set("mainForm.Width", Width);
moel@28:         Config.Set("mainForm.Height", Height);
moel@14:       }
moel@42:            
moel@40:       sensorSystemTray.Dispose();
moel@40:       notifyIcon.Dispose();
moel@28:       computer.Close();
moel@1:     }
moel@1: 
moel@1:     private void aboutToolStripMenuItem_Click(object sender, EventArgs e) {
moel@1:       new AboutBox().ShowDialog();
moel@1:     }
moel@1: 
moel@1:     private void plotToolStripMenuItem_CheckedChanged(object sender, 
moel@1:       EventArgs e) 
moel@1:     {
moel@1:       splitContainer.Panel2Collapsed = !plotMenuItem.Checked;
moel@1:       treeView.Invalidate();
moel@1:     }
moel@1: 
moel@1:     private void valueToolStripMenuItem_CheckedChanged(object sender, 
moel@1:       EventArgs e) 
moel@1:     {
moel@1:       treeView.Columns[1].IsVisible = valueToolStripMenuItem.Checked;
moel@1:     }
moel@1: 
moel@1:     private void minToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
moel@1:     {
moel@1:       treeView.Columns[2].IsVisible = minMenuItem.Checked;
moel@1:     }
moel@1: 
moel@1:     private void maxToolStripMenuItem_CheckedChanged(object sender, EventArgs e) 
moel@1:     {
moel@1:       treeView.Columns[3].IsVisible = maxMenuItem.Checked;
moel@1:     }
moel@1: 
moel@1:     private void limitToolStripMenuItem_CheckedChanged(object sender, 
moel@1:       EventArgs e) {
moel@1:       treeView.Columns[4].IsVisible = limitMenuItem.Checked;
moel@1:     }
moel@1: 
moel@1:     private void treeView_Click(object sender, EventArgs e) {
moel@1:       
moel@1:       MouseEventArgs m = e as MouseEventArgs;
moel@1:       if (m == null || m.Button != MouseButtons.Right)
moel@1:         return;
moel@1: 
moel@1:       NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
moel@28:       if (info.Control == null) {
moel@1:         columnsContextMenuStrip.Show(treeView, m.X, m.Y);
moel@40:       } else {
moel@40:         SensorNode node = info.Node.Tag as SensorNode;
moel@40:         if (node != null && node.Sensor != null) {
moel@40: 
moel@40:           sensorContextMenuStrip.Items.Clear();
moel@40:           if (sensorSystemTray.Contains(node.Sensor)) {
moel@40:             ToolStripMenuItem item = new ToolStripMenuItem("Remove From Tray");
moel@40:             item.Click += delegate(object obj, EventArgs args) {
moel@40:               sensorSystemTray.Remove(node.Sensor);
moel@40:             };
moel@40:             sensorContextMenuStrip.Items.Add(item);
moel@40:           } else {
moel@40:             ToolStripMenuItem item = new ToolStripMenuItem("Add To Tray");
moel@40:             item.Click += delegate(object obj, EventArgs args) {
moel@42:               sensorSystemTray.Add(node.Sensor, true);
moel@40:             };
moel@40:             sensorContextMenuStrip.Items.Add(item);
moel@40:           }
moel@40:           sensorContextMenuStrip.Show(treeView, m.X, m.Y);
moel@40:         }
moel@40:       }
moel@1:     }
moel@1: 
moel@1:     private void saveReportToolStripMenuItem_Click(object sender, EventArgs e) {
moel@28:       computer.SaveReport(new Version(Application.ProductVersion));      
moel@1:     }
moel@1: 
moel@1:     private void hddsensorsToolStripMenuItem_CheckedChanged(object sender, 
moel@1:       EventArgs e) 
moel@1:     {
moel@28:       computer.HDDEnabled = hddMenuItem.Checked;
moel@28:       UpdateSensorTypeChecked(null, null);
moel@28:       UpdatePlotSelection(null, null);      
moel@1:     }
moel@1: 
moel@1:     private void UpdateSensorTypeChecked(object sender, EventArgs e) {
moel@1:       foreach (HardwareNode node in root.Nodes) {
moel@1:         node.SetVisible(SensorType.Voltage, voltMenuItem.Checked);
moel@1:         node.SetVisible(SensorType.Clock, clocksMenuItem.Checked);
moel@24:         node.SetVisible(SensorType.Load, loadMenuItem.Checked);
moel@1:         node.SetVisible(SensorType.Temperature, tempMenuItem.Checked);
moel@1:         node.SetVisible(SensorType.Fan, fansMenuItem.Checked);
moel@1:       }
moel@27:     }
moel@27: 
moel@27:     private void ToggleSysTray() {
moel@27:       if (Visible) {
moel@27:         notifyIcon.Visible = true;
moel@27:         Visible = false;        
moel@27:       } else {
moel@27:         Visible = true;
moel@27:         notifyIcon.Visible = false;
moel@34:         Activate();
moel@27:       }
moel@27:     }
moel@27: 
moel@27:     protected override void WndProc(ref Message m) {
moel@27:       const int WM_SYSCOMMAND = 0x112;
moel@27:       const int SC_MINIMIZE = 0xF020;
moel@28:       if (minTrayMenuItem.Checked && 
moel@28:         m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
moel@27:         ToggleSysTray();
moel@27:       } else {      
moel@27:         base.WndProc(ref m);
moel@27:       }
moel@27:     }
moel@27: 
moel@28:     private void restoreClick(object sender, EventArgs e) {
moel@28:       ToggleSysTray();
moel@27:     }
moel@27: 
moel@40:     private void removeToolStripMenuItem_Click(object sender, EventArgs e) {
moel@40:       ToolStripMenuItem item = sender as ToolStripMenuItem;
moel@40:       if (item == null)
moel@40:         return;
moel@40: 
moel@40:       ISensor sensor = item.Owner.Tag as ISensor;
moel@40:       if (sensor == null)
moel@40:         return;
moel@40: 
moel@40:       sensorSystemTray.Remove(sensor);
moel@40:     }
moel@40: 
moel@1:   }
moel@1: }