Fixed Issue 125.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
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
9 http://www.mozilla.org/MPL/
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.
15 The Original Code is the Open Hardware Monitor code.
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.
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.
39 using System.Collections.Generic;
40 using System.ComponentModel;
41 using System.Configuration;
45 using System.Windows.Forms;
46 using Aga.Controls.Tree;
47 using Aga.Controls.Tree.NodeControls;
48 using OpenHardwareMonitor.Hardware;
49 using OpenHardwareMonitor.Utilities;
51 namespace OpenHardwareMonitor.GUI {
52 public partial class MainForm : Form {
54 private PersistentSettings settings;
55 private UnitManager unitManager;
56 private Computer computer;
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;
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;
80 InitializeComponent();
82 this.settings = new PersistentSettings();
83 this.settings.Load(Path.ChangeExtension(
84 Application.ExecutablePath, ".config"));
86 this.unitManager = new UnitManager(settings);
88 // set the DockStyle here, to avoid conflicts with the MainMenu
89 this.splitContainer.Dock = DockStyle.Fill;
91 this.Font = SystemFonts.MessageBoxFont;
92 treeView.Font = SystemFonts.MessageBoxFont;
93 plotPanel.Font = SystemFonts.MessageBoxFont;
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;
103 if (settings.Contains("mainForm.Location.X")) {
104 int x = settings.GetValue("mainForm.Location.X", Location.X);
106 int y = settings.GetValue("mainForm.Location.Y", Location.Y);
108 this.Location = new Point(x, y);
110 StartPosition = FormStartPosition.CenterScreen;
113 ClientSize = new Size(
114 settings.GetValue("mainForm.Width", 470),
115 settings.GetValue("mainForm.Height", 640));
117 foreach (TreeColumn column in treeView.Columns)
118 column.Width = Math.Max(20, Math.Min(400,
119 settings.GetValue("treeView.Columns." + column.Header + ".Width",
122 treeModel = new TreeModel();
123 root = new Node(System.Environment.MachineName);
124 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
126 treeModel.Nodes.Add(root);
127 treeView.Model = treeModel;
129 this.computer = new Computer(settings);
131 systemTray = new SystemTray(computer, settings);
132 systemTray.HideShowCommand += hideShowClick;
133 systemTray.ExitCommand += exitClick;
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;
145 gadget = new SensorGadget(computer, settings, unitManager);
148 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
149 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
152 timer.Enabled = true;
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;
169 showHiddenSensors = new UserOption("hiddenMenuItem", false, hiddenMenuItem, settings);
170 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
171 treeModel.ForceVisible = showHiddenSensors.Value;
174 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
175 showPlot.Changed += delegate(object sender, EventArgs e) {
176 splitContainer.Panel2Collapsed = !showPlot.Value;
177 treeView.Invalidate();
180 showValue = new UserOption("valueMenuItem", true, valueMenuItem, settings);
181 showValue.Changed += delegate(object sender, EventArgs e) {
182 treeView.Columns[1].IsVisible = showValue.Value;
185 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
186 showMin.Changed += delegate(object sender, EventArgs e) {
187 treeView.Columns[2].IsVisible = showMin.Value;
190 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
191 showMax.Changed += delegate(object sender, EventArgs e) {
192 treeView.Columns[3].IsVisible = showMax.Value;
195 startMinimized = new UserOption("startMinMenuItem", false, startMinMenuItem, settings);
197 minimizeToTray = new UserOption("minTrayMenuItem", true, minTrayMenuItem, settings);
198 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
199 systemTray.IsMainIconEnabled = minimizeToTray.Value;
202 minimizeOnClose = new UserOption("minCloseMenuItem", false, minCloseMenuItem, settings);
204 autoStart = new UserOption(null, startupManager.Startup, startupMenuItem, settings);
205 autoStart.Changed += delegate(object sender, EventArgs e) {
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;
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);
221 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem, settings);
222 showGadget.Changed += delegate(object sender, EventArgs e) {
224 gadget.Visible = showGadget.Value;
227 celciusMenuItem.Checked =
228 unitManager.TemperatureUnit == TemperatureUnit.Celcius;
229 fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
231 startupMenuItem.Visible = startupManager.IsAvailable;
233 if (startMinMenuItem.Checked) {
234 if (!minTrayMenuItem.Checked) {
235 WindowState = FormWindowState.Minimized;
242 // Create a handle, otherwise calling Close() does not fire FormClosed
243 IntPtr handle = Handle;
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) {
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);
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);
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);
273 foreach (Node node in nodesToRemove)
274 root.Nodes.Remove(node);
277 private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
278 Node node = e.Node.Tag as Node;
281 if (node.IsVisible) {
282 SensorNode sensorNode = node as SensorNode;
283 if (plotMenuItem.Checked && sensorNode != null &&
284 sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
287 e.TextColor = Color.DarkGray;
292 private void UpdatePlotSelection(object sender,
295 List<ISensor> selected = new List<ISensor>();
296 IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
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);
310 sensorPlotColors = colors;
311 plotPanel.SetSensors(selected, colors);
314 private void nodeTextBoxText_EditorShowing(object sender, CancelEventArgs e)
316 e.Cancel = !(treeView.CurrentNode != null &&
317 treeView.CurrentNode.Tag is SensorNode);
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;
328 private void exitClick(object sender, EventArgs e) {
332 private void timer_Tick(object sender, EventArgs e) {
333 computer.Accept(updateVisitor);
334 treeView.Invalidate();
335 plotPanel.Invalidate();
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);
349 foreach (TreeColumn column in treeView.Columns)
350 settings.SetValue("treeView.Columns." + column.Header + ".Width",
353 string fileName = Path.ChangeExtension(
354 System.Windows.Forms.Application.ExecutablePath, ".config");
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);
364 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
368 timer.Enabled = false;
369 systemTray.Dispose();
373 private void aboutMenuItem_Click(object sender, EventArgs e) {
374 new AboutBox().ShowDialog();
377 private void treeView_Click(object sender, EventArgs e) {
379 MouseEventArgs m = e as MouseEventArgs;
380 if (m == null || m.Button != MouseButtons.Right)
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);
394 sensorContextMenu.MenuItems.Add(item);
396 if (nodeTextBoxText.EditEnabled) {
397 MenuItem item = new MenuItem("Rename");
398 item.Click += delegate(object obj, EventArgs args) {
399 nodeTextBoxText.BeginEdit();
401 sensorContextMenu.MenuItems.Add(item);
403 if (node.IsVisible) {
404 MenuItem item = new MenuItem("Hide");
405 item.Click += delegate(object obj, EventArgs args) {
406 node.IsVisible = false;
408 sensorContextMenu.MenuItems.Add(item);
410 MenuItem item = new MenuItem("Unhide");
411 item.Click += delegate(object obj, EventArgs args) {
412 node.IsVisible = true;
414 sensorContextMenu.MenuItems.Add(item);
416 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
418 MenuItem item = new MenuItem("Show in Tray");
419 item.Checked = systemTray.Contains(node.Sensor);
420 item.Click += delegate(object obj, EventArgs args) {
422 systemTray.Remove(node.Sensor);
424 systemTray.Add(node.Sensor, true);
426 sensorContextMenu.MenuItems.Add(item);
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) {
433 gadget.Remove(node.Sensor);
435 gadget.Add(node.Sensor);
438 sensorContextMenu.MenuItems.Add(item);
441 sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
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)) {
455 private void SysTrayHideShow() {
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;
466 if (minimizeToTray.Value &&
467 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
469 } else if(minimizeOnClose.Value &&
470 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
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
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.
479 if (minimizeToTray.Value)
482 WindowState = FormWindowState.Minimized;
488 private void hideShowClick(object sender, EventArgs e) {
492 private void ShowParameterForm(ISensor sensor) {
493 ParameterForm form = new ParameterForm();
494 form.Parameters = sensor.Parameters;
495 form.captionLabel.Text = sensor.Name;
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);
508 private void celciusMenuItem_Click(object sender, EventArgs e) {
509 celciusMenuItem.Checked = true;
510 fahrenheitMenuItem.Checked = false;
511 unitManager.TemperatureUnit = TemperatureUnit.Celcius;
514 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
515 celciusMenuItem.Checked = false;
516 fahrenheitMenuItem.Checked = true;
517 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
520 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
522 ReportForm form = new ReportForm();
523 form.Report = computer.GetReport();
527 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
528 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {