Added the new OxyPlot based plot implementation.
1.1 --- a/Collections/ListSet.cs Sat Jun 08 17:15:09 2013 +0000
1.2 +++ b/Collections/ListSet.cs Sun Jun 09 16:08:59 2013 +0000
1.3 @@ -4,7 +4,7 @@
1.4 License, v. 2.0. If a copy of the MPL was not distributed with this
1.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
1.6
1.7 - Copyright (C) 2009-2010 Michael Möller <mmoeller@openhardwaremonitor.org>
1.8 + Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
1.9
1.10 */
1.11
1.12 @@ -48,5 +48,11 @@
1.13 IEnumerator IEnumerable.GetEnumerator() {
1.14 return list.GetEnumerator();
1.15 }
1.16 +
1.17 + public int Count {
1.18 + get {
1.19 + return list.Count;
1.20 + }
1.21 + }
1.22 }
1.23 }
2.1 --- a/GUI/AboutBox.Designer.cs Sat Jun 08 17:15:09 2013 +0000
2.2 +++ b/GUI/AboutBox.Designer.cs Sun Jun 09 16:08:59 2013 +0000
2.3 @@ -4,7 +4,7 @@
2.4 License, v. 2.0. If a copy of the MPL was not distributed with this
2.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
2.6
2.7 - Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
2.8 + Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
2.9
2.10 */
2.11
2.12 @@ -84,7 +84,7 @@
2.13 this.label2.Name = "label2";
2.14 this.label2.Size = new System.Drawing.Size(273, 13);
2.15 this.label2.TabIndex = 3;
2.16 - this.label2.Text = "Copyright © 2009-2012 Michael Möller and contributers. ";
2.17 + this.label2.Text = "Copyright © 2009-2013 Michael Möller and contributers. ";
2.18 //
2.19 // label3
2.20 //
3.1 --- a/GUI/MainForm.cs Sat Jun 08 17:15:09 2013 +0000
3.2 +++ b/GUI/MainForm.cs Sun Jun 09 16:08:59 2013 +0000
3.3 @@ -4,7 +4,7 @@
3.4 License, v. 2.0. If a copy of the MPL was not distributed with this
3.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
3.6
3.7 - Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
3.8 + Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
3.9 Copyright (C) 2010 Paul Werelds <paul@werelds.net>
3.10 Copyright (C) 2012 Prince Samuel <prince.samuel@gmail.com>
3.11
3.12 @@ -459,8 +459,7 @@
3.13 int colorIndex = 0;
3.14 foreach (TreeNodeAdv node in treeView.AllNodes) {
3.15 SensorNode sensorNode = node.Tag as SensorNode;
3.16 - if (sensorNode != null &&
3.17 - sensorNode.Sensor.SensorType == SensorType.Temperature) {
3.18 + if (sensorNode != null) {
3.19 if (sensorNode.Plot) {
3.20 colors.Add(sensorNode.Sensor,
3.21 plotColorPalette[colorIndex % plotColorPalette.Length]);
3.22 @@ -484,9 +483,7 @@
3.23 private void nodeCheckBox_IsVisibleValueNeeded(object sender,
3.24 NodeControlValueEventArgs e) {
3.25 SensorNode node = e.Node.Tag as SensorNode;
3.26 - e.Value = (node != null) &&
3.27 - (node.Sensor.SensorType == SensorType.Temperature) &&
3.28 - plotMenuItem.Checked;
3.29 + e.Value = (node != null) && plotMenuItem.Checked;
3.30 }
3.31
3.32 private void exitClick(object sender, EventArgs e) {
3.33 @@ -496,7 +493,7 @@
3.34 private void timer_Tick(object sender, EventArgs e) {
3.35 computer.Accept(updateVisitor);
3.36 treeView.Invalidate();
3.37 - plotPanel.Invalidate();
3.38 + plotPanel.InvalidatePlot();
3.39 systemTray.Redraw();
3.40 if (gadget != null)
3.41 gadget.Redraw();
3.42 @@ -506,6 +503,7 @@
3.43 }
3.44
3.45 private void SaveConfiguration() {
3.46 + plotPanel.SetCurrentSettings();
3.47 foreach (TreeColumn column in treeView.Columns)
3.48 settings.SetValue("treeView.Columns." + column.Header + ".Width",
3.49 column.Width);
4.1 --- a/GUI/PlotPanel.cs Sat Jun 08 17:15:09 2013 +0000
4.2 +++ b/GUI/PlotPanel.cs Sun Jun 09 16:08:59 2013 +0000
4.3 @@ -4,277 +4,200 @@
4.4 License, v. 2.0. If a copy of the MPL was not distributed with this
4.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
4.6
4.7 - Copyright (C) 2009-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
4.8 + Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
4.9
4.10 */
4.11
4.12 using System;
4.13 using System.Collections.Generic;
4.14 -using System.ComponentModel;
4.15 using System.Drawing;
4.16 -using System.Drawing.Drawing2D;
4.17 +using System.Linq;
4.18 using System.Windows.Forms;
4.19 using OpenHardwareMonitor.Hardware;
4.20 +using OxyPlot;
4.21 +using OxyPlot.Axes;
4.22 +using OxyPlot.WindowsForms;
4.23 +using OxyPlot.Series;
4.24 +using OpenHardwareMonitor.Collections;
4.25
4.26 namespace OpenHardwareMonitor.GUI {
4.27 public class PlotPanel : UserControl {
4.28
4.29 private PersistentSettings settings;
4.30
4.31 + private readonly Plot plot;
4.32 + private readonly PlotModel model;
4.33 + private readonly TimeSpanAxis timeAxis = new TimeSpanAxis();
4.34 + private readonly SortedDictionary<SensorType, LinearAxis> axes =
4.35 + new SortedDictionary<SensorType, LinearAxis>();
4.36 +
4.37 private DateTime now;
4.38 - private List<ISensor> clocks = new List<ISensor>();
4.39 - private List<ISensor> temperatures = new List<ISensor>();
4.40 - private List<ISensor> fans = new List<ISensor>();
4.41 - private IDictionary<ISensor, Color> colors;
4.42 -
4.43 - private StringFormat centerlower;
4.44 - private StringFormat centerleft;
4.45 - private StringFormat lowerleft;
4.46 - private Brush lightBrush;
4.47 - private Pen lightPen;
4.48 -
4.49 - private UserRadioGroup timeWindowRadioGroup;
4.50
4.51 public PlotPanel(PersistentSettings settings) {
4.52 this.settings = settings;
4.53 + this.model = CreatePlotModel();
4.54
4.55 - this.SetStyle(ControlStyles.DoubleBuffer |
4.56 - ControlStyles.UserPaint |
4.57 - ControlStyles.AllPaintingInWmPaint |
4.58 - ControlStyles.ResizeRedraw, true);
4.59 - this.UpdateStyles();
4.60 + this.plot = new Plot();
4.61 + this.plot.Dock = DockStyle.Fill;
4.62 + this.plot.Model = model;
4.63 + this.plot.BackColor = Color.White;
4.64 + this.plot.ContextMenu = new ContextMenu();
4.65 + this.plot.ContextMenu.MenuItems.Add(CreateMenu());
4.66
4.67 - CreateContextMenu();
4.68 -
4.69 - centerlower = new StringFormat();
4.70 - centerlower.Alignment = StringAlignment.Center;
4.71 - centerlower.LineAlignment = StringAlignment.Near;
4.72 -
4.73 - centerleft = new StringFormat();
4.74 - centerleft.Alignment = StringAlignment.Far;
4.75 - centerleft.LineAlignment = StringAlignment.Center;
4.76 -
4.77 - lowerleft = new StringFormat();
4.78 - lowerleft.Alignment = StringAlignment.Far;
4.79 - lowerleft.LineAlignment = StringAlignment.Near;
4.80 -
4.81 - lightBrush = new SolidBrush(Color.FromArgb(245, 245, 245));
4.82 - lightPen = new Pen(Color.FromArgb(200, 200, 200));
4.83 + this.SuspendLayout();
4.84 + this.Controls.Add(plot);
4.85 + this.ResumeLayout(true);
4.86 }
4.87
4.88 - private void CreateContextMenu() {
4.89 - MenuItem timeWindow = new MenuItem("Time Scale");
4.90 -
4.91 - MenuItem[] timeWindowMenuItems =
4.92 - { new MenuItem("Auto"),
4.93 - new MenuItem("5 min"),
4.94 - new MenuItem("10 min"),
4.95 - new MenuItem("20 min"),
4.96 - new MenuItem("30 min"),
4.97 - new MenuItem("45 min"),
4.98 - new MenuItem("1 h"),
4.99 - new MenuItem("1.5 h"),
4.100 - new MenuItem("2 h"),
4.101 - new MenuItem("3 h"),
4.102 - new MenuItem("6 h"),
4.103 - new MenuItem("12 h"),
4.104 - new MenuItem("24 h") };
4.105 + public void SetCurrentSettings() {
4.106 + settings.SetValue("plotPanel.MinTimeSpan", (float)timeAxis.ViewMinimum);
4.107 + settings.SetValue("plotPanel.MaxTimeSpan", (float)timeAxis.ViewMaximum);
4.108 +
4.109 + foreach (var axis in axes.Values) {
4.110 + settings.SetValue("plotPanel.Min" + axis.Key, (float)axis.ViewMinimum);
4.111 + settings.SetValue("plotPanel.Max" + axis.Key, (float)axis.ViewMaximum);
4.112 + }
4.113 + }
4.114 +
4.115 + private MenuItem CreateMenu() {
4.116 + MenuItem timeWindow = new MenuItem("Time Window");
4.117 +
4.118 + MenuItem[] timeWindowMenuItems =
4.119 + { new MenuItem("Auto",
4.120 + (s, e) => { timeAxis.Zoom(0, double.NaN); InvalidatePlot(); }),
4.121 + new MenuItem("5 min",
4.122 + (s, e) => { timeAxis.Zoom(0, 5 * 60); InvalidatePlot(); }),
4.123 + new MenuItem("10 min",
4.124 + (s, e) => { timeAxis.Zoom(0, 10 * 60); InvalidatePlot(); }),
4.125 + new MenuItem("20 min",
4.126 + (s, e) => { timeAxis.Zoom(0, 20 * 60); InvalidatePlot(); }),
4.127 + new MenuItem("30 min",
4.128 + (s, e) => { timeAxis.Zoom(0, 30 * 60); InvalidatePlot(); }),
4.129 + new MenuItem("45 min",
4.130 + (s, e) => { timeAxis.Zoom(0, 45 * 60); InvalidatePlot(); }),
4.131 + new MenuItem("1 h",
4.132 + (s, e) => { timeAxis.Zoom(0, 60 * 60); InvalidatePlot(); }),
4.133 + new MenuItem("1.5 h",
4.134 + (s, e) => { timeAxis.Zoom(0, 1.5 * 60 * 60); InvalidatePlot(); }),
4.135 + new MenuItem("2 h",
4.136 + (s, e) => { timeAxis.Zoom(0, 2 * 60 * 60); InvalidatePlot(); }),
4.137 + new MenuItem("3 h",
4.138 + (s, e) => { timeAxis.Zoom(0, 3 * 60 * 60); InvalidatePlot(); }),
4.139 + new MenuItem("6 h",
4.140 + (s, e) => { timeAxis.Zoom(0, 6 * 60 * 60); InvalidatePlot(); }),
4.141 + new MenuItem("12 h",
4.142 + (s, e) => { timeAxis.Zoom(0, 12 * 60 * 60); InvalidatePlot(); }),
4.143 + new MenuItem("24 h",
4.144 + (s, e) => { timeAxis.Zoom(0, 24 * 60 * 60); InvalidatePlot(); }) };
4.145
4.146 foreach (MenuItem mi in timeWindowMenuItems)
4.147 timeWindow.MenuItems.Add(mi);
4.148
4.149 - timeWindowRadioGroup = new UserRadioGroup("timeWindow", 0,
4.150 - timeWindowMenuItems, settings);
4.151 -
4.152 - this.ContextMenu = new ContextMenu();
4.153 - this.ContextMenu.MenuItems.Add(timeWindow);
4.154 + return timeWindow;
4.155 }
4.156
4.157 - private List<float> GetTemperatureGrid() {
4.158 + private PlotModel CreatePlotModel() {
4.159
4.160 - float? minTempNullable = null;
4.161 - float? maxTempNullable = null;
4.162 - foreach (ISensor sensor in temperatures) {
4.163 - IEnumerable<SensorValue> values = sensor.Values;
4.164 - foreach (SensorValue value in values) {
4.165 - if (!float.IsNaN(value.Value)) {
4.166 - if (!minTempNullable.HasValue || minTempNullable > value.Value)
4.167 - minTempNullable = value.Value;
4.168 - if (!maxTempNullable.HasValue || maxTempNullable < value.Value)
4.169 - maxTempNullable = value.Value;
4.170 - }
4.171 - }
4.172 - }
4.173 - if (!minTempNullable.HasValue) {
4.174 - minTempNullable = 20;
4.175 - maxTempNullable = 30;
4.176 + timeAxis.Position = AxisPosition.Bottom;
4.177 + timeAxis.MajorGridlineStyle = LineStyle.Solid;
4.178 + timeAxis.MajorGridlineThickness = 1;
4.179 + timeAxis.MajorGridlineColor = OxyColor.FromRgb(192, 192, 192);
4.180 + timeAxis.MinorGridlineStyle = LineStyle.Solid;
4.181 + timeAxis.MinorGridlineThickness = 1;
4.182 + timeAxis.MinorGridlineColor = OxyColor.FromRgb(232, 232, 232);
4.183 + timeAxis.StartPosition = 1;
4.184 + timeAxis.EndPosition = 0;
4.185 + timeAxis.MinimumPadding = 0;
4.186 + timeAxis.MaximumPadding = 0;
4.187 + timeAxis.AbsoluteMinimum = 0;
4.188 + timeAxis.Minimum = 0;
4.189 + timeAxis.AbsoluteMaximum = 24 * 60 * 60;
4.190 + timeAxis.Zoom(
4.191 + settings.GetValue("plotPanel.MinTimeSpan", 0.0f),
4.192 + settings.GetValue("plotPanel.MaxTimeSpan", 10.0f * 60));
4.193 + timeAxis.StringFormat = "h:mm";
4.194 +
4.195 + var units = new Dictionary<SensorType, string>();
4.196 + units.Add(SensorType.Voltage, "V");
4.197 + units.Add(SensorType.Clock, "MHz");
4.198 + units.Add(SensorType.Temperature, "°C");
4.199 + units.Add(SensorType.Load, "%");
4.200 + units.Add(SensorType.Fan, "RPM");
4.201 + units.Add(SensorType.Flow, "L/h");
4.202 + units.Add(SensorType.Control, "%");
4.203 + units.Add(SensorType.Level, "%");
4.204 + units.Add(SensorType.Factor, "1");
4.205 + units.Add(SensorType.Power, "W");
4.206 + units.Add(SensorType.Data, "GB");
4.207 +
4.208 + foreach (SensorType type in Enum.GetValues(typeof(SensorType))) {
4.209 + var axis = new LinearAxis();
4.210 + axis.Position = AxisPosition.Left;
4.211 + axis.MajorGridlineStyle = LineStyle.Solid;
4.212 + axis.MajorGridlineThickness = 1;
4.213 + axis.MajorGridlineColor = timeAxis.MajorGridlineColor;
4.214 + axis.MinorGridlineStyle = LineStyle.Solid;
4.215 + axis.MinorGridlineThickness = 1;
4.216 + axis.MinorGridlineColor = timeAxis.MinorGridlineColor;
4.217 + axis.Title = type.ToString();
4.218 + axis.Key = type.ToString();
4.219 +
4.220 + axis.Zoom(
4.221 + settings.GetValue("plotPanel.Min" + axis.Key, float.NaN),
4.222 + settings.GetValue("plotPanel.Max" + axis.Key, float.NaN));
4.223 +
4.224 + if (units.ContainsKey(type))
4.225 + axis.Unit = units[type];
4.226 + axes.Add(type, axis);
4.227 }
4.228
4.229 - float maxTemp = (float)Math.Ceiling(maxTempNullable.Value / 10) * 10;
4.230 - float minTemp = (float)Math.Floor(minTempNullable.Value / 10) * 10;
4.231 - if (maxTemp == minTemp)
4.232 - maxTemp += 10;
4.233 + var model = new PlotModel();
4.234 + model.Axes.Add(timeAxis);
4.235 + foreach (var axis in axes.Values)
4.236 + model.Axes.Add(axis);
4.237 + model.PlotMargins = new OxyThickness(0);
4.238 + model.IsLegendVisible = false;
4.239
4.240 - int countTempMax = 4;
4.241 - float deltaTemp = maxTemp - minTemp;
4.242 - int countTemp = (int)Math.Round(deltaTemp / 2);
4.243 - if (countTemp > countTempMax)
4.244 - countTemp = (int)Math.Round(deltaTemp / 5);
4.245 - if (countTemp > countTempMax)
4.246 - countTemp = (int)Math.Round(deltaTemp / 10);
4.247 - if (countTemp > countTempMax)
4.248 - countTemp = (int)Math.Round(deltaTemp / 20);
4.249 -
4.250 - List<float> grid = new List<float>(countTemp + 1);
4.251 - for (int i = 0; i <= countTemp; i++) {
4.252 - grid.Add(minTemp + i * deltaTemp / countTemp);
4.253 - }
4.254 - return grid;
4.255 - }
4.256 -
4.257 - private List<float> GetTimeGrid() {
4.258 -
4.259 - float maxTime;
4.260 - if (timeWindowRadioGroup.Value == 0) { // Auto
4.261 - maxTime = 5;
4.262 - if (temperatures.Count > 0) {
4.263 - IEnumerator<SensorValue> enumerator =
4.264 - temperatures[0].Values.GetEnumerator();
4.265 - if (enumerator.MoveNext()) {
4.266 - maxTime = (float)(now - enumerator.Current.Time).TotalMinutes;
4.267 - }
4.268 - }
4.269 - } else {
4.270 - float[] maxTimes =
4.271 - { 5, 10, 20, 30, 45, 60, 90, 120, 180, 360, 720, 1440 };
4.272 -
4.273 - maxTime = maxTimes[timeWindowRadioGroup.Value - 1];
4.274 - }
4.275 -
4.276 - int countTime = 10;
4.277 - float deltaTime = 5;
4.278 - while (deltaTime + 1 <= maxTime && deltaTime < 10)
4.279 - deltaTime += 1;
4.280 - while (deltaTime + 2 <= maxTime && deltaTime < 30)
4.281 - deltaTime += 2;
4.282 - while (deltaTime + 5 <= maxTime && deltaTime < 100)
4.283 - deltaTime += 5;
4.284 - while (deltaTime + 50 <= maxTime && deltaTime < 1000)
4.285 - deltaTime += 50;
4.286 - while (deltaTime + 100 <= maxTime && deltaTime < 10000)
4.287 - deltaTime += 100;
4.288 -
4.289 - List<float> grid = new List<float>(countTime + 1);
4.290 - for (int i = 0; i <= countTime; i++) {
4.291 - grid.Add(i * deltaTime / countTime);
4.292 - }
4.293 - return grid;
4.294 - }
4.295 -
4.296 - protected override void OnPaint(PaintEventArgs e) {
4.297 - now = DateTime.UtcNow - new TimeSpan(0, 0, 4);
4.298 -
4.299 - List<float> timeGrid = GetTimeGrid();
4.300 - List<float> tempGrid = GetTemperatureGrid();
4.301 -
4.302 - Graphics g = e.Graphics;
4.303 -
4.304 - RectangleF r =
4.305 - new RectangleF(0, 0, Bounds.Width, Bounds.Height);
4.306 -
4.307 - float ml = 40;
4.308 - float mr = 15;
4.309 - float x0 = r.X + ml;
4.310 - float w = r.Width - ml - mr;
4.311 -
4.312 - float mt = 15;
4.313 - float mb = 28;
4.314 - float y0 = r.Y + mt;
4.315 - float h = r.Height - mt - mb;
4.316 -
4.317 - float leftScaleSpace = 5;
4.318 - float bottomScaleSpace = 5;
4.319 -
4.320 - g.Clear(Color.White);
4.321 -
4.322 - if (w > 0 && h > 0) {
4.323 - g.FillRectangle(lightBrush, x0, y0, w, h);
4.324 -
4.325 - g.SmoothingMode = SmoothingMode.HighQuality;
4.326 - for (int i = 0; i < timeGrid.Count; i++) {
4.327 - float x = x0 + i * w / (timeGrid.Count - 1);
4.328 - g.DrawLine(lightPen, x, y0, x, y0 + h);
4.329 - }
4.330 -
4.331 - for (int i = 0; i < tempGrid.Count; i++) {
4.332 - float y = y0 + i * h / (tempGrid.Count - 1);
4.333 - g.DrawLine(lightPen, x0, y, x0 + w, y);
4.334 - }
4.335 -
4.336 - float deltaTemp = tempGrid[tempGrid.Count - 1] - tempGrid[0];
4.337 - float deltaTime = timeGrid[timeGrid.Count - 1];
4.338 - foreach (ISensor sensor in temperatures) {
4.339 - using (Pen pen = new Pen(colors[sensor])) {
4.340 - IEnumerable<SensorValue> values = sensor.Values;
4.341 - PointF last = new PointF();
4.342 - bool first = true;
4.343 - foreach (SensorValue v in values) {
4.344 - if (!float.IsNaN(v.Value)) {
4.345 - PointF point = new PointF(
4.346 - x0 + w - w * (float)(now - v.Time).TotalMinutes / deltaTime,
4.347 - y0 + h - h * (v.Value - tempGrid[0]) / deltaTemp);
4.348 - if (!first)
4.349 - g.DrawLine(pen, last, point);
4.350 - last = point;
4.351 - first = false;
4.352 - } else {
4.353 - first = true;
4.354 - }
4.355 - }
4.356 - }
4.357 - }
4.358 -
4.359 - g.SmoothingMode = SmoothingMode.None;
4.360 - g.FillRectangle(Brushes.White, 0, 0, x0, r.Height);
4.361 - g.FillRectangle(Brushes.White, x0 + w + 1, 0, r.Width - x0 - w,
4.362 - r.Height);
4.363 -
4.364 - for (int i = 1; i < timeGrid.Count; i++) {
4.365 - float x = x0 + (timeGrid.Count - 1 - i) * w / (timeGrid.Count - 1);
4.366 - g.DrawString(timeGrid[i].ToString(), Font, Brushes.Black, x,
4.367 - y0 + h + bottomScaleSpace, centerlower);
4.368 - }
4.369 -
4.370 - for (int i = 0; i < tempGrid.Count - 1; i++) {
4.371 - float y = y0 + (tempGrid.Count - 1 - i) * h / (tempGrid.Count - 1);
4.372 - g.DrawString(tempGrid[i].ToString(), Font, Brushes.Black,
4.373 - x0 - leftScaleSpace, y, centerleft);
4.374 - }
4.375 -
4.376 - g.SmoothingMode = SmoothingMode.HighQuality;
4.377 - g.DrawString("[°C]", Font, Brushes.Black, x0 - leftScaleSpace, y0,
4.378 - lowerleft);
4.379 - g.DrawString("[min]", Font, Brushes.Black, x0 + w,
4.380 - y0 + h + bottomScaleSpace, lowerleft);
4.381 - }
4.382 + return model;
4.383 }
4.384
4.385 public void SetSensors(List<ISensor> sensors,
4.386 IDictionary<ISensor, Color> colors) {
4.387 - this.colors = colors;
4.388 - List<ISensor> clocks = new List<ISensor>();
4.389 - List<ISensor> temperatures = new List<ISensor>();
4.390 - List<ISensor> fans = new List<ISensor>();
4.391 - foreach (ISensor sensor in sensors)
4.392 - switch (sensor.SensorType) {
4.393 - case SensorType.Clock: clocks.Add(sensor); break;
4.394 - case SensorType.Temperature: temperatures.Add(sensor); break;
4.395 - case SensorType.Fan: fans.Add(sensor); break;
4.396 - }
4.397 - this.clocks = clocks;
4.398 - this.temperatures = temperatures;
4.399 - this.fans = fans;
4.400 - Invalidate();
4.401 + this.model.Series.Clear();
4.402 +
4.403 + ListSet<SensorType> types = new ListSet<SensorType>();
4.404 +
4.405 + foreach (ISensor sensor in sensors) {
4.406 + var series = new LineSeries();
4.407 + series.ItemsSource = sensor.Values.Select(value => new DataPoint {
4.408 + X = (now - value.Time).TotalSeconds, Y = value.Value
4.409 + });
4.410 + series.Color = colors[sensor].ToOxyColor();
4.411 + series.StrokeThickness = 1;
4.412 + series.YAxisKey = axes[sensor.SensorType].Key;
4.413 + series.Title = sensor.Hardware.Name + " " + sensor.Name;
4.414 + this.model.Series.Add(series);
4.415 +
4.416 + types.Add(sensor.SensorType);
4.417 + }
4.418 +
4.419 + var start = 0.0;
4.420 + foreach (var pair in axes.Reverse()) {
4.421 + var axis = pair.Value;
4.422 + var type = pair.Key;
4.423 + axis.StartPosition = start;
4.424 + axis.IsAxisVisible = types.Contains(type);
4.425 + var delta = axis.IsAxisVisible ? 1.0 / types.Count : 0;
4.426 + start += delta;
4.427 + axis.EndPosition = start;
4.428 + }
4.429 +
4.430 + InvalidatePlot();
4.431 + }
4.432 +
4.433 + public void InvalidatePlot() {
4.434 + this.now = DateTime.UtcNow;
4.435 + this.plot.InvalidatePlot(true);
4.436 }
4.437
4.438 }
5.1 --- a/OpenHardwareMonitor.csproj Sat Jun 08 17:15:09 2013 +0000
5.2 +++ b/OpenHardwareMonitor.csproj Sun Jun 09 16:08:59 2013 +0000
5.3 @@ -58,6 +58,12 @@
5.4 <CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
5.5 </PropertyGroup>
5.6 <ItemGroup>
5.7 + <Reference Include="OxyPlot">
5.8 + <HintPath>External\OxyPlot.dll</HintPath>
5.9 + </Reference>
5.10 + <Reference Include="OxyPlot.WindowsForms">
5.11 + <HintPath>External\OxyPlot.WindowsForms.dll</HintPath>
5.12 + </Reference>
5.13 <Reference Include="System" />
5.14 <Reference Include="System.Configuration.Install" />
5.15 <Reference Include="System.Drawing" />
6.1 --- a/Properties/AssemblyInfo.cs Sat Jun 08 17:15:09 2013 +0000
6.2 +++ b/Properties/AssemblyInfo.cs Sun Jun 09 16:08:59 2013 +0000
6.3 @@ -4,7 +4,7 @@
6.4 License, v. 2.0. If a copy of the MPL was not distributed with this
6.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
6.6
6.7 - Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
6.8 + Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
6.9
6.10 */
6.11
6.12 @@ -18,7 +18,7 @@
6.13 [assembly: AssemblyConfiguration("")]
6.14 [assembly: AssemblyCompany("")]
6.15 [assembly: AssemblyProduct("Open Hardware Monitor")]
6.16 -[assembly: AssemblyCopyright("Copyright © 2009-2012 Michael Möller")]
6.17 +[assembly: AssemblyCopyright("Copyright © 2009-2013 Michael Möller")]
6.18 [assembly: AssemblyTrademark("")]
6.19 [assembly: AssemblyCulture("")]
6.20
7.1 --- a/Properties/AssemblyLibInfo.cs Sat Jun 08 17:15:09 2013 +0000
7.2 +++ b/Properties/AssemblyLibInfo.cs Sun Jun 09 16:08:59 2013 +0000
7.3 @@ -4,7 +4,7 @@
7.4 License, v. 2.0. If a copy of the MPL was not distributed with this
7.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7.6
7.7 - Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
7.8 + Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
7.9
7.10 */
7.11
7.12 @@ -17,7 +17,7 @@
7.13 [assembly: AssemblyConfiguration("")]
7.14 [assembly: AssemblyCompany("")]
7.15 [assembly: AssemblyProduct("Open Hardware Monitor Library")]
7.16 -[assembly: AssemblyCopyright("Copyright © 2009-2012 Michael Möller")]
7.17 +[assembly: AssemblyCopyright("Copyright © 2009-2013 Michael Möller")]
7.18 [assembly: AssemblyTrademark("")]
7.19 [assembly: AssemblyCulture("")]
7.20
8.1 --- a/Properties/AssemblyVersion.cs Sat Jun 08 17:15:09 2013 +0000
8.2 +++ b/Properties/AssemblyVersion.cs Sun Jun 09 16:08:59 2013 +0000
8.3 @@ -4,11 +4,11 @@
8.4 License, v. 2.0. If a copy of the MPL was not distributed with this
8.5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
8.6
8.7 - Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
8.8 + Copyright (C) 2009-2013 Michael Möller <mmoeller@openhardwaremonitor.org>
8.9
8.10 */
8.11
8.12 using System.Reflection;
8.13
8.14 -[assembly: AssemblyVersion("0.5.1.10")]
8.15 -[assembly: AssemblyInformationalVersion("0.5.1.10 Alpha")]
8.16 \ No newline at end of file
8.17 +[assembly: AssemblyVersion("0.5.1.13")]
8.18 +[assembly: AssemblyInformationalVersion("0.5.1.13 Alpha")]
8.19 \ No newline at end of file