From 9d1660270272180cd71147d6ddd53d1382643d2e Mon Sep 17 00:00:00 2001
From: wenxiangchao <wenxiangchao@ihengxin.com.cn>
Date: 星期一, 02 十一月 2026 18:00:14 +0800
Subject: [PATCH] merge: 并入远程 Initial commit 作为历史根节点
---
Plugin.TestResult/Chart.xaml.cs | 496 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 496 insertions(+), 0 deletions(-)
diff --git a/Plugin.TestResult/Chart.xaml.cs b/Plugin.TestResult/Chart.xaml.cs
new file mode 100644
index 0000000..ffd5c46
--- /dev/null
+++ b/Plugin.TestResult/Chart.xaml.cs
@@ -0,0 +1,496 @@
+锘縰sing log4net.Repository.Hierarchy;
+using Plugin.TestResult_WPF.Model;
+using ScottPlot;
+using ScottPlot.Plottables;
+using ScottPlot.TickGenerators;
+using System;
+using System.Collections.Generic;
+using System.Data.SqlTypes;
+using System.Linq;
+using System.Text;
+using System.Timers;
+using System.Windows.Controls;
+using System.Windows.Documents;
+using System.Xml.Linq;
+
+namespace Plugin.TestResult_WPF
+{
+ /// <summary>
+ /// Chart.xaml 鐨勪氦浜掗�昏緫
+ /// </summary>
+ /// <summary>
+ /// Chart.xaml 鐨勪氦浜掗�昏緫
+ /// </summary>
+ public partial class Chart : UserControl
+ {
+ private readonly int maxSize;
+
+ private readonly Queue<long> xData;
+ private readonly Queue<double> yData;
+
+ private readonly Dictionary<string, Queue<long>> xValues;
+ private readonly Dictionary<string, Queue<double>> yValues;
+
+ private readonly Dictionary<DataLogger, double> maxValue = new Dictionary<DataLogger, double>();
+ private readonly Dictionary<DataLogger, double> minValue = new Dictionary<DataLogger, double>();
+
+ private readonly string title;
+ private readonly bool multi;
+ private readonly int refreshInterval;
+
+ private double maxYValue = -1;
+ private double minYValue = double.MaxValue;
+ private float fontSize = -1;
+
+ private Timer timer;
+
+ private LinePlot[] childrenPlot;
+
+ private readonly Dictionary<string, DataLogger> loggers = new Dictionary<string, DataLogger>();
+
+ private DataLogger InitLogger()
+ {
+ DataLogger logger = chart.Plot.Add.DataLogger();
+ //logger.ViewSlide(maxSize * 5);
+ logger.ViewFull();
+ //logger.Add(new Coordinates(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), 0));
+ return logger;
+ }
+
+ public Chart(string title, bool multi, float titleSize)
+ {
+ BaseConfig config = new BaseConfig();
+ this.title = title;
+ this.maxSize = config.MaxSize;
+ this.multi = multi;
+ this.refreshInterval = config.RefreshInterval;
+ this.fontSize = titleSize;
+
+
+ InitializeComponent();
+ if (this.multi)
+ {
+ xValues = new Dictionary<string, Queue<long>>();
+ yValues = new Dictionary<string, Queue<double>>();
+ //chart.Plot.ShowLegend(Alignment.UpperLeft, Orientation.Vertical);
+ var legend = chart.Plot.ShowLegend(Edge.Top);
+ legend.Alignment = Alignment.UpperLeft;
+ legend.Padding = new PixelPadding(0);
+ }
+ else
+ {
+ xData = new Queue<long>(maxSize);
+ yData = new Queue<double>(maxSize);
+ }
+
+ chart.Plot.Axes.Left.TickLabelStyle.FontSize = 12;
+ chart.Plot.Axes.Left.Label.FontSize = 15;
+ chart.Plot.Axes.Bottom.TickLabelStyle.FontSize = 12;
+ chart.Plot.Axes.Bottom.TickLabelStyle.IsVisible = false;
+ chart.Plot.Axes.Bottom.MajorTickStyle.Color = Colors.Transparent;
+ chart.Plot.Axes.Bottom.MinorTickStyle.Color = Colors.Transparent;
+
+ /// 绂佺敤榧犳爣
+ chart.UserInputProcessor.Disable();
+ //chart.Plot.Layout.Frameless();
+
+
+ //Streamer1 = chart.Plot.Add.DataStreamer(maxSize);
+ //Streamer1.ViewScrollLeft();
+ //Streamer1.Color = Colors.Green;
+
+ //chart.Plot.Add.Scatter(xData.ToArray(), yData.ToArray());
+
+
+
+
+ //string CustomFormatter(DateTime dt)
+ //{
+ // return dt.ToString("HH:mm:ss.fff");
+ //}
+ //var axis = chart.Plot.Axes.DateTimeTicksBottom();
+ //var tickGen = (DateTimeAutomatic)axis.TickGenerator;
+ //tickGen.LabelFormatter = CustomFormatter;
+
+ //chart.Plot.Axes.Bottom.TickGenerator = new DateTimeAutomatic();
+ //chart.Plot.Axes.DateTimeTicksBottom();
+ //chart.Plot.RenderManager.RenderStarting += (s, e) =>
+ //{
+ // try
+ // {
+ // Tick[] ticks = chart.Plot.Axes.Bottom.TickGenerator.Ticks;
+ // for (int i = 0; i < ticks.Length; i++)
+ // {
+ // long ms = ticks[i].Position < 0 ? 0 : (long)ticks[i].Position;
+ // DateTime dt = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)).AddMilliseconds(ms);
+ // string label = $"{dt:hh:mm:ss.fff}";
+ // ticks[i] = new Tick(ticks[i].Position, label);
+ // }
+ // }
+ // catch (Exception ex)
+ // {
+
+ // }
+ //};
+
+ string CustomFormatter(double position)
+ {
+ if (position > 0)
+ return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddMilliseconds(position).ToString("HH:mm:ss");
+ return "";
+ }
+ EvenlySpacedMinorTickGenerator minorTickGen = new EvenlySpacedMinorTickGenerator(10);
+ NumericAutomatic myTickGenerator = new NumericAutomatic()
+ {
+ LabelFormatter = CustomFormatter,
+ MinorTickGenerator = minorTickGen
+ };
+ chart.Plot.Axes.Bottom.TickGenerator = myTickGenerator;
+ if (!string.IsNullOrEmpty(this.title))
+ {
+ chart.Plot.Axes.Left.Label.Text = this.title;
+ chart.Plot.Axes.Left.Label.Bold = false;
+ chart.Plot.Font.Automatic();
+ //RefreshData();
+ }
+
+ /// 璁剧疆鍒锋柊瀹氭椂鍣�
+ //refreshTimer = new System.Timers.Timer() { Interval = this.refreshInterval, AutoReset = true };
+ //refreshTimer.Elapsed += RefreshTimer_Elapsed;
+
+ //chart.Plot.DataBackground.Color = new Color(0, 0, 0);
+ //chart.Plot.Grid.MajorLineColor = Colors.Green.WithOpacity(.6);
+ //chart.Plot.Grid.MajorLineWidth = 1;
+ //chart.Plot.Grid.MinorLineColor = Colors.Gray.WithOpacity(.3);
+ //chart.Plot.Grid.MinorLineWidth = 1;
+
+ //chart.Plot.Axes.Bottom.TickLabelStyle.IsVisible = false;
+ //chart.Plot.Axes.Bottom.MajorTickStyle.Length = 0;
+ //chart.Plot.Axes.Left.TickLabelStyle.IsVisible = false;
+ //chart.Plot.Axes.Left.MajorTickStyle.Length = 0;
+
+ //chart.Plot.Axes.Bottom.FrameLineStyle.Width = 0;
+ //chart.Plot.Axes.Left.FrameLineStyle.Width = 0;
+ //chart.Plot.Axes.Top.FrameLineStyle.Width = 0;
+ //chart.Plot.Axes.Right.FrameLineStyle.Width = 0;
+
+ timer = new Timer();
+ timer.Interval = this.refreshInterval;
+ timer.Elapsed += Timer_Elapsed;
+ }
+
+ public Chart(string title, string[] serials, float titleSize)
+ {
+ BaseConfig config = new BaseConfig();
+ this.title = title;
+ this.multi = true;
+ this.maxSize = config.MaxSize;
+ this.refreshInterval = config.RefreshInterval;
+ fontSize = titleSize;
+
+ childrenPlot = new LinePlot[serials.Length];
+
+ InitializeComponent();
+
+ xValues = new Dictionary<string, Queue<long>>();
+ yValues = new Dictionary<string, Queue<double>>();
+ //chart.Plot.ShowLegend(Alignment.UpperLeft, Orientation.Vertical);
+ var panel = chart.Plot.ShowLegend(Edge.Top);
+ panel.Alignment = Alignment.UpperLeft;
+ panel.Padding = new PixelPadding(0);
+
+ chart.Plot.Axes.Left.TickLabelStyle.FontSize = titleSize - 3;
+ chart.Plot.Axes.Left.Label.FontSize = titleSize;
+
+ chart.Plot.Axes.Right.TickLabelStyle.FontSize = titleSize - 3;
+ chart.Plot.Axes.Right.Label.FontSize = titleSize;
+
+ chart.Plot.Axes.Bottom.TickLabelStyle.FontSize = titleSize - 3;
+ chart.Plot.Axes.Bottom.TickLabelStyle.IsVisible = false;
+ chart.Plot.Axes.Bottom.MajorTickStyle.Color = Colors.Transparent;
+ chart.Plot.Axes.Bottom.MinorTickStyle.Color = Colors.Transparent;
+
+ /// 绂佺敤榧犳爣
+ chart.UserInputProcessor.Disable();
+
+ string CustomFormatter(double position)
+ {
+ if (position > 0)
+ return TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddMilliseconds(position).ToString("HH:mm:ss");
+ return "";
+ }
+ chart.Plot.HideLegend();
+
+ EvenlySpacedMinorTickGenerator minorTickGen = new EvenlySpacedMinorTickGenerator(10);
+ NumericAutomatic myTickGenerator = new NumericAutomatic()
+ {
+ LabelFormatter = CustomFormatter,
+ MinorTickGenerator = minorTickGen
+ };
+ chart.Plot.Axes.Bottom.TickGenerator = myTickGenerator;
+ if (!string.IsNullOrEmpty(serials[0]))
+ {
+ var newLine = chart.Plot.Add.Line(Coordinates.NaN, Coordinates.NaN);
+ newLine.Axes.YAxis = chart.Plot.Axes.Left;
+ newLine.Axes.XAxis = chart.Plot.Axes.Bottom;
+
+ childrenPlot[0] = newLine;
+ chart.Plot.Axes.Left.Label.Text = serials[0];
+ chart.Plot.Axes.Left.Label.Bold = false;
+ chart.Plot.Font.Automatic();
+ }
+
+ if (!string.IsNullOrEmpty(serials[1]))
+ {
+ var newLine = chart.Plot.Add.Line(Coordinates.NaN, Coordinates.NaN);
+ newLine.Axes.YAxis = chart.Plot.Axes.Right;
+ newLine.Axes.XAxis = chart.Plot.Axes.Bottom;
+
+ childrenPlot[1] = newLine;
+ chart.Plot.Axes.Right.Label.Text = serials[1];
+ chart.Plot.Axes.Right.Label.Bold = false;
+ chart.Plot.Font.Automatic();
+ }
+
+ timer = new Timer();
+ timer.Interval = this.refreshInterval;
+ timer.Elapsed += Timer_Elapsed;
+ }
+
+ private void Timer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ if (maxYValue > 0)
+ {
+ RefreshData();
+ }
+ }
+
+ private DataLogger GetLogger(string name, out bool isNew, string legend = null)
+ {
+ isNew = false;
+ if (!loggers.ContainsKey(name))
+ {
+ var logger = InitLogger();
+ if (legend != null) logger.LegendText = name;
+ loggers.Add(name, logger);
+ isNew = true;
+ }
+ return loggers[name];
+ }
+
+ public void RefreshData()
+ {
+ bool flag = timer.Enabled;
+ try
+ {
+ timer.Enabled = false;
+ foreach (var logger in loggers.Values)
+ {
+ logger.ViewFull();
+ }
+
+ /// 闄愬埗y杞�
+ if (maxYValue > -1)
+ {
+ chart.Plot.Axes.SetLimitsY(minYValue > 5 ? minYValue - 5 : 0, maxYValue + 5);
+ }
+ else
+ {
+ chart.Plot.Axes.SetLimitsY(0, 100);
+ }
+ chart.Refresh();
+ }
+ finally
+ {
+ timer.Enabled = flag;
+ }
+ }
+
+ public void Clear()
+ {
+ this.maxYValue = -1;
+ this.minYValue = double.MaxValue;
+ foreach (var name in loggers.Keys)
+ {
+ loggers[name].Clear();
+ xValues?[name]?.Clear();
+ yValues?[name]?.Clear();
+ }
+ xData?.Clear();
+ yData?.Clear();
+ chart.Refresh();
+ }
+
+ public List<double> GetSingleData()
+ {
+ bool flag = timer.Enabled;
+ try
+ {
+ timer.Enabled = false;
+ return yData?.ToList();
+ }
+ finally
+ {
+ timer.Enabled = flag;
+ }
+ }
+
+ private void InsertData(Queue<long> xAxis, Queue<double> yAxis, long x, double y)
+ {
+ if (xAxis.Count >= maxSize)
+ {
+ xAxis.Dequeue();
+ yAxis.Dequeue();
+ }
+ xAxis.Enqueue(x);
+ yAxis.Enqueue(y);
+ }
+
+ public void AddData(double y)
+ {
+ if (this.multi)
+ {
+ return;
+ }
+ var commonName = "Single";
+ this.maxYValue = y > maxYValue ? y : maxYValue;
+ this.minYValue = y < minYValue ? y : minYValue;
+
+ var nowTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ DataLogger singleLogger = GetLogger(commonName, out _);
+ singleLogger.Color = Colors.Red;
+ InsertData(xData, yData, nowTime, y);
+ singleLogger.Add(new Coordinates(nowTime, y));
+
+ //Streamer1.Add(new Coordinates(DateTimeOffset.Now.ToUnixTimeSeconds(), y));
+
+ chart.Plot.GetPlottables<Marker>()
+ .ToList()
+ .ForEach(m => m.X -= 1);
+ chart.Plot.GetPlottables<Marker>()
+ .Where(m => m.X < 0)
+ .ToList()
+ .ForEach(m => chart.Plot.Remove(m));
+ }
+
+ public void AddData(string name, double y)
+ {
+ if (!this.multi)
+ {
+ return;
+ }
+
+ this.maxYValue = y > maxYValue ? y : maxYValue;
+ this.minYValue = y < minYValue ? y : minYValue;
+ DataLogger logger = null;
+ if (loggers.ContainsKey(name))
+ {
+ logger = loggers[name];
+ }
+ else
+ {
+ logger = InitLogger();
+ logger.LegendText = name;
+ loggers.Add(name, logger);
+ var xAxis = new Queue<long>(maxSize);
+ var yAxis = new Queue<double>(maxSize);
+
+ xValues.Add(name, xAxis);
+ yValues.Add(name, yAxis);
+ }
+
+ var x = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ logger.Add(new Coordinates(x, y));
+ InsertData(xValues[name], yValues[name], x, y);
+
+ //Streamer1.Add(new Coordinates(DateTimeOffset.Now.ToUnixTimeSeconds(), y));
+
+ chart.Plot.GetPlottables<Marker>()
+ .ToList()
+ .ForEach(m => m.X -= 1);
+ chart.Plot.GetPlottables<Marker>()
+ .Where(m => m.X < 0)
+ .ToList()
+ .ForEach(m => chart.Plot.Remove(m));
+ }
+
+ public void AddData(int serials, string name, double y)
+ {
+ if (!this.multi)
+ {
+ return;
+ }
+ var plot = childrenPlot[serials];
+
+ DataLogger logger = GetLogger(name, out bool isNew, name);
+ this.maxYValue = y > maxYValue ? y : maxYValue;
+ this.minYValue = y < minYValue ? y : minYValue;
+
+ logger.Axes.YAxis = plot.Axes.YAxis;
+ logger.Axes.XAxis = plot.Axes.XAxis;
+ if (name == "姘寸娓╁害")
+ {
+ logger.Color = Colors.Red;
+ }
+ else if (name == "鍥炴按娓╁害")
+ {
+ logger.Color = Colors.Blue;
+ }
+ else
+ {
+ logger.Color = Colors.Green;
+ }
+
+ if (isNew)
+ {
+ var xAxis = new Queue<long>(maxSize);
+ var yAxis = new Queue<double>(maxSize);
+
+ xValues.Add(name, xAxis);
+ yValues.Add(name, yAxis);
+ }
+
+ var x = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+ logger.Add(new Coordinates(x, y));
+ InsertData(xValues[name], yValues[name], x, y);
+
+ //Streamer1.Add(new Coordinates(DateTimeOffset.Now.ToUnixTimeSeconds(), y));
+
+ chart.Plot.GetPlottables<Marker>()
+ .ToList()
+ .ForEach(m => m.X -= 1);
+ chart.Plot.GetPlottables<Marker>()
+ .Where(m => m.X < 0)
+ .ToList()
+ .ForEach(m => chart.Plot.Remove(m));
+ }
+
+ private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
+ {
+ //refreshTimer.Start();
+ timer?.Start();
+ }
+
+ private void UserControl_Unloaded(object sender, System.Windows.RoutedEventArgs e)
+ {
+ timer?.Stop();
+ }
+
+ private void UserControl_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
+ {
+ if (this.multi) return;
+ if (fontSize < 0)
+ {
+ chart.Plot.Axes.Left.Label.FontSize = (float)FontSizeConverter.CountFontSize(15, ActualHeight, 92);
+ chart.Plot.Axes.Left.TickLabelStyle.FontSize = (float)FontSizeConverter.CountFontSize(10, ActualHeight, 92);
+ chart.Plot.Axes.Bottom.TickLabelStyle.FontSize = (float)FontSizeConverter.CountFontSize(10, ActualHeight, 92);
+ }
+ else
+ {
+ chart.Plot.Axes.Left.Label.FontSize = fontSize - 3;
+ chart.Plot.Axes.Left.TickLabelStyle.FontSize = fontSize - 3;
+ chart.Plot.Axes.Bottom.TickLabelStyle.FontSize = fontSize;
+ }
+ }
+ }
+}
--
Gitblit v1.9.1