From bfcefc0cf95f3b8d5243908753129c79bad8dc8b Mon Sep 17 00:00:00 2001 From: Roy Date: Fri, 9 Feb 2018 03:49:59 +0200 Subject: Implemented MultiGraph on TechView. --- .../MonitorsToMultiChannleMonitorsConverter.cs | 34 +++++++ .../Editors/MultiGraphElementEditor.xaml | 79 ++++++++++++++++ .../Editors/MultiGraphElementEditor.xaml.cs | 102 +++++++++++++++++++++ .../Images/multi-graph.png | Bin 0 -> 1185 bytes .../PropertiesTemplates/MultiGraphTemplate.xaml | 29 ++++++ .../PropertiesTemplates/MultiGraphTemplate.xaml.cs | 29 ++++++ .../Tango.MachineStudio.Technician.csproj | 19 ++++ .../TechItems/MultiGraphItem.cs | 60 ++++++++++++ .../TechItems/SingleGraphItem.cs | 2 +- .../ViewModels/MachineTechViewVM.cs | 57 +++++++++++- .../Views/MachineTechView.xaml | 3 + .../Controls/RealTimeGraphMultiControl.xaml | 6 +- .../Controls/RealTimeGraphMultiControl.xaml.cs | 25 +++++ .../Tango.Editors/ElementsEditor.xaml.cs | 2 +- 14 files changed, 440 insertions(+), 7 deletions(-) create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/MonitorsToMultiChannleMonitorsConverter.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/multi-graph.png create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml.cs create mode 100644 Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/MultiGraphItem.cs (limited to 'Software/Visual_Studio') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/MonitorsToMultiChannleMonitorsConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/MonitorsToMultiChannleMonitorsConverter.cs new file mode 100644 index 000000000..46a526f56 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/MonitorsToMultiChannleMonitorsConverter.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Data; +using Tango.Integration.Observables; + +namespace Tango.MachineStudio.Technician.Converters +{ + public class MonitorsToMultiChannleMonitorsConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, CultureInfo culture) + { + ObservableCollection monitors = value as ObservableCollection; + + if (monitors != null) + { + return monitors.Where(x => x.MultiChannel).ToObservableCollection(); + } + else + { + return null; + } + } + + public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml new file mode 100644 index 000000000..fd2db03e5 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml.cs new file mode 100644 index 000000000..35273ccda --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/MultiGraphElementEditor.xaml.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Markup; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Tango.Editors; +using Tango.Integration.Observables; +using Tango.MachineStudio.Technician.TechItems; + +namespace Tango.MachineStudio.Technician.Editors +{ + [ContentProperty("InnerContent")] + public partial class MultiGraphElementEditor : ElementEditor + { + /// + /// Initializes a new instance of the class. + /// + public MultiGraphElementEditor() + : base() + { + InitializeComponent(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The framework element. + public MultiGraphElementEditor(MultiGraphItem graphItem) + : this() + { + GraphItem = graphItem; + } + + /// + /// Initializes a new instance of the class. + /// + /// The framework element. + /// The bounds. + public MultiGraphElementEditor(MultiGraphItem graphItem, Rect bounds) + : this(graphItem) + { + Left = bounds.Left; + Top = bounds.Top; + Width = bounds.Width; + Height = bounds.Height; + } + + private MultiGraphItem _monitorItem; + + public MultiGraphItem GraphItem + { + get { return _monitorItem; } + set { _monitorItem = value; RaisePropertyChanged(nameof(GraphItem)); } + } + + + /// + /// Clones this instance. + /// + /// + public override IElementEditor Clone() + { + try + { + MultiGraphElementEditor cloned = new MultiGraphElementEditor(); + + cloned.GraphItem = GraphItem.Clone() as MultiGraphItem; + cloned.Top = Top; + cloned.Left = Left; + cloned.Width = Width; + cloned.Height = Height; + cloned.Angle = Angle; + return cloned; + } + catch (Exception ex) + { + throw new InvalidOperationException("Could not clone this editor. You may have to create a custom editor and implement a custom Clone method.", ex); + } + } + + /// + /// Gets the hosted element. + /// + [ParameterIgnore] + public override Object HostedElement + { + get { return GraphItem; } + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/multi-graph.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/multi-graph.png new file mode 100644 index 000000000..096d75cc4 Binary files /dev/null and b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/multi-graph.png differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml new file mode 100644 index 000000000..491a8b5c8 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + Selected Input + + + + diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml.cs new file mode 100644 index 000000000..ae5cf4f89 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/MultiGraphTemplate.xaml.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Tango.MachineStudio.Technician.TechItems; + +namespace Tango.MachineStudio.Technician.PropertiesTemplates +{ + /// + /// Interaction logic for SingleGraphTemplate.xaml + /// + public partial class MultiGraphTemplate : UserControl + { + public MultiGraphTemplate() + { + InitializeComponent(); + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Tango.MachineStudio.Technician.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Tango.MachineStudio.Technician.csproj index 502ec398d..ed270c017 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Tango.MachineStudio.Technician.csproj +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Tango.MachineStudio.Technician.csproj @@ -77,9 +77,13 @@ + + + MultiGraphElementEditor.xaml + SingleGraphElementEditor.xaml @@ -90,9 +94,13 @@ MonitorTemplate.xaml + + MultiGraphTemplate.xaml + SingleGraphTemplate.xaml + @@ -121,6 +129,10 @@ GlobalVersionInfo.cs + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -133,6 +145,10 @@ Designer MSBuild:Compile + + MSBuild:Compile + Designer + Designer MSBuild:Compile @@ -258,5 +274,8 @@ + + + \ No newline at end of file diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/MultiGraphItem.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/MultiGraphItem.cs new file mode 100644 index 000000000..13591fb01 --- /dev/null +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/MultiGraphItem.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; +using Tango.Integration.Observables; +using Tango.MachineStudio.Technician.Editors; +using Tango.SharedUI.Helpers; + +namespace Tango.MachineStudio.Technician.TechItems +{ + public class MultiGraphItem : TechItem + { + private TechMonitor _techMonitor; + [XmlIgnore] + public TechMonitor TechMonitor + { + get { return _techMonitor; } + set + { + TechMonitor old = _techMonitor; + + _techMonitor = value; + RaisePropertyChangedAuto(); + RaisePropertyChanged(nameof(Data)); + + if (_techMonitor != old && Editor != null) + { + Editor.InnerGraph.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(TechMonitor.PointsPerFrame); + Editor.InnerGraph.InvalidateGraph(); + } + } + } + + [XmlIgnore] + public MultiGraphElementEditor Editor { get; set; } + + public override object Data => TechMonitor; + + public MultiGraphItem() : base() + { + Name = "Single Channel Graph"; + Description = "Single channel real-time graph"; + Image = ResourceHelper.GetImageFromResources("Images/multi-graph.png"); + } + + public MultiGraphItem(TechMonitor techMonitor) : this() + { + TechMonitor = techMonitor; + } + + public override TechItem Clone() + { + MultiGraphItem cloned = base.Clone() as MultiGraphItem; + cloned.TechMonitor = TechMonitor; + return cloned; + } + } +} diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/SingleGraphItem.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/SingleGraphItem.cs index 9ce559047..ff87aa44d 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/SingleGraphItem.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/SingleGraphItem.cs @@ -52,7 +52,7 @@ namespace Tango.MachineStudio.Technician.TechItems public override TechItem Clone() { - MonitorItem cloned = base.Clone() as MonitorItem; + SingleGraphItem cloned = base.Clone() as SingleGraphItem; cloned.TechMonitor = TechMonitor; return cloned; } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs index 2be98e619..8bbebdfb7 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/ViewModels/MachineTechViewVM.cs @@ -8,6 +8,8 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows; +using System.Windows.Media; +using Tango.Core.Helpers; using Tango.Editors; using Tango.Integration.Observables; using Tango.Integration.Operators; @@ -23,6 +25,7 @@ namespace Tango.MachineStudio.Technician.ViewModels { private List _diagnoticsDataProperties; private Dictionary _singleControllers; + private Dictionary _multiControllers; private static object _elementsLock = new object(); private ObservableCollection _elements; @@ -62,6 +65,7 @@ namespace Tango.MachineStudio.Technician.ViewModels public MachineTechViewVM(IStudioApplicationManager applicationManager) { _singleControllers = new Dictionary(); + _multiControllers = new Dictionary(); AvailableTechItems = TechItem.GetAvailableTechItems().ToObservableCollection(); SelectedTechItem = AvailableTechItems.FirstOrDefault(); _diagnoticsDataProperties = typeof(PushDiagnosticsResponse).GetProperties(BindingFlags.Public | BindingFlags.Instance).ToList(); @@ -127,6 +131,22 @@ namespace Tango.MachineStudio.Technician.ViewModels } } } + else if (item.GetType() == typeof(MultiGraphItem)) + { + MultiGraphItem graphItem = item as MultiGraphItem; + + var prop = _diagnoticsDataProperties.SingleOrDefault(x => x.Name == graphItem.TechMonitor.Name); + + if (prop != null) + { + GraphMultiController controller = null; + + if (_multiControllers.TryGetValue(graphItem, out controller)) + { + controller.PushData(GetMultiGraphValues(graphItem.TechMonitor, prop.GetValue(data))); + } + } + } } } } @@ -150,20 +170,26 @@ namespace Tango.MachineStudio.Technician.ViewModels return (value as RepeatedField).ToList(); } + private List> GetMultiGraphValues(TechMonitor monitor,object value) + { + DoubleArray[] arrayOfDoubles = Enumerable.ToArray(value as IEnumerable); + return arrayOfDoubles.Select(x => x.Data.ToList()).ToList(); + } + public void AddElement(Rect bounds) { lock (_elementsLock) { if (SelectedTechItem is MonitorItem) { - var monitorItem = new MonitorItem(Adapter.TechMonitors.FirstOrDefault()); + var monitorItem = new MonitorItem(Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault()); MonitorElementEditor editor = new MonitorElementEditor(monitorItem, bounds); editor.DataContext = monitorItem; Elements.Add(editor); } else if (SelectedTechItem is SingleGraphItem) { - var graphItem = new SingleGraphItem(Adapter.TechMonitors.FirstOrDefault()); + var graphItem = new SingleGraphItem(Adapter.TechMonitors.Where(x => !x.MultiChannel).FirstOrDefault()); SingleGraphElementEditor editor = new SingleGraphElementEditor(graphItem, bounds); editor.InnerGraph.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(graphItem.TechMonitor.PointsPerFrame); editor.DataContext = graphItem; @@ -175,6 +201,33 @@ namespace Tango.MachineStudio.Technician.ViewModels _singleControllers.Add(graphItem, controller); + Elements.Add(editor); + } + else if (SelectedTechItem is MultiGraphItem) + { + var graphItem = new MultiGraphItem(Adapter.TechMonitors.Where(x => x.MultiChannel).FirstOrDefault()); + MultiGraphElementEditor editor = new MultiGraphElementEditor(graphItem, bounds); + editor.InnerGraph.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(graphItem.TechMonitor.PointsPerFrame); + editor.DataContext = graphItem; + graphItem.Editor = editor; + + + GraphMultiController controller = new GraphMultiController(); + + for (int i = 0; i < graphItem.TechMonitor.ChannelCount; i++) + { + controller.AddSeries(new RealTimeGraphEx.DataSeries.DataYSeries() + { + UseFillAndStroke = true, + Name = graphItem.TechMonitor.Name.First() + (i + 1).ToString(), + Stroke = new SolidColorBrush(ColorHelper.GetRandomColor()), + }); + } + + editor.InnerGraph.Controller = controller; + + _multiControllers.Add(graphItem, controller); + Elements.Add(editor); } } diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml index 2c895a789..0f255fac8 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Views/MachineTechView.xaml @@ -157,6 +157,9 @@ + + + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml index 23573e574..9a5ae3636 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml @@ -62,12 +62,12 @@ - - + + - + diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs index a18021ff5..8e3b6b6e3 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Controls/RealTimeGraphMultiControl.xaml.cs @@ -50,6 +50,31 @@ namespace Tango.MachineStudio.Common.Controls public static readonly DependencyProperty SensorUnitsProperty = DependencyProperty.Register("SensorUnits", typeof(String), typeof(RealTimeGraphMultiControl), new PropertyMetadata(null)); + public double Minimum + { + get { return (double)GetValue(MinimumProperty); } + set { SetValue(MinimumProperty, value); } + } + public static readonly DependencyProperty MinimumProperty = + DependencyProperty.Register("Minimum", typeof(double), typeof(RealTimeGraphMultiControl), new PropertyMetadata(0.0)); + + + + public double Maximum + { + get { return (double)GetValue(MaximumProperty); } + set { SetValue(MaximumProperty, value); } + } + public static readonly DependencyProperty MaximumProperty = + DependencyProperty.Register("Maximum", typeof(double), typeof(RealTimeGraphMultiControl), new PropertyMetadata(100.0)); + + public void InvalidateGraph() + { + InnerGraph.Clear(); + yAxis.Render(InnerGraph); + yAxisTicks.Render(InnerGraph); + } + /// /// Gets or sets the inner real-time graph control. /// diff --git a/Software/Visual_Studio/Tango.Editors/ElementsEditor.xaml.cs b/Software/Visual_Studio/Tango.Editors/ElementsEditor.xaml.cs index a0e92ccf6..c6d4c00a3 100644 --- a/Software/Visual_Studio/Tango.Editors/ElementsEditor.xaml.cs +++ b/Software/Visual_Studio/Tango.Editors/ElementsEditor.xaml.cs @@ -730,7 +730,7 @@ namespace Tango.Editors /// The instance containing the event data. private void Element_PreviewMouseDown(object sender, MouseButtonEventArgs e) { - if (e.ChangedButton == MouseButton.Left && !Keyboard.IsKeyDown(Key.LeftShift)) + if (e.ChangedButton == MouseButton.Left && !Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.LeftAlt)) { SelectedElement = sender as IElementEditor; } -- cgit v1.3.1