AnalogSignalPreviewViewModel.cs 9.0 KB

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