Fixed Issue 91.
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;
42 using System.Drawing.Drawing2D;
43 using System.Windows.Forms;
44 using OpenHardwareMonitor.Hardware;
46 namespace OpenHardwareMonitor.GUI {
47 public partial class PlotPanel : UserControl {
50 private List<ISensor> clocks = new List<ISensor>();
51 private List<ISensor> temperatures = new List<ISensor>();
52 private List<ISensor> fans = new List<ISensor>();
53 private IDictionary<ISensor, Color> colors;
55 private StringFormat centerlower;
56 private StringFormat centerleft;
57 private StringFormat lowerleft;
58 private Brush lightBrush;
62 this.SetStyle(ControlStyles.DoubleBuffer |
63 ControlStyles.UserPaint |
64 ControlStyles.AllPaintingInWmPaint |
65 ControlStyles.ResizeRedraw, true);
68 InitializeComponent();
70 centerlower = new StringFormat();
71 centerlower.Alignment = StringAlignment.Center;
72 centerlower.LineAlignment = StringAlignment.Near;
74 centerleft = new StringFormat();
75 centerleft.Alignment = StringAlignment.Far;
76 centerleft.LineAlignment = StringAlignment.Center;
78 lowerleft = new StringFormat();
79 lowerleft.Alignment = StringAlignment.Far;
80 lowerleft.LineAlignment = StringAlignment.Near;
82 lightBrush = new SolidBrush(Color.FromArgb(245, 245, 245));
83 lightPen = new Pen(Color.FromArgb(200, 200, 200));
86 private List<float> GetTemperatureGrid() {
88 float? minTempNullable = null;
89 float? maxTempNullable = null;
90 foreach (ISensor sensor in temperatures) {
91 IEnumerable<ISensorEntry> graph = sensor.Plot;
92 foreach (ISensorEntry entry in graph) {
93 if (!minTempNullable.HasValue || minTempNullable > entry.Value)
94 minTempNullable = entry.Value;
95 if (!maxTempNullable.HasValue || maxTempNullable < entry.Value)
96 maxTempNullable = entry.Value;
99 if (!minTempNullable.HasValue) {
100 minTempNullable = 20;
101 maxTempNullable = 30;
104 float maxTemp = (float)Math.Ceiling(maxTempNullable.Value / 10) * 10;
105 float minTemp = (float)Math.Floor(minTempNullable.Value / 10) * 10;
106 if (maxTemp == minTemp)
109 int countTempMax = 4;
110 float deltaTemp = maxTemp - minTemp;
111 int countTemp = (int)Math.Round(deltaTemp / 2);
112 if (countTemp > countTempMax)
113 countTemp = (int)Math.Round(deltaTemp / 5);
114 if (countTemp > countTempMax)
115 countTemp = (int)Math.Round(deltaTemp / 10);
116 if (countTemp > countTempMax)
117 countTemp = (int)Math.Round(deltaTemp / 20);
119 List<float> grid = new List<float>(countTemp + 1);
120 for (int i = 0; i <= countTemp; i++) {
121 grid.Add(minTemp + i * deltaTemp / countTemp);
126 private List<float> GetTimeGrid() {
129 if (temperatures.Count > 0) {
130 IEnumerator<ISensorEntry> enumerator =
131 temperatures[0].Plot.GetEnumerator();
132 if (enumerator.MoveNext()) {
133 maxTime = (float)(now - enumerator.Current.Time).TotalMinutes;
139 while (deltaTime + 1 < maxTime && deltaTime < 10)
141 while (deltaTime + 2 < maxTime && deltaTime < 30)
143 while (deltaTime + 5 < maxTime && deltaTime < 100)
146 List<float> grid = new List<float>(countTime + 1);
147 for (int i = 0; i <= countTime; i++) {
148 grid.Add(i * deltaTime / countTime);
153 protected override void OnPaint(PaintEventArgs e) {
155 now = DateTime.Now - new TimeSpan(0, 0, 4);
157 List<float> timeGrid = GetTimeGrid();
158 List<float> tempGrid = GetTemperatureGrid();
160 Graphics g = e.Graphics;
163 new RectangleF(0, 0, Bounds.Width, Bounds.Height);
168 float w = r.Width - ml - mr;
173 float h = r.Height - mt - mb;
175 float leftScaleSpace = 5;
176 float bottomScaleSpace = 5;
178 g.Clear(Color.White);
180 if (w > 0 && h > 0) {
181 g.FillRectangle(lightBrush, x0, y0, w, h);
183 g.SmoothingMode = SmoothingMode.HighQuality;
184 for (int i = 0; i < timeGrid.Count; i++) {
185 float x = x0 + i * w / (timeGrid.Count - 1);
186 g.DrawLine(lightPen, x, y0, x, y0 + h);
189 for (int i = 0; i < tempGrid.Count; i++) {
190 float y = y0 + i * h / (tempGrid.Count - 1);
191 g.DrawLine(lightPen, x0, y, x0 + w, y);
194 float deltaTemp = tempGrid[tempGrid.Count - 1] - tempGrid[0];
195 float deltaTime = timeGrid[timeGrid.Count - 1];
196 foreach (ISensor sensor in temperatures) {
197 using (Pen pen = new Pen(colors[sensor])) {
198 IEnumerable<ISensorEntry> graph = sensor.Plot;
199 PointF last = new PointF();
201 foreach (ISensorEntry entry in graph) {
202 PointF point = new PointF(
203 x0 + w - w * (float)(now - entry.Time).TotalMinutes / deltaTime,
204 y0 + h - h * (entry.Value - tempGrid[0]) / deltaTemp);
206 g.DrawLine(pen, last, point);
213 g.SmoothingMode = SmoothingMode.None;
214 g.FillRectangle(Brushes.White, 0, 0, x0, r.Height);
215 g.FillRectangle(Brushes.White, x0 + w + 1, 0, r.Width - x0 - w,
218 for (int i = 1; i < timeGrid.Count; i++) {
219 float x = x0 + (timeGrid.Count - 1 - i) * w / (timeGrid.Count - 1);
220 g.DrawString(timeGrid[i].ToString(), Font, Brushes.Black, x,
221 y0 + h + bottomScaleSpace, centerlower);
224 for (int i = 0; i < tempGrid.Count - 1; i++) {
225 float y = y0 + (tempGrid.Count - 1 - i) * h / (tempGrid.Count - 1);
226 g.DrawString(tempGrid[i].ToString(), Font, Brushes.Black,
227 x0 - leftScaleSpace, y, centerleft);
230 g.SmoothingMode = SmoothingMode.HighQuality;
231 g.DrawString("[°C]", Font, Brushes.Black, x0 - leftScaleSpace, y0,
233 g.DrawString("[min]", Font, Brushes.Black, x0 + w,
234 y0 + h + bottomScaleSpace, lowerleft);
238 public void SetSensors(List<ISensor> sensors,
239 IDictionary<ISensor, Color> colors)
241 this.colors = colors;
242 List<ISensor> clocks = new List<ISensor>();
243 List<ISensor> temperatures = new List<ISensor>();
244 List<ISensor> fans = new List<ISensor>();
245 foreach (ISensor sensor in sensors)
246 switch (sensor.SensorType) {
247 case SensorType.Clock: clocks.Add(sensor); break;
248 case SensorType.Temperature: temperatures.Add(sensor); break;
249 case SensorType.Fan: fans.Add(sensor); break;
251 this.clocks = clocks;
252 this.temperatures = temperatures;