GUI/PlotPanel.cs
author moel.mich
Sun, 25 Apr 2010 14:40:19 +0000
changeset 97 1a2d7dad320e
child 158 119693c3b7d1
permissions -rw-r--r--
Fixed Issue 43.
     1 /*
     2   
     3   Version: MPL 1.1/GPL 2.0/LGPL 2.1
     4 
     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
     8  
     9   http://www.mozilla.org/MPL/
    10 
    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.
    14 
    15   The Original Code is the Open Hardware Monitor code.
    16 
    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.
    21 
    22   Contributor(s):
    23 
    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.
    35  
    36 */
    37 
    38 using System;
    39 using System.Collections.Generic;
    40 using System.ComponentModel;
    41 using System.Drawing;
    42 using System.Drawing.Drawing2D;
    43 using System.Windows.Forms;
    44 using OpenHardwareMonitor.Hardware;
    45 
    46 namespace OpenHardwareMonitor.GUI {
    47   public partial class PlotPanel : UserControl {
    48 
    49     private DateTime now;
    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;
    54 
    55     private StringFormat centerlower;
    56     private StringFormat centerleft;
    57     private StringFormat lowerleft;
    58     private Brush lightBrush;
    59     private Pen lightPen;
    60 
    61     public PlotPanel() {
    62       this.SetStyle(ControlStyles.DoubleBuffer |
    63         ControlStyles.UserPaint |
    64         ControlStyles.AllPaintingInWmPaint | 
    65         ControlStyles.ResizeRedraw, true);
    66       this.UpdateStyles();
    67 
    68       InitializeComponent();
    69 
    70       centerlower = new StringFormat();
    71       centerlower.Alignment = StringAlignment.Center;
    72       centerlower.LineAlignment = StringAlignment.Near;
    73 
    74       centerleft = new StringFormat();
    75       centerleft.Alignment = StringAlignment.Far;
    76       centerleft.LineAlignment = StringAlignment.Center;
    77 
    78       lowerleft = new StringFormat();
    79       lowerleft.Alignment = StringAlignment.Far;
    80       lowerleft.LineAlignment = StringAlignment.Near;
    81 
    82       lightBrush = new SolidBrush(Color.FromArgb(245, 245, 245));
    83       lightPen = new Pen(Color.FromArgb(200, 200, 200));
    84     }
    85 
    86     private List<float> GetTemperatureGrid() {
    87 
    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;
    97         }
    98       }
    99       if (!minTempNullable.HasValue) {
   100         minTempNullable = 20;
   101         maxTempNullable = 30;
   102       }
   103 
   104       float maxTemp = (float)Math.Ceiling(maxTempNullable.Value / 10) * 10;
   105       float minTemp = (float)Math.Floor(minTempNullable.Value / 10) * 10;
   106       if (maxTemp == minTemp) 
   107         maxTemp += 10;   
   108      
   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);
   118 
   119       List<float> grid = new List<float>(countTemp + 1);
   120       for (int i = 0; i <= countTemp; i++) {
   121         grid.Add(minTemp + i * deltaTemp / countTemp);
   122       }
   123       return grid;
   124     }
   125 
   126     private List<float> GetTimeGrid() {
   127 
   128       float maxTime = 5;      
   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;
   134         }
   135       }
   136 
   137       int countTime = 10;
   138       float deltaTime = 5;
   139       while (deltaTime + 1 < maxTime && deltaTime < 10)
   140         deltaTime += 1;
   141       while (deltaTime + 2 < maxTime && deltaTime < 30)
   142         deltaTime += 2;
   143       while (deltaTime + 5 < maxTime && deltaTime < 100)
   144         deltaTime += 5;
   145 
   146       List<float> grid = new List<float>(countTime + 1);
   147       for (int i = 0; i <= countTime; i++) {
   148         grid.Add(i * deltaTime / countTime);
   149       }
   150       return grid;
   151     }
   152 
   153     protected override void OnPaint(PaintEventArgs e) {
   154 
   155       now = DateTime.Now - new TimeSpan(0, 0, 4);
   156 
   157       List<float> timeGrid = GetTimeGrid();
   158       List<float> tempGrid = GetTemperatureGrid();
   159 
   160       Graphics g = e.Graphics;
   161 
   162       RectangleF r =
   163         new RectangleF(0, 0, Bounds.Width, Bounds.Height);
   164 
   165       float ml = 40;
   166       float mr = 15;
   167       float x0 = r.X + ml;
   168       float w = r.Width - ml - mr;
   169 
   170       float mt = 15;
   171       float mb = 28;
   172       float y0 = r.Y + mt;
   173       float h = r.Height - mt - mb;
   174 
   175       float leftScaleSpace = 5;
   176       float bottomScaleSpace = 5;
   177       
   178       g.Clear(Color.White);
   179 
   180       if (w > 0 && h > 0) {
   181         g.FillRectangle(lightBrush, x0, y0, w, h);
   182 
   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);
   187         }
   188 
   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);
   192         }
   193 
   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();
   200             bool first = true;
   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);
   205               if (!first)
   206                 g.DrawLine(pen, last, point);
   207               last = point;
   208               first = false;
   209             }
   210           }
   211         }
   212 
   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, 
   216           r.Height);
   217 
   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);
   222         }
   223 
   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);
   228         }
   229 
   230         g.SmoothingMode = SmoothingMode.HighQuality;
   231         g.DrawString("[°C]", Font, Brushes.Black, x0 - leftScaleSpace, y0,
   232           lowerleft);        
   233         g.DrawString("[min]", Font, Brushes.Black, x0 + w,
   234           y0 + h + bottomScaleSpace, lowerleft);        
   235       }
   236     }
   237 
   238     public void SetSensors(List<ISensor> sensors, 
   239       IDictionary<ISensor, Color> colors) 
   240     {
   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;
   250         }
   251       this.clocks = clocks;
   252       this.temperatures = temperatures;
   253       this.fans = fans;
   254       Invalidate();
   255     }
   256 
   257   }
   258 }