Added more error checking to the T-Balancer enumeration code. This hopefully fixes an IndexOutOfRangeException in the TBalancerGroup constructor.
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 foreach (TreeColumn column in treeView.Columns)
104 column.Width = Math.Max(20, Math.Min(400,
105 settings.GetValue("treeView.Columns." + column.Header + ".Width",
108 treeModel = new TreeModel();
109 root = new Node(System.Environment.MachineName);
110 root.Image = Utilities.EmbeddedResources.GetImage("computer.png");
112 treeModel.Nodes.Add(root);
113 treeView.Model = treeModel;
115 this.computer = new Computer(settings);
117 systemTray = new SystemTray(computer, settings);
118 systemTray.HideShowCommand += hideShowClick;
119 systemTray.ExitCommand += exitClick;
121 int p = (int)Environment.OSVersion.Platform;
122 if ((p == 4) || (p == 128)) { // Unix
123 splitContainer.BorderStyle = BorderStyle.None;
124 splitContainer.Border3DStyle = Border3DStyle.Adjust;
125 splitContainer.SplitterWidth = 4;
126 treeView.BorderStyle = BorderStyle.Fixed3D;
127 plotPanel.BorderStyle = BorderStyle.Fixed3D;
128 gadgetMenuItem.Visible = false;
129 minCloseMenuItem.Visible = false;
131 gadget = new SensorGadget(computer, settings, unitManager);
134 computer.HardwareAdded += new HardwareEventHandler(HardwareAdded);
135 computer.HardwareRemoved += new HardwareEventHandler(HardwareRemoved);
138 timer.Enabled = true;
140 plotColorPalette = new Color[13];
141 plotColorPalette[0] = Color.Blue;
142 plotColorPalette[1] = Color.OrangeRed;
143 plotColorPalette[2] = Color.Green;
144 plotColorPalette[3] = Color.LightSeaGreen;
145 plotColorPalette[4] = Color.Goldenrod;
146 plotColorPalette[5] = Color.DarkViolet;
147 plotColorPalette[6] = Color.YellowGreen;
148 plotColorPalette[7] = Color.SaddleBrown;
149 plotColorPalette[8] = Color.RoyalBlue;
150 plotColorPalette[9] = Color.DeepPink;
151 plotColorPalette[10] = Color.MediumSeaGreen;
152 plotColorPalette[11] = Color.Olive;
153 plotColorPalette[12] = Color.Firebrick;
155 showHiddenSensors = new UserOption("hiddenMenuItem", false, hiddenMenuItem, settings);
156 showHiddenSensors.Changed += delegate(object sender, EventArgs e) {
157 treeModel.ForceVisible = showHiddenSensors.Value;
160 showPlot = new UserOption("plotMenuItem", false, plotMenuItem, settings);
161 showPlot.Changed += delegate(object sender, EventArgs e) {
162 splitContainer.Panel2Collapsed = !showPlot.Value;
163 treeView.Invalidate();
166 showValue = new UserOption("valueMenuItem", true, valueMenuItem, settings);
167 showValue.Changed += delegate(object sender, EventArgs e) {
168 treeView.Columns[1].IsVisible = showValue.Value;
171 showMin = new UserOption("minMenuItem", false, minMenuItem, settings);
172 showMin.Changed += delegate(object sender, EventArgs e) {
173 treeView.Columns[2].IsVisible = showMin.Value;
176 showMax = new UserOption("maxMenuItem", true, maxMenuItem, settings);
177 showMax.Changed += delegate(object sender, EventArgs e) {
178 treeView.Columns[3].IsVisible = showMax.Value;
181 startMinimized = new UserOption("startMinMenuItem", false, startMinMenuItem, settings);
183 minimizeToTray = new UserOption("minTrayMenuItem", true, minTrayMenuItem, settings);
184 minimizeToTray.Changed += delegate(object sender, EventArgs e) {
185 systemTray.IsMainIconEnabled = minimizeToTray.Value;
188 minimizeOnClose = new UserOption("minCloseMenuItem", false, minCloseMenuItem, settings);
190 autoStart = new UserOption(null, startupManager.Startup, startupMenuItem, settings);
191 autoStart.Changed += delegate(object sender, EventArgs e) {
193 startupManager.Startup = autoStart.Value;
194 } catch (InvalidOperationException) {
195 MessageBox.Show("Updating the auto-startup option failed.", "Error",
196 MessageBoxButtons.OK, MessageBoxIcon.Error);
197 autoStart.Value = startupManager.Startup;
201 readHddSensors = new UserOption("hddMenuItem", true, hddMenuItem, settings);
202 readHddSensors.Changed += delegate(object sender, EventArgs e) {
203 computer.HDDEnabled = readHddSensors.Value;
204 UpdatePlotSelection(null, null);
207 showGadget = new UserOption("gadgetMenuItem", false, gadgetMenuItem, settings);
208 showGadget.Changed += delegate(object sender, EventArgs e) {
210 gadget.Visible = showGadget.Value;
213 celciusMenuItem.Checked =
214 unitManager.TemperatureUnit == TemperatureUnit.Celcius;
215 fahrenheitMenuItem.Checked = !celciusMenuItem.Checked;
217 startupMenuItem.Visible = startupManager.IsAvailable;
219 if (startMinMenuItem.Checked) {
220 if (!minTrayMenuItem.Checked) {
221 WindowState = FormWindowState.Minimized;
228 // Create a handle, otherwise calling Close() does not fire FormClosed
229 IntPtr handle = Handle;
231 // Make sure the settings are saved when the user logs off
232 Microsoft.Win32.SystemEvents.SessionEnded +=
233 delegate(object sender, Microsoft.Win32.SessionEndedEventArgs e) {
238 private void SubHardwareAdded(IHardware hardware, Node node) {
239 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
240 node.Nodes.Add(hardwareNode);
241 foreach (IHardware subHardware in hardware.SubHardware)
242 SubHardwareAdded(subHardware, hardwareNode);
245 private void HardwareAdded(IHardware hardware) {
246 Node hardwareNode = new HardwareNode(hardware, settings, unitManager);
247 root.Nodes.Add(hardwareNode);
248 foreach (IHardware subHardware in hardware.SubHardware)
249 SubHardwareAdded(subHardware, hardwareNode);
252 private void HardwareRemoved(IHardware hardware) {
253 List<Node> nodesToRemove = new List<Node>();
254 foreach (Node node in root.Nodes) {
255 HardwareNode hardwareNode = node as HardwareNode;
256 if (hardwareNode != null && hardwareNode.Hardware == hardware)
257 nodesToRemove.Add(node);
259 foreach (Node node in nodesToRemove)
260 root.Nodes.Remove(node);
263 private void nodeTextBoxText_DrawText(object sender, DrawEventArgs e) {
264 Node node = e.Node.Tag as Node;
267 if (node.IsVisible) {
268 SensorNode sensorNode = node as SensorNode;
269 if (plotMenuItem.Checked && sensorNode != null &&
270 sensorPlotColors.TryGetValue(sensorNode.Sensor, out color))
273 e.TextColor = Color.DarkGray;
278 private void UpdatePlotSelection(object sender,
281 List<ISensor> selected = new List<ISensor>();
282 IDictionary<ISensor, Color> colors = new Dictionary<ISensor, Color>();
284 foreach (TreeNodeAdv node in treeView.AllNodes) {
285 SensorNode sensorNode = node.Tag as SensorNode;
286 if (sensorNode != null &&
287 sensorNode.Sensor.SensorType == SensorType.Temperature) {
288 if (sensorNode.Plot) {
289 colors.Add(sensorNode.Sensor,
290 plotColorPalette[colorIndex % plotColorPalette.Length]);
291 selected.Add(sensorNode.Sensor);
296 sensorPlotColors = colors;
297 plotPanel.SetSensors(selected, colors);
300 private void nodeTextBoxText_EditorShowing(object sender, CancelEventArgs e)
302 e.Cancel = !(treeView.CurrentNode != null &&
303 treeView.CurrentNode.Tag is SensorNode);
306 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
307 NodeControlValueEventArgs e) {
308 SensorNode node = e.Node.Tag as SensorNode;
309 e.Value = (node != null) &&
310 (node.Sensor.SensorType == SensorType.Temperature) &&
311 plotMenuItem.Checked;
314 private void exitClick(object sender, EventArgs e) {
318 private void timer_Tick(object sender, EventArgs e) {
319 computer.Accept(updateVisitor);
320 treeView.Invalidate();
321 plotPanel.Invalidate();
327 private void SaveConfiguration() {
328 if (WindowState != FormWindowState.Minimized) {
329 settings.SetValue("mainForm.Location.X", Bounds.X);
330 settings.SetValue("mainForm.Location.Y", Bounds.Y);
331 settings.SetValue("mainForm.Width", Bounds.Width);
332 settings.SetValue("mainForm.Height", Bounds.Height);
335 foreach (TreeColumn column in treeView.Columns)
336 settings.SetValue("treeView.Columns." + column.Header + ".Width",
339 string fileName = Path.ChangeExtension(
340 System.Windows.Forms.Application.ExecutablePath, ".config");
342 settings.Save(fileName);
343 } catch (UnauthorizedAccessException) {
344 MessageBox.Show("Access to the path '" + fileName + "' is denied. " +
345 "The current seetings could not be saved.",
346 "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
350 private void MainForm_Load(object sender, EventArgs e) {
351 Rectangle newBounds = new Rectangle {
352 X = settings.GetValue("mainForm.Location.X", Location.X),
353 Y = settings.GetValue("mainForm.Location.Y", Location.Y),
354 Width = settings.GetValue("mainForm.Width", 470),
355 Height = settings.GetValue("mainForm.Height", 640)
358 Rectangle totalWorkingArea = new Rectangle(int.MaxValue, int.MaxValue,
359 int.MinValue, int.MinValue);
361 foreach (Screen screen in Screen.AllScreens)
362 totalWorkingArea = Rectangle.Union(totalWorkingArea, screen.Bounds);
364 Rectangle intersection = Rectangle.Intersect(totalWorkingArea, newBounds);
365 if (intersection.Width < 20 || intersection.Height < 20 ||
366 !settings.Contains("mainForm.Location.X")
368 newBounds.X = (Screen.PrimaryScreen.WorkingArea.Width / 2) -
371 newBounds.Y = (Screen.PrimaryScreen.WorkingArea.Height / 2) -
372 (newBounds.Height / 2);
375 this.Bounds = newBounds;
378 private void MainForm_FormClosed(object sender, FormClosedEventArgs e) {
382 timer.Enabled = false;
383 systemTray.Dispose();
387 private void aboutMenuItem_Click(object sender, EventArgs e) {
388 new AboutBox().ShowDialog();
391 private void treeView_Click(object sender, EventArgs e) {
393 MouseEventArgs m = e as MouseEventArgs;
394 if (m == null || m.Button != MouseButtons.Right)
397 NodeControlInfo info = treeView.GetNodeControlInfoAt(new Point(m.X, m.Y));
398 treeView.SelectedNode = info.Node;
399 if (info.Node != null) {
400 SensorNode node = info.Node.Tag as SensorNode;
401 if (node != null && node.Sensor != null) {
402 sensorContextMenu.MenuItems.Clear();
403 if (node.Sensor.Parameters.Length > 0) {
404 MenuItem item = new MenuItem("Parameters...");
405 item.Click += delegate(object obj, EventArgs args) {
406 ShowParameterForm(node.Sensor);
408 sensorContextMenu.MenuItems.Add(item);
410 if (nodeTextBoxText.EditEnabled) {
411 MenuItem item = new MenuItem("Rename");
412 item.Click += delegate(object obj, EventArgs args) {
413 nodeTextBoxText.BeginEdit();
415 sensorContextMenu.MenuItems.Add(item);
417 if (node.IsVisible) {
418 MenuItem item = new MenuItem("Hide");
419 item.Click += delegate(object obj, EventArgs args) {
420 node.IsVisible = false;
422 sensorContextMenu.MenuItems.Add(item);
424 MenuItem item = new MenuItem("Unhide");
425 item.Click += delegate(object obj, EventArgs args) {
426 node.IsVisible = true;
428 sensorContextMenu.MenuItems.Add(item);
430 sensorContextMenu.MenuItems.Add(new MenuItem("-"));
432 MenuItem item = new MenuItem("Show in Tray");
433 item.Checked = systemTray.Contains(node.Sensor);
434 item.Click += delegate(object obj, EventArgs args) {
436 systemTray.Remove(node.Sensor);
438 systemTray.Add(node.Sensor, true);
440 sensorContextMenu.MenuItems.Add(item);
442 if (gadget != null) {
443 MenuItem item = new MenuItem("Show in Gadget");
444 item.Checked = gadget.Contains(node.Sensor);
445 item.Click += delegate(object obj, EventArgs args) {
447 gadget.Remove(node.Sensor);
449 gadget.Add(node.Sensor);
452 sensorContextMenu.MenuItems.Add(item);
455 sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
460 private void saveReportMenuItem_Click(object sender, EventArgs e) {
461 string report = computer.GetReport();
462 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
463 using (TextWriter w = new StreamWriter(saveFileDialog.FileName)) {
469 private void SysTrayHideShow() {
475 protected override void WndProc(ref Message m) {
476 const int WM_SYSCOMMAND = 0x112;
477 const int SC_MINIMIZE = 0xF020;
478 const int SC_CLOSE = 0xF060;
480 if (minimizeToTray.Value &&
481 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_MINIMIZE) {
483 } else if(minimizeOnClose.Value &&
484 m.Msg == WM_SYSCOMMAND && m.WParam.ToInt32() == SC_CLOSE) {
486 * Apparently the user wants to minimize rather than close
487 * Now we still need to check if we're going to the tray or not
489 * Note: the correct way to do this would be to send out SC_MINIMIZE,
490 * but since the code here is so simple,
491 * that would just be a waste of time.
493 if (minimizeToTray.Value)
496 WindowState = FormWindowState.Minimized;
502 private void hideShowClick(object sender, EventArgs e) {
506 private void ShowParameterForm(ISensor sensor) {
507 ParameterForm form = new ParameterForm();
508 form.Parameters = sensor.Parameters;
509 form.captionLabel.Text = sensor.Name;
513 private void treeView_NodeMouseDoubleClick(object sender,
514 TreeNodeAdvMouseEventArgs e) {
515 SensorNode node = e.Node.Tag as SensorNode;
516 if (node != null && node.Sensor != null &&
517 node.Sensor.Parameters.Length > 0) {
518 ShowParameterForm(node.Sensor);
522 private void celciusMenuItem_Click(object sender, EventArgs e) {
523 celciusMenuItem.Checked = true;
524 fahrenheitMenuItem.Checked = false;
525 unitManager.TemperatureUnit = TemperatureUnit.Celcius;
528 private void fahrenheitMenuItem_Click(object sender, EventArgs e) {
529 celciusMenuItem.Checked = false;
530 fahrenheitMenuItem.Checked = true;
531 unitManager.TemperatureUnit = TemperatureUnit.Fahrenheit;
534 private void sumbitReportMenuItem_Click(object sender, EventArgs e)
536 ReportForm form = new ReportForm();
537 form.Report = computer.GetReport();
541 private void resetMinMaxMenuItem_Click(object sender, EventArgs e) {
542 computer.Accept(new SensorVisitor(delegate(ISensor sensor) {