aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Tango.PPC.Common
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2018-05-27 19:33:15 +0300
committerRoy Ben-Shabat <Roy@Twine-s.com>2018-05-27 19:33:15 +0300
commite571f20e27c4fca6bb6efe03d6427a1f332f9830 (patch)
treeb16041b76ea3b4e8368039c9396f9bbf9624dcc2 /Software/Visual_Studio/PPC/Tango.PPC.Common
parent157e0685abb2e7b22b6584cdc7d6f5838ed0a808 (diff)
downloadTango-e571f20e27c4fca6bb6efe03d6427a1f332f9830.tar.gz
Tango-e571f20e27c4fca6bb6efe03d6427a1f332f9830.zip
Working on panel pc.
Diffstat (limited to 'Software/Visual_Studio/PPC/Tango.PPC.Common')
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs54
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/DefaultAuthenticationProvider.cs32
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/IAuthenticationProvider.cs38
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml8
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml.cs263
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChartBrushCollection.cs9
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Converters/SegmentsToPieConverter.cs52
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/CustomControl1.cs25
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs97
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/IDiagnosticsFrameProvider.cs32
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs331
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/IEventLogger.cs64
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationManager.cs20
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs18
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/DialogViewVM.cs74
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/INotificationProvider.cs129
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/TaskItem.cs62
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs19
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs39
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/AssemblyInfo.cs55
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.Designer.cs62
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.resx117
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.Designer.cs30
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.settings7
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj188
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Themes/Generic.xaml18
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/app.config61
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/packages.config5
28 files changed, 1909 insertions, 0 deletions
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs
new file mode 100644
index 000000000..3a516c072
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.BL.Entities;
+using Tango.Integration.Operation;
+using Tango.Integration.Services;
+
+namespace Tango.PPC.Common.Application
+{
+ /// <summary>
+ /// Represents the Machine Studio application manager.
+ /// </summary>
+ public interface IPPCApplicationManager
+ {
+ /// <summary>
+ /// Gets or sets the DAL machine.
+ /// </summary>
+ Machine Machine { get; }
+
+ /// <summary>
+ /// Sets the machine.
+ /// </summary>
+ /// <param name="machine">The machine.</param>
+ void SetMachine(Machine machine);
+
+ /// <summary>
+ /// Occurs when the connected machine property has changed.
+ /// </summary>
+ event EventHandler<IMachineOperator> ConnectedMachineChanged;
+
+ /// <summary>
+ /// Gets a value indicating whether Machine Studio is shutting down.
+ /// </summary>
+ bool IsShuttingDown { get; }
+
+ /// <summary>
+ /// Shutdown the application.
+ /// </summary>
+ void ShutDown();
+
+ /// <summary>
+ /// Gets or sets the currently connected machine if any.
+ /// </summary>
+ IMachineOperator ConnectedMachine { get; set; }
+
+ /// <summary>
+ /// Gets the machine studio application version.
+ /// </summary>
+ String Version { get; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/DefaultAuthenticationProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/DefaultAuthenticationProvider.cs
new file mode 100644
index 000000000..c8e89ac2f
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/DefaultAuthenticationProvider.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+
+namespace Tango.PPC.Common.Authentication
+{
+ public class DefaultAuthenticationProvider : IAuthenticationProvider
+ {
+ public User CurrentUser
+ {
+ get
+ {
+ throw new NotImplementedException();
+ }
+ }
+
+ public event EventHandler<User> CurrentUserChanged;
+
+ public User Login(string email, string password)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void Logout()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/IAuthenticationProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/IAuthenticationProvider.cs
new file mode 100644
index 000000000..0892932a8
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Authentication/IAuthenticationProvider.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+
+namespace Tango.PPC.Common.Authentication
+{
+ /// <summary>
+ /// Represents the Machine Studio user authentication provider responsible for the current logged-in user.
+ /// </summary>
+ public interface IAuthenticationProvider
+ {
+ /// <summary>
+ /// Occurs when the current logged-in user has changed.
+ /// </summary>
+ event EventHandler<User> CurrentUserChanged;
+
+ /// <summary>
+ /// Gets the current logged-in user.
+ /// </summary>
+ User CurrentUser { get; }
+
+ /// <summary>
+ /// Performs a user login by the specified email and password.
+ /// </summary>
+ /// <param name="email">The email.</param>
+ /// <param name="password">The password.</param>
+ /// <returns></returns>
+ User Login(String email, String password);
+
+ /// <summary>
+ /// Logs-out the current logged-in user.
+ /// </summary>
+ void Logout();
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml
new file mode 100644
index 000000000..0c6ae7630
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml
@@ -0,0 +1,8 @@
+<UserControl x:Class="Tango.PPC.Common.Controls.MultiPieChart"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:pieCharts="clr-namespace:Tango.PPC.Common.Controls">
+
+ <Image x:Name="_pieChartImage" RenderOptions.BitmapScalingMode="NearestNeighbor"/>
+
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml.cs
new file mode 100644
index 000000000..2415573fe
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChart.xaml.cs
@@ -0,0 +1,263 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace Tango.PPC.Common.Controls
+{
+ /// <summary>
+ /// Interaction logic for MultiPieChart.xaml
+ /// </summary>
+ public partial class MultiPieChart : UserControl
+ {
+ private const string DefaultDataBrush = "#939496";
+
+ #region dependency properties
+
+ public static readonly DependencyProperty SizeProperty =
+ DependencyProperty.Register( "Size", typeof( double ), typeof( MultiPieChart ), new PropertyMetadata( 100.0, OnPiePropertyChanged ) );
+
+ public static readonly DependencyProperty InnerPieSliceFillProperty =
+ DependencyProperty.Register( "InnerPieSliceFill", typeof( Brush ), typeof( MultiPieChart ), new PropertyMetadata( CreateBrush( "#939496" ), OnPiePropertyChanged ) );
+
+ public static readonly DependencyProperty OuterPieSliceFillProperty =
+ DependencyProperty.Register( "OuterPieSliceFill", typeof( Brush ), typeof( MultiPieChart ), new PropertyMetadata( CreateBrush( "#D0D1D3" ), OnPiePropertyChanged ) );
+
+ public static readonly DependencyProperty DataListProperty =
+ DependencyProperty.Register( "DataList", typeof( IList<double> ), typeof( MultiPieChart ), new PropertyMetadata( null, OnDataListPropertyChanged ) );
+
+ public static readonly DependencyProperty DataBrushesProperty =
+ DependencyProperty.Register( "DataBrushes", typeof( MultiPieChartBrushCollection ), typeof( MultiPieChart ), new PropertyMetadata( new MultiPieChartBrushCollection(), OnPiePropertyChanged ) );
+
+ public double Size
+ {
+ get { return (double)GetValue( SizeProperty ); }
+ set { SetValue( SizeProperty, value ); }
+ }
+
+ public Brush InnerPieSliceFill
+ {
+ get { return (Brush)GetValue( InnerPieSliceFillProperty ); }
+ set { SetValue( InnerPieSliceFillProperty, value ); }
+ }
+
+ public Brush OuterPieSliceFill
+ {
+ get { return (Brush)GetValue( OuterPieSliceFillProperty ); }
+ set { SetValue( OuterPieSliceFillProperty, value ); }
+ }
+
+ public IList<double> DataList
+ {
+ get { return (IList<double>)GetValue( DataListProperty ); }
+ set { SetValue( DataListProperty, value ); }
+ }
+
+ public MultiPieChartBrushCollection DataBrushes
+ {
+ get { return (MultiPieChartBrushCollection)GetValue( DataBrushesProperty ); }
+ set { SetValue( DataBrushesProperty, value ); }
+ }
+
+ #endregion
+
+ #region constructor
+
+ public MultiPieChart()
+ {
+ InitializeComponent();
+ this.Loaded += (_, __) => { CreatePieChart(); };
+ }
+
+ #endregion
+
+ #region overrides
+
+ #endregion
+
+ #region events
+
+ private static void OnPiePropertyChanged( DependencyObject dep, DependencyPropertyChangedEventArgs ev )
+ {
+ //var chart = (MultiPieChart)dep;
+
+ //if ( chart.IsInitialized )
+ //{
+ // chart.CreatePieChart();
+ //}
+ }
+
+ private static void OnDataListPropertyChanged( DependencyObject dep, DependencyPropertyChangedEventArgs ev )
+ {
+ var chart = (MultiPieChart)dep;
+
+ var collection = ev.OldValue as INotifyCollectionChanged;
+ if ( collection != null )
+ {
+ collection.CollectionChanged -= chart.DataListCollectionChanged;
+ }
+
+ collection = ev.NewValue as INotifyCollectionChanged;
+ if ( collection != null )
+ {
+ collection.CollectionChanged += chart.DataListCollectionChanged;
+ }
+ }
+
+
+ private void DataListCollectionChanged( object sender, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs )
+ {
+ //CreatePieChart();
+ }
+
+ #endregion
+
+ #region private methods
+
+ private void CreatePieChart()
+ {
+ Size = ActualWidth;
+
+ if ( _pieChartImage != null )
+ {
+ if ( !double.IsNaN( Size ) && DataList != null && DataList.Any() )
+ {
+ _pieChartImage.Width = _pieChartImage.Height = Width = Height = Size;
+
+ var di = new DrawingImage();
+ _pieChartImage.Source = di;
+
+ var dg = new DrawingGroup();
+ di.Drawing = dg;
+
+ if ( DataList.Count > 1 )
+ {
+ var total = DataList.Sum();
+ var startPoint = new Point( Width / 2, 0 );
+ double radians = 0;
+
+ for ( int i = 0; i < DataList.Count; i++ )
+ {
+ var data = DataList[i];
+ var dataBrush = GetBrushFromList( i );
+ var percentage = data / total;
+
+ Point endPoint;
+ var angle = 360 * percentage;
+
+ if ( i + 1 == DataList.Count )
+ {
+ endPoint = new Point( Width / 2, 0 );
+ }
+ else
+ {
+ radians += ( Math.PI / 180 ) * angle;
+ var endPointX = Math.Sin( radians ) * Height / 2 + Height / 2;
+ var endPointY = Width / 2 - Math.Cos( radians ) * Width / 2;
+ endPoint = new Point( endPointX, endPointY );
+ }
+
+ dg.Children.Add( CreatePathGeometry( dataBrush, startPoint, endPoint, angle > 180 ) );
+
+ startPoint = endPoint;
+ }
+ }
+ else
+ {
+ dg.Children.Add( CreateEllipseGeometry( GetBrushFromList( 0 ) ) );
+ }
+ }
+ else
+ {
+ _pieChartImage.Source = null;
+ }
+ }
+ }
+
+ private GeometryDrawing CreatePathGeometry( Brush brush, Point startPoint, Point arcPoint, bool isLargeArc )
+ {
+ /*
+ * <GeometryDrawing Brush="@Brush">
+ <GeometryDrawing.Geometry>
+ <PathGeometry>
+ <PathFigure StartPoint="@Size/2">
+ <PathFigure.Segments>
+ <LineSegment Point="@startPoint"/>
+ <ArcSegment Point="@arcPoint" SweepDirection="Clockwise" Size="@Size/2"/>
+ <LineSegment Point="@Size/2"/>
+ </PathFigure.Segments>
+ </PathFigure>
+ </PathGeometry>
+ </GeometryDrawing.Geometry>
+ </GeometryDrawing>
+ * */
+
+ var midPoint = new Point( Width / 2, Height / 2 );
+
+ var drawing = new GeometryDrawing { Brush = brush };
+ var pathGeometry = new PathGeometry();
+ var pathFigure = new PathFigure { StartPoint = midPoint };
+
+ var ls1 = new LineSegment( startPoint, false );
+ var arc = new ArcSegment
+ {
+ SweepDirection = SweepDirection.Clockwise,
+ Size = new Size( Width / 2, Height / 2 ),
+ Point = arcPoint,
+ IsLargeArc = isLargeArc
+ };
+ var ls2 = new LineSegment( midPoint, false );
+
+ drawing.Geometry = pathGeometry;
+ pathGeometry.Figures.Add( pathFigure );
+
+ pathFigure.Segments.Add( ls1 );
+ pathFigure.Segments.Add( arc );
+ pathFigure.Segments.Add( ls2 );
+
+ return drawing;
+ }
+
+ private GeometryDrawing CreateEllipseGeometry( Brush brush )
+ {
+ var midPoint = new Point( Width / 2, Height / 2 );
+
+ var drawing = new GeometryDrawing { Brush = brush };
+ var ellipse = new EllipseGeometry( midPoint, Size / 2, Size / 2 );
+
+ drawing.Geometry = ellipse;
+
+ return drawing;
+ }
+
+ private static SolidColorBrush CreateBrush( string brush )
+ {
+ var color = ColorConverter.ConvertFromString( brush );
+ if ( color != null )
+ {
+ return new SolidColorBrush( (Color)color );
+ }
+
+ return null;
+ }
+
+ private Brush GetBrushFromList( int index )
+ {
+ if ( DataBrushes == null || !DataBrushes.Any() )
+ {
+ return CreateBrush( DefaultDataBrush );
+ }
+ else
+ {
+ var modIndex = index % DataBrushes.Count;
+ return DataBrushes[modIndex];
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChartBrushCollection.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChartBrushCollection.cs
new file mode 100644
index 000000000..0d8c754f7
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Controls/MultiPieChartBrushCollection.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+using System.Windows.Media;
+
+namespace Tango.PPC.Common.Controls
+{
+ public class MultiPieChartBrushCollection : List<Brush>
+ {
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Converters/SegmentsToPieConverter.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Converters/SegmentsToPieConverter.cs
new file mode 100644
index 000000000..77eab71b8
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Converters/SegmentsToPieConverter.cs
@@ -0,0 +1,52 @@
+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 System.Windows.Media;
+using Tango.BL.Entities;
+using Tango.PPC.Common.Controls;
+
+namespace Tango.PPC.Common.Converters
+{
+ public class SegmentsToPieConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ ObservableCollection<Segment> segments = value as ObservableCollection<Segment>;
+
+ if (segments != null)
+ {
+ MultiPieChart pie = new MultiPieChart();
+
+ pie.DataList = new List<Double>();
+
+ if (segments.Count > 0)
+ {
+ foreach (var segment in segments)
+ {
+ pie.DataList.Add(10);
+ pie.DataBrushes.Add(segment.GetSegmentBrush());
+ }
+ }
+ else
+ {
+ pie.DataList.Add(10);
+ pie.DataBrushes.Add(new SolidColorBrush(Colors.Gainsboro));
+ }
+
+ return pie;
+ }
+
+ return null;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/CustomControl1.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/CustomControl1.cs
new file mode 100644
index 000000000..82fcc6431
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/CustomControl1.cs
@@ -0,0 +1,25 @@
+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;
+
+namespace Tango.PPC.Common
+{
+ public class CustomControl1 : Control
+ {
+ static CustomControl1()
+ {
+ DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomControl1), new FrameworkPropertyMetadata(typeof(CustomControl1)));
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs
new file mode 100644
index 000000000..c4e0563ab
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs
@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Integration.Operation;
+using Tango.Integration.Services;
+using Tango.PMR.Diagnostics;
+using Tango.PPC.Common.Application;
+
+namespace Tango.PPC.Common.Diagnostics
+{
+ /// <summary>
+ /// Represents the default diagnostics frame provider.
+ /// </summary>
+ /// <seealso cref="Tango.MachineStudio.Common.Diagnostics.IDiagnosticsFrameProvider" />
+ public class DefaultDiagnosticsFrameProvider : ExtendedObject, IDiagnosticsFrameProvider
+ {
+ private IPPCApplicationManager _application;
+
+ private bool _disable;
+ /// <summary>
+ /// Disables the frame delivery from the current connected machine and enables the manual push frame method.
+ /// </summary>
+ public bool Disable
+ {
+ get { return _disable; }
+ set
+ {
+ _disable = value;
+ }
+ }
+
+ /// <summary>
+ /// Occurs when a new data frame is available.
+ /// </summary>
+ public event EventHandler<StartDiagnosticsResponse> FrameReceived;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultDiagnosticsFrameProvider"/> class.
+ /// </summary>
+ /// <param name="applicationManager">The application manager.</param>
+ public DefaultDiagnosticsFrameProvider(IPPCApplicationManager applicationManager)
+ {
+ _application = applicationManager;
+ applicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged;
+ }
+
+ /// <summary>
+ /// Applications the manager connected machine changed.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="machine">The machine.</param>
+ private void ApplicationManager_ConnectedMachineChanged(object sender, IMachineOperator machine)
+ {
+ if (machine != null)
+ {
+ machine.DiagnosticsDataAvailable += DefaultDiagnosticsFrameProvider_DiagnosticsDataAvailable;
+ }
+ }
+
+ /// <summary>
+ /// Defaults the diagnostics frame provider diagnostics data available.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="frame">The frame.</param>
+ private void DefaultDiagnosticsFrameProvider_DiagnosticsDataAvailable(object sender, StartDiagnosticsResponse frame)
+ {
+ if (!Disable)
+ {
+ OnFrameReceived(frame);
+ }
+ }
+
+ /// <summary>
+ /// Push frames manual. (Only when Disable = true)
+ /// </summary>
+ /// <param name="frame">The frame.</param>
+ public void PushFrame(StartDiagnosticsResponse frame)
+ {
+ if (Disable)
+ {
+ OnFrameReceived(frame);
+ }
+ }
+
+ /// <summary>
+ /// Raises the <see cref="FrameReceived"/> event.
+ /// </summary>
+ /// <param name="frame">The frame.</param>
+ protected virtual void OnFrameReceived(StartDiagnosticsResponse frame)
+ {
+ FrameReceived?.Invoke(this, frame);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/IDiagnosticsFrameProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/IDiagnosticsFrameProvider.cs
new file mode 100644
index 000000000..169870042
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Diagnostics/IDiagnosticsFrameProvider.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Integration.Operation;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.PPC.Common.Diagnostics
+{
+ /// <summary>
+ /// Represents a tango machine diagnostics frame provider.
+ /// </summary>
+ public interface IDiagnosticsFrameProvider
+ {
+ /// <summary>
+ /// Occurs when a new data frame is available.
+ /// </summary>
+ event EventHandler<StartDiagnosticsResponse> FrameReceived;
+
+ /// <summary>
+ /// Disables the frame delivery from the current connected machine and enables the manual push frame method.
+ /// </summary>
+ bool Disable { get; set; }
+
+ /// <summary>
+ /// Push frames manual. (Only when Disable = true)
+ /// </summary>
+ /// <param name="frame">The frame.</param>
+ void PushFrame(StartDiagnosticsResponse frame);
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs
new file mode 100644
index 000000000..2675fa1fa
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/DefaultEventLogger.cs
@@ -0,0 +1,331 @@
+using Google.Protobuf;
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.BL;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.Core;
+using Tango.Integration.Services;
+using Tango.PMR.Diagnostics;
+using Tango.Integration.Operation;
+using Tango.PPC.Common.Application;
+using Tango.PPC.Common.Authentication;
+
+namespace Tango.PPC.Common.EventLogging
+{
+ /// <summary>
+ /// Represents the default database events logger.
+ /// </summary>
+ /// <seealso cref="IEventLogger" />
+ public class DefaultEventLogger : ExtendedObject, IEventLogger
+ {
+ private ObservablesContext _db;
+ private Thread _logThread;
+ private ConcurrentQueue<MachinesEvent> _events;
+ private IPPCApplicationManager _application;
+ private IAuthenticationProvider _authentication;
+ private Dictionary<EventTypes, BL.Entities.EventType> _eventTypesGuids;
+ private String _hostName;
+ private bool _isInitialized;
+ private List<MachinesEvent> _pendingEvents;
+
+ #region Events
+
+ /// <summary>
+ /// Occurs when a new machine event has been logged.
+ /// </summary>
+ public event EventHandler<MachinesEvent> NewLog;
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultEventLogger"/> class.
+ /// </summary>
+ /// <param name="applicationManager">The application manager.</param>
+ /// <param name="authenticationProvider">The authentication provider.</param>
+ public DefaultEventLogger(IPPCApplicationManager applicationManager, IAuthenticationProvider authenticationProvider)
+ {
+ _hostName = Environment.MachineName;
+
+ _events = new ConcurrentQueue<MachinesEvent>();
+ _pendingEvents = new List<MachinesEvent>();
+
+ _eventTypesGuids = new Dictionary<EventTypes, BL.Entities.EventType>();
+
+ _application = applicationManager;
+ _authentication = authenticationProvider;
+ _logThread = new Thread(LogThreadMethod);
+ _logThread.IsBackground = true;
+ _logThread.Start();
+
+ _application.ConnectedMachineChanged += _application_ConnectedMachineChanged;
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private void Init()
+ {
+ if (!_isInitialized)
+ {
+ try
+ {
+ _db = ObservablesContext.CreateDefault();
+ _db.Configuration.LazyLoadingEnabled = false;
+
+ _db.ActionTypes.ToList();
+ _db.EventTypesActions.ToList();
+ _db.EventTypesCategories.ToList();
+ _db.EventTypesGroups.ToList();
+ _db.EventTypes.ToList();
+
+ foreach (var type in _db.EventTypes)
+ {
+ _eventTypesGuids.Add((EventTypes)type.Code, type);
+ }
+
+ _isInitialized = true;
+ }
+ catch
+ {
+ _isInitialized = false;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Event Handlers
+
+ /// <summary>
+ /// Handle the application manager connected machine changed event.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="machine">The machine.</param>
+ private void _application_ConnectedMachineChanged(object sender, IMachineOperator machine)
+ {
+ if (machine != null)
+ {
+ if (machine.MachineEventsStateProvider != null)
+ {
+ machine.MachineEventsStateProvider.NewEvents -= MachineEventsStateProvider_NewEvents;
+ machine.MachineEventsStateProvider.NewEvents += MachineEventsStateProvider_NewEvents;
+ machine.MachineEventsStateProvider.EventsResolved -= MachineEventsStateProvider_EventsResolved;
+ machine.MachineEventsStateProvider.EventsResolved += MachineEventsStateProvider_EventsResolved;
+ }
+
+ machine.RequestSent -= Machine_RequestSent;
+ machine.RequestFailed -= Machine_RequestFailed;
+ machine.ResponseReceived -= Machine_ResponseReceived;
+
+ machine.RequestSent += Machine_RequestSent;
+ machine.RequestFailed += Machine_RequestFailed;
+ machine.ResponseReceived += Machine_ResponseReceived;
+ }
+ }
+
+ /// <summary>
+ /// Handles the RequestSent event of the connected machine.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="message">The message.</param>
+ private void Machine_RequestSent(object sender, IMessage message)
+ {
+ Log(EventTypes.RequestSent, String.Format("Sending request '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString()));
+ }
+
+ /// <summary>
+ /// Handles the RequestFailed event of the connected machine.
+ /// </summary>
+ /// <param name="sender">The source of the event.</param>
+ /// <param name="e">The <see cref="RequestFailedEventArgs"/> instance containing the event data.</param>
+ private void Machine_RequestFailed(object sender, RequestFailedEventArgs e)
+ {
+ Log(EventTypes.RequestFailed, String.Format("Request failed '{0}'...{1}{2}{1}{3}", e.Message.GetType().Name, Environment.NewLine, e.Message.ToJsonString(), e.Exception.ToString()));
+ }
+
+ /// <summary>
+ /// Handles the ResponseReceived event of the connected machine.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="message">The message.</param>
+ private void Machine_ResponseReceived(object sender, IMessage message)
+ {
+ Log(EventTypes.ResponseReceived, String.Format("Response received '{0}'...{1}{2}", message.GetType().Name, Environment.NewLine, message.ToJsonString()));
+ }
+
+ /// <summary>
+ /// Handles the connected machine events state provider NewEvents event.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="events">The events.</param>
+ private void MachineEventsStateProvider_NewEvents(object sender, IEnumerable<MachinesEvent> events)
+ {
+ foreach (var ev in events)
+ {
+ Log(ev);
+ }
+ }
+
+ /// <summary>
+ /// Handles the connected machine events state provider EventsResolved event.
+ /// </summary>
+ /// <param name="sender">The sender.</param>
+ /// <param name="events">The events.</param>
+ private void MachineEventsStateProvider_EventsResolved(object sender, IEnumerable<MachinesEvent> events)
+ {
+ foreach (var ev in events)
+ {
+ Log(String.Format("Event '{0}' resolved.", ev.EventType.Name));
+ }
+ }
+
+ #endregion
+
+ #region Logging
+
+ /// <summary>
+ /// Logs the specified machine event.
+ /// </summary>
+ /// <param name="machineEvent">The machine event.</param>
+ public void Log(MachinesEvent machineEvent)
+ {
+ machineEvent.HostName = _hostName;
+ machineEvent.EventType = _eventTypesGuids[machineEvent.Type];
+
+ if (_application.ConnectedMachine == null || _authentication.CurrentUser == null)
+ {
+ _pendingEvents.Add(machineEvent);
+ }
+ else
+ {
+ if (_pendingEvents.Count > 0)
+ {
+ var pending = _pendingEvents.ToList();
+ _pendingEvents.Clear();
+
+ foreach (var ev in pending)
+ {
+ Log(ev);
+ }
+ }
+
+ LogManager.Log("Logging event " + machineEvent.EventType.Name + " - " + machineEvent.Description);
+ machineEvent.MachineGuid = _application.ConnectedMachine.Machine.Guid;
+ machineEvent.UserGuid = _authentication.CurrentUser.Guid;
+ machineEvent.User = _authentication.CurrentUser;
+ _events.Enqueue(machineEvent);
+ NewLog?.Invoke(this, machineEvent);
+ }
+ }
+
+ /// <summary>
+ /// Logs the specified event type.
+ /// </summary>
+ /// <param name="eventType">Type of the event.</param>
+ /// <param name="message">The message.</param>
+ public void Log(EventTypes eventType, string message)
+ {
+ Init();
+
+ MachinesEvent machineEvent = new MachinesEvent();
+ machineEvent.DateTime = DateTime.UtcNow;
+ machineEvent.Description = message;
+ machineEvent.EventType = _eventTypesGuids[eventType];
+ machineEvent.EventTypeGuid = machineEvent.EventType.Guid;
+
+ Log(machineEvent);
+ }
+
+ /// <summary>
+ /// Logs the specified hardware event.
+ /// </summary>
+ /// <param name="hardwareEvent">The hardware event.</param>
+ public void Log(Event hardwareEvent)
+ {
+ Log((EventTypes)hardwareEvent.Type, hardwareEvent.Message);
+ }
+
+ /// <summary>
+ /// Logs the specified exception using the <see cref="EventTypes.ApplicationException"/>.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ public void Log(Exception exception)
+ {
+ Log(EventTypes.ApplicationException, exception.ToString());
+ }
+
+ /// <summary>
+ /// Logs the specified exception using the <see cref="EventTypes.ApplicationException" />.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ /// <param name="description"></param>
+ public void Log(Exception exception, string description)
+ {
+ Log(EventTypes.ApplicationException, description + Environment.NewLine + exception.ToString());
+ }
+
+ /// <summary>
+ /// Logs the specified message using the <see cref="EventTypes.ApplicationInformation"/>.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ public void Log(String message)
+ {
+ Log(EventTypes.ApplicationInformation, message);
+ }
+
+ /// <summary>
+ /// Logging thread loop.
+ /// </summary>
+ private void LogThreadMethod()
+ {
+ while (true)
+ {
+ FlushAll();
+ Thread.Sleep(5000);
+ }
+ }
+
+ /// <summary>
+ /// Immediately saves all pending events to database.
+ /// </summary>
+ public void FlushAll()
+ {
+ bool _saveChanges = false;
+
+ while (_events.Count > 0)
+ {
+ MachinesEvent ev = null;
+
+ if (_events.TryDequeue(out ev))
+ {
+ ev.User = null;
+ _db.MachinesEvents.Add(ev);
+ _saveChanges = true;
+ }
+ }
+
+ if (_saveChanges)
+ {
+ try
+ {
+ _db.SaveChanges();
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error saving machine event to database.");
+ }
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/IEventLogger.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/IEventLogger.cs
new file mode 100644
index 000000000..f7eadac1e
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/EventLogging/IEventLogger.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.Entities;
+using Tango.BL.Enumerations;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.PPC.Common.EventLogging
+{
+ /// <summary>
+ /// Represents a database events logger.
+ /// </summary>
+ public interface IEventLogger
+ {
+ /// <summary>
+ /// Occurs when a new machine event has been logged.
+ /// </summary>
+ event EventHandler<MachinesEvent> NewLog;
+
+ /// <summary>
+ /// Logs the specified machine event.
+ /// </summary>
+ /// <param name="machineEvent">The machine event.</param>
+ void Log(MachinesEvent machineEvent);
+
+ /// <summary>
+ /// Logs the specified event type.
+ /// </summary>
+ /// <param name="eventType">Type of the event.</param>
+ /// <param name="message">The message.</param>
+ void Log(EventTypes eventType, String message);
+
+ /// <summary>
+ /// Logs the specified hardware event.
+ /// </summary>
+ /// <param name="hardwareEvent">The hardware event.</param>
+ void Log(Event hardwareEvent);
+
+ /// <summary>
+ /// Logs the specified exception using the <see cref="EventTypes.ApplicationException"/>.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ void Log(Exception exception);
+
+ /// <summary>
+ /// Logs the specified exception using the <see cref="EventTypes.ApplicationException"/>.
+ /// </summary>
+ /// <param name="exception">The exception.</param>
+ void Log(Exception exception, String description);
+
+ /// <summary>
+ /// Logs the specified message using the <see cref="EventTypes.ApplicationInformation"/>.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ void Log(String message);
+
+ /// <summary>
+ /// Immediately saves all pending events to database.
+ /// </summary>
+ void FlushAll();
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationManager.cs
new file mode 100644
index 000000000..f29476631
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/INavigationManager.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.Navigation
+{
+ /// <summary>
+ /// Represents the Machine Studio views navigation manager.
+ /// </summary>
+ public interface INavigationManager
+ {
+ /// <summary>
+ /// Navigates to the specified view.
+ /// </summary>
+ /// <param name="view">The view.</param>
+ void NavigateTo(NavigationView view);
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs
new file mode 100644
index 000000000..d860bce76
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Navigation/NavigationView.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.Navigation
+{
+ /// <summary>
+ /// Represents the available views to navigate to using the <see cref="INavigationManager"/>.
+ /// </summary>
+ public enum NavigationView
+ {
+ LoadingView,
+ LayoutView,
+ JobsView,
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/DialogViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/DialogViewVM.cs
new file mode 100644
index 000000000..b7a48f259
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/DialogViewVM.cs
@@ -0,0 +1,74 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.SharedUI;
+
+namespace Tango.PPC.Common.Notifications
+{
+ /// <summary>
+ /// Represents a dialog view model base class.
+ /// </summary>
+ /// <seealso cref="Tango.SharedUI.ViewModel" />
+ public abstract class DialogViewVM : ViewModel
+ {
+ public event Action Accepted;
+ public event Action Canceled;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DialogViewVM"/> class.
+ /// </summary>
+ public DialogViewVM()
+ {
+ CanClose = true;
+ CloseCommand = new RelayCommand(Cancel, (x) => CanClose);
+ OKCommand = new RelayCommand(Accept, (x) => CanClose);
+ }
+
+ private bool _canClose;
+ /// <summary>
+ /// Gets or sets a value indicating whether this dialog can be closed.
+ /// </summary>
+ public bool CanClose
+ {
+ get { return _canClose; }
+ set { _canClose = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the close command.
+ /// </summary>
+ public RelayCommand CloseCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the ok command.
+ /// </summary>
+ public RelayCommand OKCommand { get; set; }
+
+ /// <summary>
+ /// Called when the dialog has been shown.
+ /// </summary>
+ public virtual void OnShow()
+ {
+
+ }
+
+ /// <summary>
+ /// Invokes the <see cref="Accepted"/> event.
+ /// </summary>
+ protected virtual void Accept()
+ {
+ Accepted?.Invoke();
+ }
+
+ /// <summary>
+ /// Invokes the <see cref="Canceled"/> event.
+ /// </summary>
+ protected virtual void Cancel()
+ {
+ Canceled?.Invoke();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/INotificationProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/INotificationProvider.cs
new file mode 100644
index 000000000..edad5c1e9
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/INotificationProvider.cs
@@ -0,0 +1,129 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+
+namespace Tango.PPC.Common.Notifications
+{
+ /// <summary>
+ /// Represents the Machine Studio user notification provider responsible for displaying information, alerts and dialogs to the user.
+ /// </summary>
+ public interface INotificationProvider
+ {
+ /// <summary>
+ /// Gets the collection of active task items.
+ /// </summary>
+ ObservableCollection<TaskItem> TaskItems { get; }
+
+ /// <summary>
+ /// Gets the current displayed task item.
+ /// </summary>
+ TaskItem CurrentTaskItem { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether there are any queued task items.
+ /// </summary>
+ bool HasTaskItems { get; }
+
+ /// <summary>
+ /// Pushes the specified task item to the queue.
+ /// </summary>
+ /// <param name="taskItem">The task item.</param>
+ void PushTaskItem(TaskItem taskItem);
+
+ /// <summary>
+ /// Create and push a new task item from the specified message.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <returns></returns>
+ TaskItem PushTaskItem(String message);
+
+ /// <summary>
+ /// Removed the specified task item from the queue.
+ /// </summary>
+ /// <param name="taskItem">The task item.</param>
+ void PopTaskItem(TaskItem taskItem);
+
+ /// <summary>
+ /// Creates a new instance of the specified View type and displays it as a modal dialog.
+ /// </summary>
+ /// <typeparam name="View">The type of the view.</typeparam>
+ /// <typeparam name="VM">The type of the view model.</typeparam>
+ /// <param name="onAccept">Accept button callback.</param>
+ /// <param name="onCancel">Cancel button callback.</param>
+ void ShowModalDialog<View, VM>(Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM;
+
+ /// <summary>
+ /// Creates a new view by a naming convention of the specified view model type.
+ /// </summary>
+ /// <typeparam name="VM">The type of the view model.</typeparam>
+ /// <param name="onAccept">Accept button callback.</param>
+ /// <param name="onCancel">Cancel button callback.</param>
+ void ShowModalDialog<VM>(Action<VM> onAccept, Action onCancel) where VM : DialogViewVM;
+
+ /// <summary>
+ /// Shows the specified view with the specified view model as it's data context.
+ /// </summary>
+ /// <typeparam name="VM">The type of the mm.</typeparam>
+ /// <typeparam name="View">The type of the view.</typeparam>
+ /// <param name="vm">The view model.</param>
+ /// <param name="onAccept">The accept action.</param>
+ /// <param name="onCancel">The cancel action.</param>
+ void ShowModalDialog<VM, View>(VM vm, Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM;
+
+ /// <summary>
+ /// Shows the specified view with the specified view model as it's data context.
+ /// </summary>
+ /// <typeparam name="VM">The type of the mm.</typeparam>
+ /// <typeparam name="View">The type of the view.</typeparam>
+ /// <param name="vm">The view model.</param>
+ /// <param name="view">The view.</param>
+ /// <param name="onAccept">The accept action.</param>
+ /// <param name="onCancel">The cancel action.</param>
+ void ShowModalDialog<VM, View>(VM vm, View view, Action<VM> onAccept, Action onCancel) where View : FrameworkElement where VM : DialogViewVM;
+
+ /// <summary>
+ /// Creates a new view by a naming convention of the specified view model type.
+ /// </summary>
+ /// <typeparam name="VM">The type of the view model.</typeparam>
+ /// <param name="onAccept">Accept button callback.</param>
+ void ShowModalDialog<VM>(Action<VM> onAccept) where VM : DialogViewVM;
+
+ /// <summary>
+ /// Shows an information message box.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ void ShowInfo(String message);
+
+ /// <summary>
+ /// Shows warning message box.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ void ShowWarning(String message);
+
+ /// <summary>
+ /// Shows an error message box.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ void ShowError(String message);
+
+ /// <summary>
+ /// Shows a question message box.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ bool ShowQuestion(String message);
+
+ /// <summary>
+ /// Shows a dialog with a text input field and returns the response.
+ /// </summary>
+ /// <param name="message">The message.</param>
+ /// <param name="hint">Text field hint.</param>
+ /// <param name="defaultResponse">Optional default response.</param>
+ /// <returns></returns>
+ String ShowTextInput(String message, String hint, String defaultResponse = null);
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/TaskItem.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/TaskItem.cs
new file mode 100644
index 000000000..b9ffa4a72
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Notification/TaskItem.cs
@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+
+namespace Tango.PPC.Common.Notifications
+{
+ /// <summary>
+ /// Represents a Machine Studio "work-bar" item.
+ /// </summary>
+ /// <seealso cref="Tango.Core.ExtendedObject" />
+ /// <seealso cref="System.IDisposable" />
+ public class TaskItem : ExtendedObject, IDisposable
+ {
+ private INotificationProvider _notificationProvider;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TaskItem"/> class.
+ /// </summary>
+ /// <param name="notificationProvider">The notification provider.</param>
+ public TaskItem(INotificationProvider notificationProvider)
+ {
+ _notificationProvider = notificationProvider;
+ }
+
+ private String _message;
+ /// <summary>
+ /// Gets or sets the message.
+ /// </summary>
+ public String Message
+ {
+ get { return _message; }
+ set { _message = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Removed this item from the queue.
+ /// </summary>
+ public void Pop()
+ {
+ _notificationProvider.PopTaskItem(this);
+ }
+
+ /// <summary>
+ /// Pushes this item to the queue.
+ /// </summary>
+ public void Push()
+ {
+ _notificationProvider.PushTaskItem(this);
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public void Dispose()
+ {
+ Pop();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs
new file mode 100644
index 000000000..db04c04ee
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Settings;
+
+namespace Tango.PPC.Common
+{
+ public class PPCSettings : SettingsBase
+ {
+ public String MachineSerialNumber { get; set; }
+
+ public PPCSettings()
+ {
+ MachineSerialNumber = "1111";
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
new file mode 100644
index 000000000..e5f13e394
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PPC.Common.Application;
+using Tango.PPC.Common.Authentication;
+using Tango.PPC.Common.Navigation;
+using Tango.PPC.Common.Notifications;
+using Tango.Settings;
+using Tango.SharedUI;
+
+namespace Tango.PPC.Common
+{
+ public abstract class PPCViewModel : ViewModel
+ {
+ public IPPCApplicationManager ApplicationManager { get; private set; }
+
+ public IAuthenticationProvider AuthenticationProvider { get; private set; }
+
+ public INavigationManager NavigationManager { get; private set; }
+
+ public INotificationProvider NotificationProvider { get; private set; }
+
+ public PPCSettings Settings { get; private set; }
+
+ public PPCViewModel(IPPCApplicationManager application, IAuthenticationProvider authentication, INavigationManager navigation, INotificationProvider notification)
+ {
+ ApplicationManager = application;
+ AuthenticationProvider = authentication;
+ NavigationManager = navigation;
+ NotificationProvider = notification;
+
+ Settings = SettingsManager.Default.GetOrCreate<PPCSettings>();
+ }
+
+ public abstract void OnApplicationStarted();
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/AssemblyInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..3394347d0
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tango.PPC.Common")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Tango.PanelPC.Common")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>. For example, if you are using US english
+//in your source files, set the <UICulture> to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly:ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.Designer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..243da50ac
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.Designer.cs
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.PPC.Common.Properties {
+
+
+ /// <summary>
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// </summary>
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ /// <summary>
+ /// Returns the cached ResourceManager instance used by this class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if ((resourceMan == null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tango.PanelPC.Common.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.resx b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.Designer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..8537a6bb1
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.PPC.Common.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.settings b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.settings
new file mode 100644
index 000000000..033d7a5e9
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
new file mode 100644
index 000000000..3a3090c6a
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
@@ -0,0 +1,188 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{0BE74EEE-22CB-4DBA-B896-793B9E1A3AC0}</ProjectGuid>
+ <OutputType>library</OutputType>
+ <RootNamespace>Tango.PanelPC.Common</RootNamespace>
+ <AssemblyName>Tango.PanelPC.Common</AssemblyName>
+ <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ <PublishUrl>publish\</PublishUrl>
+ <Install>true</Install>
+ <InstallFrom>Disk</InstallFrom>
+ <UpdateEnabled>false</UpdateEnabled>
+ <UpdateMode>Foreground</UpdateMode>
+ <UpdateInterval>7</UpdateInterval>
+ <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+ <UpdatePeriodically>false</UpdatePeriodically>
+ <UpdateRequired>false</UpdateRequired>
+ <MapFileExtensions>true</MapFileExtensions>
+ <ApplicationRevision>0</ApplicationRevision>
+ <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+ <IsWebBootstrapper>false</IsWebBootstrapper>
+ <UseApplicationTrust>false</UseApplicationTrust>
+ <BootstrapperEnabled>true</BootstrapperEnabled>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\Build\Debug\PPC\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.dll</HintPath>
+ </Reference>
+ <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+ </Reference>
+ <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL">
+ <HintPath>..\..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xaml">
+ <RequiredTargetFramework>4.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="Controls\MultiPieChart.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Themes\Generic.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Compile Include="Application\IPPCApplicationManager.cs" />
+ <Compile Include="Authentication\DefaultAuthenticationProvider.cs" />
+ <Compile Include="Authentication\IAuthenticationProvider.cs" />
+ <Compile Include="Controls\MultiPieChart.xaml.cs">
+ <DependentUpon>MultiPieChart.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Controls\MultiPieChartBrushCollection.cs" />
+ <Compile Include="Converters\SegmentsToPieConverter.cs" />
+ <Compile Include="CustomControl1.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="Diagnostics\DefaultDiagnosticsFrameProvider.cs" />
+ <Compile Include="Diagnostics\IDiagnosticsFrameProvider.cs" />
+ <Compile Include="EventLogging\DefaultEventLogger.cs" />
+ <Compile Include="EventLogging\IEventLogger.cs" />
+ <Compile Include="Navigation\INavigationManager.cs" />
+ <Compile Include="Navigation\NavigationView.cs" />
+ <Compile Include="Notification\DialogViewVM.cs" />
+ <Compile Include="Notification\INotificationProvider.cs" />
+ <Compile Include="Notification\TaskItem.cs" />
+ <Compile Include="PPCSettings.cs" />
+ <Compile Include="PPCViewModel.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="app.config" />
+ <None Include="packages.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Tango.BL\Tango.BL.csproj">
+ <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project>
+ <Name>Tango.BL</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.Integration\Tango.Integration.csproj">
+ <Project>{4206ac58-3b57-4699-8835-90bf6db01a61}</Project>
+ <Name>Tango.Integration</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.Logging\Tango.Logging.csproj">
+ <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
+ <Name>Tango.Logging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.PMR\Tango.PMR.csproj">
+ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project>
+ <Name>Tango.PMR</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.Settings\Tango.Settings.csproj">
+ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project>
+ <Name>Tango.Settings</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.SharedUI\Tango.SharedUI.csproj">
+ <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project>
+ <Name>Tango.SharedUI</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.Transport\Tango.Transport.csproj">
+ <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project>
+ <Name>Tango.Transport</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Content Include="..\..\..\DB\Tango.mdf">
+ <Link>DB\Tango.mdf</Link>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ <Content Include="..\..\..\DB\Tango_log.ldf">
+ <Link>DB\Tango_log.ldf</Link>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </Content>
+ </ItemGroup>
+ <ItemGroup>
+ <BootstrapperPackage Include=".NETFramework,Version=v4.6">
+ <Visible>False</Visible>
+ <ProductName>Microsoft .NET Framework 4.6 %28x86 and x64%29</ProductName>
+ <Install>true</Install>
+ </BootstrapperPackage>
+ <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+ <Visible>False</Visible>
+ <ProductName>.NET Framework 3.5 SP1</ProductName>
+ <Install>false</Install>
+ </BootstrapperPackage>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Themes/Generic.xaml b/Software/Visual_Studio/PPC/Tango.PPC.Common/Themes/Generic.xaml
new file mode 100644
index 000000000..af7652bf7
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Themes/Generic.xaml
@@ -0,0 +1,18 @@
+<ResourceDictionary
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:local="clr-namespace:Tango.PPC.Common">
+ <Style TargetType="{x:Type local:CustomControl1}">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type local:CustomControl1}">
+ <Border Background="{TemplateBinding Background}"
+ BorderBrush="{TemplateBinding BorderBrush}"
+ BorderThickness="{TemplateBinding BorderThickness}">
+
+ </Border>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ </Style>
+</ResourceDictionary>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/app.config b/Software/Visual_Studio/PPC/Tango.PPC.Common/app.config
new file mode 100644
index 000000000..dcbe9e918
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/app.config
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <configSections>
+ <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
+ <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+ </configSections>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+ <entityFramework>
+ <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
+ <providers>
+ <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+ </providers>
+ </entityFramework>
+</configuration> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/packages.config b/Software/Visual_Studio/PPC/Tango.PPC.Common/packages.config
new file mode 100644
index 000000000..033360b54
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/packages.config
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="EntityFramework" version="6.0.0" targetFramework="net46" />
+ <package id="Google.Protobuf" version="3.4.1" targetFramework="net46" />
+</packages> \ No newline at end of file