AnalogSignalPreviewViewModel.cs 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. using Avalonia.Collections;
  2. using Avalonia.Controls;
  3. using IViewModel.Models;
  4. using IViewModel.Tools;
  5. using IViewModel.ViewModels;
  6. using OxyPlot;
  7. using OxyPlot.Axes;
  8. using OxyPlot.Series;
  9. using Shaker.Model;
  10. using System;
  11. using System.Collections.Generic;
  12. using System.Diagnostics.CodeAnalysis;
  13. using System.Linq;
  14. using System.Text;
  15. using System.Threading.Tasks;
  16. namespace Dynamicloadsimulationdevice.ViewModels
  17. {
  18. internal sealed class AnalogSignalPreviewViewModel:DisplayViewModelBase,IDataPreview
  19. {
  20. public string AttachTitle
  21. {
  22. get => attachTitle;
  23. set
  24. {
  25. if (attachTitle == value) return;
  26. attachTitle = value;
  27. UpdatePlotTitle(SelectedAnalog);
  28. }
  29. }
  30. List<OxyPlot.Series.LineSeries> lineSeries = new List<OxyPlot.Series.LineSeries>();
  31. private object locker = new object();
  32. public AvaloniaList<ViewModels.StatisticsViewModel> Statistics { get; } = new AvaloniaList<StatisticsViewModel>();
  33. private ResultChannelType selectedAnalog;
  34. private bool canChangedAnalog = true;
  35. public bool StatisticsVisibily { get => statisticsVisibily; set =>SetProperty(ref statisticsVisibily , value); }
  36. public AnalogSignalPreviewViewModel(bool createcontrol = false):base()
  37. {
  38. Content = typeof(Views.AnalogSignalPreviewView);
  39. if(createcontrol)
  40. {
  41. Control = (Control)Activator.CreateInstance(Content)!;
  42. }
  43. PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
  44. {
  45. MaximumPadding = 0,
  46. MinimumPadding = 0,
  47. Title = LanguageValueViewModel.Instance.Time,
  48. Unit = "s",
  49. Key = "X",
  50. MajorGridlineStyle = OxyPlot.LineStyle.Solid,
  51. Position = OxyPlot.Axes.AxisPosition.Bottom
  52. });
  53. PlotModel.Axes.Add(new OxyPlot.Axes.LinearAxis()
  54. {
  55. Title = LanguageValueViewModel.Instance.Ampt,
  56. Unit = "V",
  57. Key = "Y",
  58. MajorGridlineStyle = OxyPlot.LineStyle.Solid,
  59. Position = OxyPlot.Axes.AxisPosition.Left,
  60. });
  61. UpdatePlotTitle(lasttype);
  62. PlotModel.Legends.Add(new OxyPlot.Legends.Legend()
  63. {
  64. ShowInvisibleSeries = true,
  65. });
  66. PlotController.BindMouseWheel(OxyMouseWheelCommand);
  67. GetEvent(Topic.DATA).Subscrip((_, _) =>
  68. {
  69. if (!UpSignalData) return;
  70. lock(locker)
  71. {
  72. var data = ShakerDataViewModel.Instance.GetAnalogData(SelectedAnalog);
  73. PlotModel.InvalidatePlot(false);
  74. for(int i=0;i<data.Count;i++)
  75. {
  76. lineSeries[i].ItemsSource = data[i].Item1;
  77. Statistics[i].UpDateModel(data[i].Item2);
  78. }
  79. PlotModel.InvalidatePlot(true);
  80. }
  81. });
  82. GetEvent(Topic.InitSeries).Subscrip((_, _) =>
  83. {
  84. lock(locker)
  85. {
  86. Menu.Clear();
  87. ShakerChannelViewModel.Instance.ResultChannels
  88. .DistinctBy(x=>x.Value.ChannelType)
  89. .ToList()
  90. .ForEach(x =>
  91. {
  92. Menu.Add(new TimeDomainMenuViewModel()
  93. {
  94. IsChecked = false,
  95. IsEnabled = true,
  96. AnalogType = x.Value.ChannelType,
  97. Unit = x.Value.Unit,
  98. });
  99. });
  100. if (CanChangedAnalog)
  101. {
  102. int index = Menu.ToList().FindIndex(x => x.AnalogType == lasttype);
  103. if (index == -1)
  104. {
  105. SelectedAnalog = Menu.First().AnalogType;
  106. }
  107. else
  108. {
  109. SelectedAnalog = lasttype;
  110. }
  111. }
  112. else
  113. {
  114. SelectedAnalog = lasttype;
  115. }
  116. }
  117. });
  118. GetEvent(IViewModel.ViewModels.LanguageViewModel.LANGUAGECHANGEDEVENT).Subscrip((_, _) =>
  119. {
  120. PlotModel.InvalidatePlot(false);
  121. PlotModel.Axes[0].Title = LanguageValueViewModel.Instance.Time;
  122. PlotModel.Axes[1].Title = LanguageValueViewModel.Instance.Ampt;
  123. UpdatePlotTitle(SelectedAnalog);
  124. var config = ShakerChannelViewModel.Instance.ResultChannels.FirstOrDefault(x => x.Value.ChannelType == SelectedAnalog);
  125. if (config == null) return;
  126. for(int i=0;i<PlotModel.Series.Count;i++)
  127. {
  128. PlotModel.Series[i].Title = LanguageValueViewModel.Instance[config.Value.Name];
  129. }
  130. });
  131. }
  132. [AllowNull]
  133. public Control Control { get; }
  134. private ResultChannelType lasttype = ResultChannelType.ActualDisplacement;
  135. private bool statisticsVisibily = true;
  136. private string attachTitle = string.Empty;
  137. private void UpdatePlotTitle(ResultChannelType analogType)
  138. {
  139. PlotModel.Title = string.IsNullOrEmpty(AttachTitle) ? LanguageValueViewModel.Instance[analogType.Description()] : $"{LanguageValueViewModel.Instance[AttachTitle]}-{LanguageValueViewModel.Instance[analogType.Description()]}";
  140. }
  141. public AvaloniaList<TimeDomainMenuViewModel> Menu { get; } = new AvaloniaList<TimeDomainMenuViewModel>();
  142. public AnalogSignalPreviewViewModel(ResultChannelType analogType,bool createcontrol = false):this(createcontrol)
  143. {
  144. lasttype = analogType;
  145. }
  146. public ResultChannelType SelectedAnalog
  147. {
  148. get => selectedAnalog;
  149. set
  150. {
  151. SetProperty(ref selectedAnalog, value);
  152. ChangeAnalogType(value);
  153. }
  154. }
  155. public bool UpSignalData { get; set; } = true;
  156. private void ChangeAnalogType(ResultChannelType type)
  157. {
  158. lock (locker)
  159. {
  160. lineSeries.Clear();
  161. PlotModel.Series.Clear();
  162. Statistics.Clear();
  163. for (int i = 0; i < Menu.Count; i++)
  164. {
  165. Menu[i].IsChecked = Menu[i].AnalogType == type;
  166. }
  167. if (ShakerChannelViewModel.Instance.ResultChannels.Count == 0) return;
  168. var config = ShakerChannelViewModel.Instance.ResultChannels.FirstOrDefault(x => x.Value.ChannelType == type);
  169. if (config == null) return;
  170. PlotModel.Axes[1].Unit = config.Value.Unit;
  171. var allconfig = ShakerChannelViewModel.Instance.ResultChannels.Where(x => x.Value.ChannelType == type).ToList();
  172. for (int i = 0; i < allconfig.Count; i++)
  173. {
  174. LineSeries series = new LineSeries();
  175. series.Title = LanguageValueViewModel.Instance[allconfig[i].Value.Name];
  176. series.XAxisKey = "X";
  177. series.YAxisKey = "Y";
  178. series.Tag = allconfig[i].Value.Unit;
  179. series.DataFieldX = nameof(DataPoint.X);
  180. series.DataFieldY = nameof(DataPoint.Y);
  181. Statistics.Add(new StatisticsViewModel(new StatisticsModel()
  182. {
  183. Name = allconfig[i].Value.Name,
  184. }));
  185. lineSeries.Add(series);
  186. }
  187. PlotModel.InvalidatePlot(false);
  188. UpdatePlotTitle(type);
  189. lineSeries.ForEach(x => PlotModel.Series.Add(x));
  190. PlotModel.InvalidatePlot(true);
  191. }
  192. }
  193. public bool CanChangedAnalog
  194. {
  195. get => canChangedAnalog;
  196. set =>SetProperty(ref canChangedAnalog , value);
  197. }
  198. public OxyPlot.PlotModel PlotModel { get; } = new OxyPlot.PlotModel();
  199. public OxyPlot.PlotController PlotController { get; } = new OxyPlot.PlotController();
  200. public IViewCommand<OxyMouseWheelEventArgs> OxyMouseWheelCommand => new DelegatePlotCommand<OxyMouseWheelEventArgs>(OnOxyMouseWheel);
  201. private void OnOxyMouseWheel(IPlotView view, IController controller, OxyMouseWheelEventArgs args)
  202. {
  203. HandleZoomByWheel(view, args);
  204. if (view.ActualModel is PlotModel plotModel && plotModel.Axes.Count >= 1 && plotModel.Axes[0] is LinearAxis axis)
  205. {
  206. axis.MajorStep = (axis.Maximum - axis.Minimum) / 10;
  207. }
  208. }
  209. private void HandleZoomByWheel(IPlotView view, OxyMouseWheelEventArgs args, double factor = 1)
  210. {
  211. var m = new ZoomStepManipulator(view)
  212. {
  213. AxisPreference = AxisPreference.X,
  214. Step = args.Delta * 0.001 * factor,
  215. FineControl = args.IsControlDown,
  216. };
  217. m.Started(args);
  218. }
  219. }
  220. }