aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio
diff options
context:
space:
mode:
authorRoy <roy.mail.net@gmail.com>2018-02-14 22:51:52 +0200
committerRoy <roy.mail.net@gmail.com>2018-02-14 22:51:52 +0200
commitb934b152eea671fa06678baa0cdf7f8811e6d2d9 (patch)
tree35c092bff1e06905c70c23e60ed1a9fdf9825e5a /Software/Visual_Studio/MachineStudio
parent12967bd645e92f7b08b8d323b93225e027ad69f0 (diff)
downloadTango-b934b152eea671fa06678baa0cdf7f8811e6d2d9.tar.gz
Tango-b934b152eea671fa06678baa0cdf7f8811e6d2d9.zip
MERGE.
Diffstat (limited to 'Software/Visual_Studio/MachineStudio')
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/DataCaptureModule.cs84
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/capture-device.pngbin0 -> 1812 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/data-capture.jpgbin0 -> 121309 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/recordings.pngbin0 -> 858 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/tape.pngbin0 -> 713 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/video-frame.pngbin0 -> 97254 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/AssemblyInfo.cs18
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Resources.Designer.cs62
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Resources.resx117
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Settings.Designer.cs30
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Settings.settings7
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Recording/DataRecording.cs37
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Tango.MachineStudio.DataCapture.csproj174
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModelLocator.cs33
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModels/MainViewVM.cs297
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml250
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml50
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/packages.config8
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Converters/OneToPercentConverter.cs23
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/TechIosToDigitalInsConverter.cs35
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/TechIosToDigitalOutsConverter.cs35
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalInElementEditor.xaml92
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalInElementEditor.xaml.cs90
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml103
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml.cs90
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/digital-in.pngbin0 -> 2082 bytes
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml33
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml33
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml.cs28
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalInItem.cs73
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalOutItem.cs98
-rw-r--r--Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/TechItemAttribute.cs29
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs84
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/IDiagnosticsFrameProvider.cs31
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/BarItem.cs46
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioModuleBase.cs113
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/DefaultVideoCaptureProvider.cs44
-rw-r--r--Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/IVideoCaptureProvider.cs21
41 files changed, 2352 insertions, 0 deletions
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/DataCaptureModule.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/DataCaptureModule.cs
new file mode 100644
index 000000000..ee650dc13
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/DataCaptureModule.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media.Imaging;
+using Tango.Integration.Observables;
+using Tango.MachineStudio.Common;
+using Tango.MachineStudio.DataCapture.Views;
+using Tango.SharedUI.Helpers;
+
+namespace Tango.MachineStudio.DataCapture
+{
+ /// <summary>
+ /// Represents the machine studio data capturing and playing module.
+ /// </summary>
+ /// <seealso cref="Tango.MachineStudio.Common.StudioModuleBase" />
+ public class DataCaptureModule : StudioModuleBase
+ {
+ /// <summary>
+ /// Gets the module name.
+ /// </summary>
+ public override string Name
+ {
+ get
+ {
+ return "Data Capture";
+ }
+ }
+
+ /// <summary>
+ /// Gets the module description.
+ /// </summary>
+ public override string Description
+ {
+ get
+ {
+ return "Capture and synchronize diagnostics machine data with video capturing devices for later analysis";
+ }
+ }
+
+ /// <summary>
+ /// Gets the module cover image.
+ /// </summary>
+ public override BitmapSource Image
+ {
+ get
+ {
+ return ResourceHelper.GetImageFromResources("Images/data-capture.jpg");
+ }
+ }
+
+ /// <summary>
+ /// Gets the module entry point view.
+ /// </summary>
+ public override FrameworkElement MainView
+ {
+ get
+ {
+ return new MainView();
+ }
+ }
+
+ /// <summary>
+ /// Gets the permission required to see and load this module.
+ /// </summary>
+ public override Permissions Permission
+ {
+ get
+ {
+ return Permissions.RunTechnicianModule;
+ }
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public override void Dispose()
+ {
+
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/capture-device.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/capture-device.png
new file mode 100644
index 000000000..5f04b660a
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/capture-device.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/data-capture.jpg b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/data-capture.jpg
new file mode 100644
index 000000000..87524f07a
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/data-capture.jpg
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/recordings.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/recordings.png
new file mode 100644
index 000000000..a965c62af
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/recordings.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/tape.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/tape.png
new file mode 100644
index 000000000..8a4739b23
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/tape.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/video-frame.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/video-frame.png
new file mode 100644
index 000000000..9c29dc438
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Images/video-frame.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/AssemblyInfo.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..0fd6e93b2
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/AssemblyInfo.cs
@@ -0,0 +1,18 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+[assembly: AssemblyTitle("Tango - Machine Studio Data Capturing Module")]
+
+[assembly: ComVisible(false)]
+
+[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)
+)]
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Resources.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..fdd6d78b8
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/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.MachineStudio.DataCapture.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.MachineStudio.DataCapture.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/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Resources.resx b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/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/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Settings.Designer.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..8a9ab67ad
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/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.MachineStudio.DataCapture.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/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Settings.settings b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Properties/Settings.settings
new file mode 100644
index 000000000..033d7a5e9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/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/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Recording/DataRecording.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Recording/DataRecording.cs
new file mode 100644
index 000000000..a191c244e
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Recording/DataRecording.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+
+namespace Tango.MachineStudio.DataCapture.Recording
+{
+ public class DataRecording : ExtendedObject
+ {
+ private DateTime _date;
+
+ public DateTime Date
+ {
+ get { return _date; }
+ set { _date = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _name;
+
+ public String Name
+ {
+ get { return _name; }
+ set { _name = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _file;
+
+ public String FilePath
+ {
+ get { return _file; }
+ set { _file = value; RaisePropertyChangedAuto(); }
+ }
+
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Tango.MachineStudio.DataCapture.csproj b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Tango.MachineStudio.DataCapture.csproj
new file mode 100644
index 000000000..1c13be809
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Tango.MachineStudio.DataCapture.csproj
@@ -0,0 +1,174 @@
+<?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>{FC337A7F-1214-41D8-9992-78092A3B961E}</ProjectGuid>
+ <OutputType>library</OutputType>
+ <RootNamespace>Tango.MachineStudio.DataCapture</RootNamespace>
+ <AssemblyName>Tango.MachineStudio.DataCapture</AssemblyName>
+ <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\Build\Debug\</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="GalaSoft.MvvmLight, Version=5.3.0.19026, Culture=neutral, PublicKeyToken=e7570ab207bcb616, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.dll</HintPath>
+ </Reference>
+ <Reference Include="GalaSoft.MvvmLight.Extras, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=669f0b5e8f868abf, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Extras.dll</HintPath>
+ </Reference>
+ <Reference Include="GalaSoft.MvvmLight.Platform, Version=5.3.0.19032, Culture=neutral, PublicKeyToken=5f873c45e98af8a1, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MvvmLightLibs.5.3.0.0\lib\net45\GalaSoft.MvvmLight.Platform.dll</HintPath>
+ </Reference>
+ <Reference Include="MahApps.Metro, Version=1.5.0.23, Culture=neutral, PublicKeyToken=f4fb5a3c4d1e5b4f, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\MahApps.Metro.dll</HintPath>
+ </Reference>
+ <Reference Include="MaterialDesignColors, Version=1.1.2.0, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MaterialDesignColors.1.1.2\lib\net45\MaterialDesignColors.dll</HintPath>
+ </Reference>
+ <Reference Include="MaterialDesignThemes.Wpf, Version=2.3.1.953, Culture=neutral, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MaterialDesignThemes.2.3.1.953\lib\net45\MaterialDesignThemes.Wpf.dll</HintPath>
+ </Reference>
+ <Reference Include="Microsoft.Practices.ServiceLocation, Version=1.3.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll</HintPath>
+ </Reference>
+ <Reference Include="System" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\MahApps.Metro.1.5.0\lib\net45\System.Windows.Interactivity.dll</HintPath>
+ </Reference>
+ <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>
+ <Compile Include="Recording\DataRecording.cs" />
+ <Compile Include="ViewModelLocator.cs" />
+ <Compile Include="ViewModels\MainViewVM.cs" />
+ <Compile Include="Views\MainView.xaml.cs">
+ <DependentUpon>MainView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="..\..\..\Versioning\GlobalVersionInfo.cs">
+ <Link>GlobalVersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="DataCaptureModule.cs" />
+ <Compile Include="Views\RecordingBarView.xaml.cs">
+ <DependentUpon>RecordingBarView.xaml</DependentUpon>
+ </Compile>
+ <Page Include="Views\MainView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\RecordingBarView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <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="packages.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <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>
+ <ProjectReference Include="..\..\..\Tango.Video\Tango.Video.csproj">
+ <Project>{9652f972-2bd1-4283-99cb-fc6240434c17}</Project>
+ <Name>Tango.Video</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.MachineStudio.Common\Tango.MachineStudio.Common.csproj">
+ <Project>{cb0b0aa2-bb24-4bca-a720-45e397684e12}</Project>
+ <Name>Tango.MachineStudio.Common</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\data-capture.jpg" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\recordings.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\tape.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\video-frame.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\capture-device.png" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModelLocator.cs
new file mode 100644
index 000000000..98c5db8fe
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModelLocator.cs
@@ -0,0 +1,33 @@
+using GalaSoft.MvvmLight;
+using GalaSoft.MvvmLight.Ioc;
+using Microsoft.Practices.ServiceLocation;
+using Tango.MachineStudio.DataCapture.ViewModels;
+using Tango.MachineStudio.DataCapture.Views;
+
+namespace Tango.MachineStudio.DataCapture
+{
+ /// <summary>
+ /// This class contains static references to all the view models in the
+ /// application and provides an entry point for the bindings.
+ /// </summary>
+ public static class ViewModelLocator
+ {
+ /// <summary>
+ /// Initializes a new instance of the ViewModelLocator class.
+ /// </summary>
+ static ViewModelLocator()
+ {
+ ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
+
+ SimpleIoc.Default.Register<MainViewVM>();
+ }
+
+ public static MainViewVM MainViewVM
+ {
+ get
+ {
+ return ServiceLocator.Current.GetInstance<MainViewVM>();
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModels/MainViewVM.cs
new file mode 100644
index 000000000..b63ee51d0
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/ViewModels/MainViewVM.cs
@@ -0,0 +1,297 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Controls;
+using Tango.Core.Commands;
+using Tango.Integration.Diagnostics;
+using Tango.Integration.Operators;
+using Tango.MachineStudio.Common.Diagnostics;
+using Tango.MachineStudio.Common.Notifications;
+using Tango.MachineStudio.Common.StudioApplication;
+using Tango.MachineStudio.Common.Video;
+using Tango.MachineStudio.DataCapture.Recording;
+using Tango.MachineStudio.DataCapture.Views;
+using Tango.PMR.Diagnostics;
+using Tango.Settings;
+using Tango.SharedUI;
+using Tango.Video.DirectCapture;
+
+namespace Tango.MachineStudio.DataCapture.ViewModels
+{
+ /// <summary>
+ /// Represents the data capture main view, view model.
+ /// </summary>
+ /// <seealso cref="Tango.SharedUI.ViewModel" />
+ public class MainViewVM : ViewModel
+ {
+ private INotificationProvider _notification;
+ private IStudioApplicationManager _applicationManager;
+ private IDiagnosticsFrameProvider _frameProvider;
+ private String _recordingsFolder;
+
+ #region Properties
+
+ private ObservableCollection<DataRecording> _recordings;
+ /// <summary>
+ /// Gets or sets the recordings collection.
+ /// </summary>
+ public ObservableCollection<DataRecording> Recordings
+ {
+ get { return _recordings; }
+ set { _recordings = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DataRecording _selectedRecording;
+ /// <summary>
+ /// Gets or sets the selected recording.
+ /// </summary>
+ public DataRecording SelectedRecording
+ {
+ get { return _selectedRecording; }
+ set { _selectedRecording = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the video capture provider.
+ /// </summary>
+ public IVideoCaptureProvider VideoCaptureProvider { get; set; }
+
+ private DiagnosticsFileRecorder _recorder;
+ /// <summary>
+ /// Gets or sets the diagnostics file recorder.
+ /// </summary>
+ public DiagnosticsFileRecorder Recorder
+ {
+ get { return _recorder; }
+ set { _recorder = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DiagnosticsFilePlayer _player;
+ /// <summary>
+ /// Gets or sets the diagnostics file player.
+ /// </summary>
+ public DiagnosticsFilePlayer Player
+ {
+ get { return _player; }
+ set { _player = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Gets or sets the machine operator.
+ /// </summary>
+ public IMachineOperator MachineOperator { get; set; }
+
+ #endregion
+
+ #region Commands
+
+ /// <summary>
+ /// Gets or sets the remove recording command.
+ /// </summary>
+ public RelayCommand<DataRecording> RemoveRecordingCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the toggle camera command.
+ /// </summary>
+ public RelayCommand<CaptureDevice> ToggleCameraCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the media recording command.
+ /// </summary>
+ public RelayCommand MediaRecordingCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the media stop command.
+ /// </summary>
+ public RelayCommand MediaStopCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the media toggle play pause command.
+ /// </summary>
+ public RelayCommand MediaTogglePlayPauseCommand { get; set; }
+
+ /// <summary>
+ /// Gets or sets the media play pause command.
+ /// </summary>
+ public RelayCommand MediaPlayPauseCommand { get; set; }
+
+ #endregion
+
+ #region Constructors
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MainViewVM"/> class.
+ /// </summary>
+ public MainViewVM(IVideoCaptureProvider videoCaptureProvider, INotificationProvider notification, IStudioApplicationManager applicationManager, IDiagnosticsFrameProvider frameProvider)
+ {
+ _notification = notification;
+ _applicationManager = applicationManager;
+ _frameProvider = frameProvider;
+
+ Recorder = new DiagnosticsFileRecorder();
+ Player = new DiagnosticsFilePlayer();
+
+ VideoCaptureProvider = videoCaptureProvider;
+ Recordings = new ObservableCollection<DataRecording>();
+
+ ToggleCameraCommand = new RelayCommand<CaptureDevice>(ToggleCamera);
+
+ Recordings.Add(new DataRecording()
+ {
+ Name = "Recording 1"
+ });
+ Recordings.Add(new DataRecording()
+ {
+ Name = "Recording 2"
+ });
+ Recordings.Add(new DataRecording()
+ {
+ Name = "Recording 3"
+ });
+
+ RemoveRecordingCommand = new RelayCommand<DataRecording>(RemoveRecording);
+
+ MediaRecordingCommand = new RelayCommand(StartDiagnosticsRecording, () => !Recorder.IsRecording && MachineOperator != null && !Player.IsPlaying);
+ MediaStopCommand = new RelayCommand(StopRecorderOrPlayer, () => Recorder.IsRecording || Player.IsPlaying);
+ MediaPlayPauseCommand = new RelayCommand(DiagnosticsTogglePlayPause, () => !Recorder.IsRecording && Player.IsLoaded);
+
+ _recordingsFolder = Path.Combine(SettingsManager.DefaultFolder, "Recordings");
+ Directory.CreateDirectory(_recordingsFolder);
+
+ _frameProvider.FrameReceived += _frameProvider_FrameReceived;
+
+ _notification.PushBarItem(new RecordingBarView() { DataContext = this });
+
+ applicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged;
+ }
+
+ private void ApplicationManager_ConnectedMachineChanged(object sender, Integration.Services.IExternalBridgeClient machine)
+ {
+ MachineOperator = machine;
+ InvalidateRelayCommands();
+ }
+
+ private void _frameProvider_FrameReceived(object sender, PushDiagnosticsResponse frame)
+ {
+ if (!_frameProvider.Disable)
+ {
+ if (Recorder.IsRecording)
+ {
+ Recorder.Write(frame);
+ }
+ }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ /// <summary>
+ /// Removes the recording.
+ /// </summary>
+ /// <param name="recording">The recording.</param>
+ private void RemoveRecording(DataRecording recording)
+ {
+ Recordings.Remove(recording);
+ }
+
+ /// <summary>
+ /// Toggles the camera.
+ /// </summary>
+ /// <param name="captureDevice">The capture device.</param>
+ private void ToggleCamera(CaptureDevice captureDevice)
+ {
+ if (captureDevice.Device != null)
+ {
+ captureDevice.IsStarted = !captureDevice.IsStarted;
+ }
+ }
+
+ private void DiagnosticsTogglePlayPause()
+ {
+ if (!Player.IsPlaying || Player.IsPaused)
+ {
+ _frameProvider.Disable = true;
+ Player.Play();
+ }
+ else
+ {
+ Player.Pause();
+ }
+
+ InvalidateRelayCommands();
+ }
+
+ private async void LoadSelectedRecording()
+ {
+ using (_notification.PushTaskItem("Loading Recording..."))
+ {
+ if (Player != null)
+ {
+ Player.Dispose();
+ }
+
+ Player = new DiagnosticsFilePlayer();
+ Player.FrameReceived += Player_FrameReceived;
+ await Player.Load(SelectedRecording.FilePath);
+ }
+
+ InvalidateRelayCommands();
+ }
+
+ private void Player_FrameReceived(object sender, DataFileFrame frame)
+ {
+ if (_frameProvider.Disable)
+ {
+ _frameProvider.PushFrame(frame.PushDiagnosticsResponse);
+ }
+ }
+
+ private void StartDiagnosticsRecording()
+ {
+ using (_notification.PushTaskItem("Starting Recording..."))
+ {
+ Recorder.Start();
+ }
+
+ InvalidateRelayCommands();
+ }
+
+ private async void StopRecorderOrPlayer()
+ {
+ if (Recorder.IsRecording)
+ {
+ using (_notification.PushTaskItem("Stopping Recording..."))
+ {
+ await Recorder.Stop();
+ }
+
+ String recordingName = _notification.ShowTextInput("Enter recording name", "Recording name");
+
+ if (!String.IsNullOrWhiteSpace(recordingName))
+ {
+ using (_notification.PushTaskItem("Saving Recording..."))
+ {
+ await Recorder.Save(Path.Combine(_recordingsFolder, recordingName + ".tdr"));
+ }
+ }
+
+ Recorder.Dispose();
+ Recorder = new DiagnosticsFileRecorder();
+ }
+ else if (Player.IsPlaying)
+ {
+ await Player.Stop();
+ _frameProvider.Disable = false;
+ }
+
+ InvalidateRelayCommands();
+ }
+
+ #endregion
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml
new file mode 100644
index 000000000..74addf942
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml
@@ -0,0 +1,250 @@
+<UserControl x:Class="Tango.MachineStudio.DataCapture.Views.MainView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:vm="clr-namespace:Tango.MachineStudio.DataCapture.ViewModels"
+ xmlns:video="clr-namespace:Tango.Video.DirectCapture;assembly=Tango.Video"
+ xmlns:global="clr-namespace:Tango.MachineStudio.DataCapture"
+ xmlns:local="clr-namespace:Tango.MachineStudio.DataCapture.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="1080" d:DesignWidth="1920" Background="White" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+
+ <UserControl.Resources>
+ <converters:StringEllipsisConverter x:Key="StringEllipsisConverter" />
+ <converters:BooleanToVisibilityInverseConverter x:Key="BooleanToVisibilityInverseConverter" />
+ <converters:NumberToFileSizeConverter x:Key="NumberToFileSizeConverter"/>
+ </UserControl.Resources>
+
+ <Grid>
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="250"/>
+ <ColumnDefinition Width="1*"/>
+ </Grid.ColumnDefinitions>
+
+ <Grid>
+ <DockPanel Margin="10">
+ <Grid DockPanel.Dock="Top">
+ <StackPanel Orientation="Horizontal" Margin="0 0 0 10">
+ <Image Source="../Images/recordings.png" Width="42"></Image>
+ <TextBlock VerticalAlignment="Center" Margin="10 0 0 0" Foreground="DimGray" FontSize="16" FontWeight="SemiBold">RECORDINGS</TextBlock>
+ </StackPanel>
+
+ <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Stroke="Gainsboro" StrokeDashArray="5 5 5 5"></Rectangle>
+ </Grid>
+
+ <Grid Margin="0 10 0 0">
+ <ListBox ItemsSource="{Binding Recordings}" SelectedItem="{Binding SelectedRecording}" HorizontalContentAlignment="Stretch">
+ <ListBox.ItemTemplate>
+ <DataTemplate>
+ <Grid HorizontalAlignment="Stretch">
+ <DockPanel>
+ <Button DockPanel.Dock="Right" Style="{StaticResource MaterialDesignFlatButton}" Padding="0" Width="24" Height="24" Foreground="#FF6F6F" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RemoveRecordingCommand}" CommandParameter="{Binding}">
+ <materialDesign:PackIcon Kind="Delete" Width="20" Height="20" />
+ </Button>
+
+ <StackPanel Orientation="Horizontal" DockPanel.Dock="Left">
+ <Image Source="../Images/tape.png" VerticalAlignment="Top" Width="32" Height="40" Stretch="Fill"></Image>
+ <TextBlock VerticalAlignment="Top" Margin="5 5 0 0">
+ <Run Text="{Binding Name}"></Run>
+ <LineBreak/>
+ <Run Text="{Binding Date}" FontSize="10"></Run>
+ </TextBlock>
+ </StackPanel>
+ </DockPanel>
+
+ </Grid>
+ </DataTemplate>
+ </ListBox.ItemTemplate>
+ </ListBox>
+ </Grid>
+ </DockPanel>
+
+ <Rectangle HorizontalAlignment="Right" VerticalAlignment="Stretch" Stroke="Gainsboro" StrokeDashArray="5 5 5 5" Margin="0 50 0 50"></Rectangle>
+ </Grid>
+
+ <Grid Grid.Column="1" Margin="10">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="430"/>
+ <RowDefinition Height="419*"/>
+ </Grid.RowDefinitions>
+
+ <Grid>
+ <DockPanel>
+ <StackPanel Orientation="Horizontal" Margin="0 0 0 10" DockPanel.Dock="Top" HorizontalAlignment="Center">
+ <Image Source="../Images/capture-device.png" Width="42"></Image>
+ <TextBlock VerticalAlignment="Center" Margin="10 10 0 0" Foreground="DimGray" FontSize="16" FontWeight="SemiBold">CAPTURE DEVICES</TextBlock>
+ </StackPanel>
+ <ItemsControl Margin="0 20 0 0" ItemsSource="{Binding VideoCaptureProvider.AvailableCaptureDevices}">
+ <ItemsControl.ItemsPanel>
+ <ItemsPanelTemplate>
+ <UniformGrid Rows="1" Columns="{Binding VideoCaptureProvider.AvailableCaptureDevices.Count}" />
+ </ItemsPanelTemplate>
+ </ItemsControl.ItemsPanel>
+ <ItemsControl.ItemTemplate>
+ <DataTemplate DataType="{x:Type video:CaptureDevice}">
+ <Border RenderOptions.BitmapScalingMode="Fant" Width="480">
+ <Border.Background>
+ <ImageBrush ImageSource="../Images/video-frame.png" Stretch="Fill"></ImageBrush>
+ </Border.Background>
+
+ <Grid>
+ <Border Margin="33 32 33 55">
+ <Grid>
+ <Border IsHitTestVisible="False" VerticalAlignment="Center" Padding="10" HorizontalAlignment="Center" Background="#20808080" CornerRadius="5">
+ <TextBlock FontSize="11" Text="{Binding Device.Name,Converter={StaticResource StringEllipsisConverter},ConverterParameter=30,FallbackValue='No Camera',TargetNullValue='No Camera'}"></TextBlock>
+ </Border>
+
+ <Image Source="{Binding VideoSource,Mode=OneWay,IsAsync=True}" Stretch="Fill" Visibility="{Binding IsStarted,Converter={StaticResource BooleanToVisibilityConverter}}"></Image>
+
+ <Grid Background="#83000000" Cursor="Hand">
+ <Grid.Style>
+ <Style TargetType="Grid">
+ <Setter Property="Opacity" Value="0"></Setter>
+ <Style.Triggers>
+ <EventTrigger RoutedEvent="MouseEnter">
+ <EventTrigger.Actions>
+ <BeginStoryboard>
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetProperty="Opacity" To="1" Duration="00:00:0.2"></DoubleAnimation>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger.Actions>
+ </EventTrigger>
+ <EventTrigger RoutedEvent="MouseLeave">
+ <EventTrigger.Actions>
+ <BeginStoryboard>
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="00:00:0.2"></DoubleAnimation>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger.Actions>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+ </Grid.Style>
+
+ <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.ToggleCameraCommand}" CommandParameter="{Binding}" Style="{StaticResource MaterialDesignFloatingActionMiniButton}" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Width="60" Height="60" Padding="0">
+ <materialDesign:PackIcon Width="40" Height="40">
+ <materialDesign:PackIcon.Style>
+ <Style TargetType="materialDesign:PackIcon">
+ <Setter Property="Kind" Value="Play"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding IsStarted}" Value="True">
+ <Setter Property="Kind" Value="Stop"></Setter>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding IsStarted}" Value="False">
+ <Setter Property="Kind" Value="Play"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </materialDesign:PackIcon.Style>
+ </materialDesign:PackIcon>
+ </Button>
+ </Grid>
+ </Grid>
+ </Border>
+ </Grid>
+ </Border>
+ </DataTemplate>
+ </ItemsControl.ItemTemplate>
+ </ItemsControl>
+ </DockPanel>
+
+ <Rectangle HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Stroke="Gainsboro" StrokeDashArray="5 5 5 5"></Rectangle>
+ </Grid>
+
+ <Grid Grid.Row="1">
+
+ <DockPanel HorizontalAlignment="Center" VerticalAlignment="Top" Margin="60" Visibility="{Binding Recorder.IsRecording,Converter={StaticResource BooleanToVisibilityConverter}}" TextElement.FontSize="40">
+ <TextBlock DockPanel.Dock="Left">
+ <Run FontWeight="SemiBold" FontStyle="Italic">Total Frames:</Run>
+ <Run FontStyle="Italic" Foreground="#545454" Text="{Binding Recorder.TotalFramesRecorded,StringFormat={}{0:N0},Mode=OneWay,TargetNullValue=0,FallbackValue=0}"></Run>
+ </TextBlock>
+ <TextBlock Margin="80 0 0 0" HorizontalAlignment="Right" Width="250">
+ <Run FontWeight="SemiBold" FontStyle="Italic">File Size:</Run>
+ <Run FontStyle="Italic" Foreground="#545454" Text="{Binding Recorder.TotalBytesRecorded,Mode=OneWay,Converter={StaticResource NumberToFileSizeConverter},TargetNullValue=0,FallbackValue=0}"></Run>
+ </TextBlock>
+ </DockPanel>
+
+ <StackPanel VerticalAlignment="Bottom" Margin="0 0 0 50">
+ <Grid Margin="50 0 0 0">
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center">
+ <Button Command="{Binding MediaStopCommand}" Margin="0 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="150" Height="150" Background="Transparent">
+ <materialDesign:PackIcon Width="100" Height="100" Kind="Rewind" Foreground="{StaticResource AccentColorBrush}" />
+ </Button>
+ <Button Command="{Binding MediaPlayPauseCommand}" Margin="20 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="200" Height="200" Background="Transparent">
+ <materialDesign:PackIcon Width="100" Height="100" Foreground="{StaticResource AccentColorBrush}">
+ <materialDesign:PackIcon.Style>
+ <Style TargetType="materialDesign:PackIcon">
+ <Setter Property="Kind" Value="Play"></Setter>
+ <Style.Triggers>
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding Player.IsPlaying}" Value="True" />
+ <Condition Binding="{Binding Player.IsPaused}" Value="False" />
+ </MultiDataTrigger.Conditions>
+ <Setter Property="Kind" Value="Pause"></Setter>
+ </MultiDataTrigger>
+ </Style.Triggers>
+ </Style>
+ </materialDesign:PackIcon.Style>
+ </materialDesign:PackIcon>
+ </Button>
+ <Button Command="{Binding MediaStopCommand}" Margin="20 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="150" Height="150" Background="Transparent">
+ <materialDesign:PackIcon Width="100" Height="100" Kind="Stop" Foreground="{StaticResource AccentColorBrush}" />
+ </Button>
+ <Button Command="{Binding MediaStopCommand}" Margin="20 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Padding="0" Width="150" Height="150" Background="Transparent">
+ <materialDesign:PackIcon Width="100" Height="100" Kind="FastForward" Foreground="{StaticResource AccentColorBrush}" />
+ </Button>
+ <Button Command="{Binding MediaRecordingCommand}" Margin="20 0 0 0" Style="{StaticResource MaterialDesignFloatingActionButton}" Foreground="#FF7A7A" BorderBrush="#FF8585" Padding="0" Width="100" Height="100" Background="Transparent" ToolTip="Start Recording">
+ <materialDesign:PackIcon Width="50" Height="50" Kind="Record" />
+ </Button>
+ </StackPanel>
+ <Grid>
+ <TextBlock Margin="0 0 50 0" VerticalAlignment="Center" HorizontalAlignment="Right" Foreground="#FF8585" FontSize="60" FontFamily="{StaticResource digital-7}">
+ <TextBlock.Style>
+ <Style TargetType="TextBlock">
+ <Setter Property="Opacity" Value="1"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Recorder.IsRecording}" Value="True">
+ <DataTrigger.EnterActions>
+ <BeginStoryboard>
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="00:00:01" RepeatBehavior="Forever">
+ <DiscreteDoubleKeyFrame KeyTime="00:00:00" Value="1" />
+ <DiscreteDoubleKeyFrame KeyTime="00:00:0.5" Value="0" />
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </BeginStoryboard>
+ </DataTrigger.EnterActions>
+ <DataTrigger.ExitActions>
+ <BeginStoryboard>
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="00:00:01">
+ <DiscreteDoubleKeyFrame KeyTime="00:00:00" Value="1" />
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </BeginStoryboard>
+ </DataTrigger.ExitActions>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </TextBlock.Style>
+ <Run Text="{Binding Player.CurrentTime,Mode=OneWay,StringFormat=hh\\:mm\\:ss,FallbackValue='00:00:00'}"/>
+ <Run>/</Run>
+ <Run Text="{Binding Player.TotalTime,Mode=OneWay,StringFormat=hh\\:mm\\:ss,FallbackValue='00:00:00'}"/>
+ </TextBlock>
+ </Grid>
+ </Grid>
+ <Slider Margin="10 40 50 0" Visibility="{Binding Recorder.IsRecording,Converter={StaticResource BooleanToVisibilityInverseConverter}}" Maximum="{Binding Player.TotalFrames}" Value="{Binding Player.CurrentFrame}"></Slider>
+ </StackPanel>
+ </Grid>
+ </Grid>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml.cs
new file mode 100644
index 000000000..624840d66
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/MainView.xaml.cs
@@ -0,0 +1,28 @@
+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.MachineStudio.DataCapture.Views
+{
+ /// <summary>
+ /// Interaction logic for MainView.xaml
+ /// </summary>
+ public partial class MainView : UserControl
+ {
+ public MainView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml
new file mode 100644
index 000000000..d076eb631
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml
@@ -0,0 +1,50 @@
+<UserControl x:Class="Tango.MachineStudio.DataCapture.Views.RecordingBarView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:vm="clr-namespace:Tango.MachineStudio.DataCapture.ViewModels"
+ xmlns:video="clr-namespace:Tango.Video.DirectCapture;assembly=Tango.Video"
+ xmlns:global="clr-namespace:Tango.MachineStudio.DataCapture"
+ xmlns:local="clr-namespace:Tango.MachineStudio.DataCapture.Views"
+ mc:Ignorable="d"
+ Width="200" Height="30" Background="{StaticResource AccentColorBrush}" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}">
+ <Grid>
+ <DockPanel>
+
+ <StackPanel Orientation="Horizontal" DockPanel.Dock="Right">
+ <TextBlock VerticalAlignment="Center" FontFamily="{StaticResource digital-7}" Text="{Binding Recorder.RecordingTime,Mode=OneWay,StringFormat=hh\\:mm\\:ss,FallbackValue='00:00:00'}" Foreground="#F6F6F6" FontSize="20"></TextBlock>
+ <Button Command="{Binding MediaStopCommand}" Style="{StaticResource MaterialDesignFlatButton}" Padding="0" Width="30" Height="30" Foreground="White" ToolTip="Stop">
+ <materialDesign:PackIcon Kind="Stop" Width="30" Height="30" />
+ </Button>
+ </StackPanel>
+
+ <StackPanel Orientation="Horizontal">
+ <Ellipse Width="12" Height="12" Fill="#FF6464" Margin="0 0 0 0">
+ <Ellipse.Style>
+ <Style TargetType="Ellipse">
+ <Style.Triggers>
+ <EventTrigger RoutedEvent="Loaded">
+ <EventTrigger.Actions>
+ <BeginStoryboard>
+ <Storyboard>
+ <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="Opacity" Duration="00:00:01" RepeatBehavior="Forever">
+ <DiscreteDoubleKeyFrame KeyTime="00:00:00" Value="1" />
+ <DiscreteDoubleKeyFrame KeyTime="00:00:0.5" Value="0" />
+ </DoubleAnimationUsingKeyFrames>
+ </Storyboard>
+ </BeginStoryboard>
+ </EventTrigger.Actions>
+ </EventTrigger>
+ </Style.Triggers>
+ </Style>
+ </Ellipse.Style>
+ </Ellipse>
+ <TextBlock Margin="5 0 0 0" Text="Recording..." VerticalAlignment="Center" Foreground="White" FontWeight="SemiBold" FontStyle="Italic"></TextBlock>
+ </StackPanel>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml.cs
new file mode 100644
index 000000000..97389a1e5
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/Views/RecordingBarView.xaml.cs
@@ -0,0 +1,28 @@
+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.MachineStudio.DataCapture.Views
+{
+ /// <summary>
+ /// Interaction logic for RecordingBarView.xaml
+ /// </summary>
+ public partial class RecordingBarView : UserControl
+ {
+ public RecordingBarView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/packages.config b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/packages.config
new file mode 100644
index 000000000..4fd672b32
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.DataCapture/packages.config
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="CommonServiceLocator" version="1.3" targetFramework="net46" />
+ <package id="MahApps.Metro" version="1.5.0" targetFramework="net46" />
+ <package id="MaterialDesignColors" version="1.1.2" targetFramework="net46" />
+ <package id="MaterialDesignThemes" version="2.3.1.953" targetFramework="net46" />
+ <package id="MvvmLightLibs" version="5.3.0.0" targetFramework="net46" />
+</packages> \ No newline at end of file
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Converters/OneToPercentConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Converters/OneToPercentConverter.cs
new file mode 100644
index 000000000..292de5cb4
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/Converters/OneToPercentConverter.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Tango.MachineStudio.Developer.Converters
+{
+ public class OneToPercentConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return System.Convert.ToDouble(value) * 100d;
+ }
+
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ return System.Convert.ToDouble(value) / 100d;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/TechIosToDigitalInsConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/TechIosToDigitalInsConverter.cs
new file mode 100644
index 000000000..4b587743d
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/TechIosToDigitalInsConverter.cs
@@ -0,0 +1,35 @@
+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;
+using Tango.Integration.Observables.Enumerations;
+
+namespace Tango.MachineStudio.Technician.Converters
+{
+ public class TechIosToDigitalInsConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ ObservableCollection<TechIo> ios = value as ObservableCollection<TechIo>;
+
+ if (ios != null)
+ {
+ return ios.Where(x => x.Type == IOType.DigitalInput.ToInt32()).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/Converters/TechIosToDigitalOutsConverter.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/TechIosToDigitalOutsConverter.cs
new file mode 100644
index 000000000..734c4bebf
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Converters/TechIosToDigitalOutsConverter.cs
@@ -0,0 +1,35 @@
+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;
+using Tango.Integration.Observables.Enumerations;
+
+namespace Tango.MachineStudio.Technician.Converters
+{
+ public class TechIosToDigitalOutsConverter : IValueConverter
+ {
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ {
+ ObservableCollection<TechIo> ios = value as ObservableCollection<TechIo>;
+
+ if (ios != null)
+ {
+ return ios.Where(x => x.Type == IOType.DigitalOutput.ToInt32()).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/DigitalInElementEditor.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalInElementEditor.xaml
new file mode 100644
index 000000000..29eab7042
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalInElementEditor.xaml
@@ -0,0 +1,92 @@
+<local:ElementEditor x:Class="Tango.MachineStudio.Technician.Editors.DigitalInElementEditor"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:sharedConverters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:items="clr-namespace:Tango.MachineStudio.Technician.TechItems"
+ xmlns:converters="clr-namespace:Tango.Editors.Converters;assembly=Tango.Editors"
+ xmlns:visuals="clr-namespace:Tango.Visuals;assembly=Tango.Visuals"
+ xmlns:local="clr-namespace:Tango.Editors;assembly=Tango.Editors"
+ mc:Ignorable="d" Background="Transparent" ClipToBounds="False" BorderThickness="0" MinWidth="1" MinHeight="1" RenderTransformOrigin="0.5,0.5" d:DataContext="{d:DesignInstance Type=items:DigitalInItem, IsDesignTimeCreatable=False}" Height="83.778" Width="72.703">
+
+ <UserControl.Resources>
+ <converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"></converters:BoolToVisibilityConverter>
+ <sharedConverters:BooleanInverseConverter x:Key="BooleanInverseConverter" />
+
+ <!--Theme-->
+ <SolidColorBrush x:Key="BorderBrush" Color="Transparent"></SolidColorBrush>
+ <SolidColorBrush x:Key="CornersBrush" Color="Red"></SolidColorBrush>
+ </UserControl.Resources>
+
+ <UserControl.RenderTransform>
+ <RotateTransform Angle="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=Angle}"></RotateTransform>
+ </UserControl.RenderTransform>
+
+ <Grid>
+
+
+ <!--Content-->
+ <Grid IsHitTestVisible="{Binding RelativeSource={RelativeSource AncestorType=local:ElementsEditor},Path=IsEditable,Converter={StaticResource BooleanInverseConverter}}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="221*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+
+ <Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5" Padding="5">
+ <Border.Background>
+ <ImageBrush ImageSource="../Images/black-screen.jpg" Opacity="0.1" />
+ </Border.Background>
+ <Grid>
+ <Viewbox Margin="5">
+ <visuals:Led Width="100" Height="100" IsChecked="{Binding Value}" IsHitTestVisible="False" />
+ </Viewbox>
+ </Grid>
+ </Border>
+
+ <Border VerticalAlignment="Bottom" Grid.Row="1" Margin="0 0 0 0">
+ <TextBlock TextWrapping="Wrap" FontSize="14" Foreground="DimGray" HorizontalAlignment="Center" Text="{Binding TechIo.Description}"></TextBlock>
+ </Border>
+ </Grid>
+ <!--Content-->
+
+
+ <Border BorderThickness="1" BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=BorderBrush,TargetNullValue={StaticResource BorderBrush},FallbackValue={StaticResource BorderBrush}}" Visibility="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=(local:ElementsEditor.IsSelected),Converter={StaticResource BoolToVisibilityConverter}}">
+ <Grid>
+ <ContentPresenter Content="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=InnerContent}"></ContentPresenter>
+
+ <Thumb Opacity="0" DragDelta="MoveDrag" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb HorizontalAlignment="Left" Cursor="SizeWE" Opacity="0" DragDelta="DragLeft" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb HorizontalAlignment="Right" Cursor="SizeWE" Opacity="0" DragDelta="DragRight" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb VerticalAlignment="Top" Cursor="SizeNS" Opacity="0" DragDelta="DragTop" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb VerticalAlignment="Bottom" Cursor="SizeNS" Opacity="0" DragDelta="DragBottom" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+
+ <Grid ClipToBounds="False" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0 -20 0 0" Width="10" Height="10">
+ <Ellipse Stroke="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" StrokeThickness="2"></Ellipse>
+ <Rectangle HorizontalAlignment="Center" VerticalAlignment="Stretch" Margin="0 10 0 -8" StrokeThickness="1" Stroke="Red"></Rectangle>
+ <Thumb Opacity="0" DragDelta="DragAngle" DragStarted="DragStarted" Cursor="Arrow" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="-8 -8 0 0">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="2 2 0 0"></Border>
+ <Thumb Opacity="0" DragDelta="DragTopLeft" DragStarted="DragStarted" Cursor="SizeNWSE" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 -8 -8 0">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="0 2 2 0"></Border>
+ <Thumb Opacity="0" DragDelta="DragTopRight" DragStarted="DragStarted" Cursor="SizeNESW" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0 0 -8 -8">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="0 0 2 2"></Border>
+ <Thumb Opacity="0" DragDelta="DragBottomRight" DragStarted="DragStarted" Cursor="SizeNWSE" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="-8 0 0 -8">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="2 0 0 2"></Border>
+ <Thumb Opacity="0" DragDelta="DragBottomLeft" DragStarted="DragStarted" Cursor="SizeNESW" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+ </Grid>
+ </Border>
+ </Grid>
+</local:ElementEditor>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalInElementEditor.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalInElementEditor.xaml.cs
new file mode 100644
index 000000000..e884e70b9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalInElementEditor.xaml.cs
@@ -0,0 +1,90 @@
+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 DigitalInElementEditor : ElementEditor
+ {
+ public DigitalInElementEditor()
+ : base()
+ {
+ InitializeComponent();
+ }
+
+ public DigitalInElementEditor(DigitalInItem digitalInItem)
+ : this()
+ {
+ DigitalInItem = digitalInItem;
+ DataContext = DigitalInItem;
+ }
+
+ public DigitalInElementEditor(DigitalInItem digitalInItem, Rect bounds)
+ : this(digitalInItem)
+ {
+ Left = bounds.Left;
+ Top = bounds.Top;
+ Width = bounds.Width;
+ Height = bounds.Height;
+ }
+
+ private DigitalInItem _digitalInItem;
+
+ public DigitalInItem DigitalInItem
+ {
+ get { return _digitalInItem; }
+ set { _digitalInItem = value; RaisePropertyChanged(nameof(DigitalInItem)); }
+ }
+
+
+ /// <summary>
+ /// Clones this instance.
+ /// </summary>
+ /// <returns></returns>
+ public override IElementEditor Clone()
+ {
+ try
+ {
+ var clonedItem = DigitalInItem.Clone() as DigitalInItem;
+ DigitalInElementEditor cloned = new DigitalInElementEditor(clonedItem);
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Gets the hosted element.
+ /// </summary>
+ [ParameterIgnore]
+ public override Object HostedElement
+ {
+ get { return DigitalInItem; }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml
new file mode 100644
index 000000000..dcf78ca69
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml
@@ -0,0 +1,103 @@
+<local:ElementEditor x:Class="Tango.MachineStudio.Technician.Editors.DigitalOutElementEditor"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:sharedConverters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI"
+ xmlns:items="clr-namespace:Tango.MachineStudio.Technician.TechItems"
+ xmlns:converters="clr-namespace:Tango.Editors.Converters;assembly=Tango.Editors"
+ xmlns:visuals="clr-namespace:Tango.Visuals;assembly=Tango.Visuals"
+ xmlns:local="clr-namespace:Tango.Editors;assembly=Tango.Editors"
+ mc:Ignorable="d"
+ d:DesignHeight="88.852" d:DesignWidth="142.323" Background="Transparent" ClipToBounds="False" BorderThickness="0" MinWidth="1" MinHeight="1" RenderTransformOrigin="0.5,0.5" d:DataContext="{d:DesignInstance Type=items:DigitalOutItem, IsDesignTimeCreatable=False}">
+
+ <UserControl.Resources>
+ <converters:BoolToVisibilityConverter x:Key="BoolToVisibilityConverter"></converters:BoolToVisibilityConverter>
+ <sharedConverters:BooleanInverseConverter x:Key="BooleanInverseConverter" />
+
+ <!--Theme-->
+ <SolidColorBrush x:Key="BorderBrush" Color="Transparent"></SolidColorBrush>
+ <SolidColorBrush x:Key="CornersBrush" Color="Red"></SolidColorBrush>
+ </UserControl.Resources>
+
+ <UserControl.RenderTransform>
+ <RotateTransform Angle="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=Angle}"></RotateTransform>
+ </UserControl.RenderTransform>
+
+ <Grid>
+
+
+ <!--Content-->
+ <Grid IsHitTestVisible="{Binding RelativeSource={RelativeSource AncestorType=local:ElementsEditor},Path=IsEditable,Converter={StaticResource BooleanInverseConverter}}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="221*"/>
+ <RowDefinition Height="Auto"/>
+ </Grid.RowDefinitions>
+
+ <Border BorderBrush="Gray" BorderThickness="1" CornerRadius="5" Padding="5">
+ <Border.Background>
+ <ImageBrush ImageSource="../Images/black-screen.jpg" Opacity="0.1" />
+ </Border.Background>
+ <Grid>
+ <Grid.ColumnDefinitions>
+ <ColumnDefinition Width="55*"/>
+ <ColumnDefinition Width="55*"/>
+ </Grid.ColumnDefinitions>
+
+ <Viewbox Margin="5">
+ <visuals:Led Width="100" Height="100" IsChecked="{Binding EffectiveValue}" IsHitTestVisible="False" />
+ </Viewbox>
+ <visuals:AnalogSwitch Cursor="Hand" RenderTransformOrigin="0.5,0.5" Grid.Column="1" IsChecked="{Binding Value,Mode=TwoWay}">
+ <!--<visuals:AnalogSwitch.LayoutTransform>
+ <RotateTransform Angle="90" />
+ </visuals:AnalogSwitch.LayoutTransform>-->
+ </visuals:AnalogSwitch>
+ </Grid>
+ </Border>
+
+ <Border VerticalAlignment="Bottom" Grid.Row="1" Margin="0 0 0 0">
+ <TextBlock TextWrapping="Wrap" FontSize="14" Foreground="DimGray" HorizontalAlignment="Center" Text="{Binding TechIo.Description}"></TextBlock>
+ </Border>
+ </Grid>
+ <!--Content-->
+
+
+ <Border BorderThickness="1" BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=BorderBrush,TargetNullValue={StaticResource BorderBrush},FallbackValue={StaticResource BorderBrush}}" Visibility="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=(local:ElementsEditor.IsSelected),Converter={StaticResource BoolToVisibilityConverter}}">
+ <Grid>
+ <ContentPresenter Content="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=InnerContent}"></ContentPresenter>
+
+ <Thumb Opacity="0" DragDelta="MoveDrag" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb HorizontalAlignment="Left" Cursor="SizeWE" Opacity="0" DragDelta="DragLeft" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb HorizontalAlignment="Right" Cursor="SizeWE" Opacity="0" DragDelta="DragRight" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb VerticalAlignment="Top" Cursor="SizeNS" Opacity="0" DragDelta="DragTop" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+ <Thumb VerticalAlignment="Bottom" Cursor="SizeNS" Opacity="0" DragDelta="DragBottom" DragStarted="DragStarted" DragCompleted="OnDragEnded"></Thumb>
+
+ <Grid ClipToBounds="False" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0 -20 0 0" Width="10" Height="10">
+ <Ellipse Stroke="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" StrokeThickness="2"></Ellipse>
+ <Rectangle HorizontalAlignment="Center" VerticalAlignment="Stretch" Margin="0 10 0 -8" StrokeThickness="1" Stroke="Red"></Rectangle>
+ <Thumb Opacity="0" DragDelta="DragAngle" DragStarted="DragStarted" Cursor="Arrow" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="-8 -8 0 0">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="2 2 0 0"></Border>
+ <Thumb Opacity="0" DragDelta="DragTopLeft" DragStarted="DragStarted" Cursor="SizeNWSE" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 -8 -8 0">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="0 2 2 0"></Border>
+ <Thumb Opacity="0" DragDelta="DragTopRight" DragStarted="DragStarted" Cursor="SizeNESW" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0 0 -8 -8">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="0 0 2 2"></Border>
+ <Thumb Opacity="0" DragDelta="DragBottomRight" DragStarted="DragStarted" Cursor="SizeNWSE" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+
+ <Grid Width="10" Height="10" HorizontalAlignment="Left" VerticalAlignment="Bottom" Margin="-8 0 0 -8">
+ <Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=local:ElementEditor},Path=CornersBrush,TargetNullValue={StaticResource CornersBrush},FallbackValue={StaticResource CornersBrush}}" BorderThickness="2 0 0 2"></Border>
+ <Thumb Opacity="0" DragDelta="DragBottomLeft" DragStarted="DragStarted" Cursor="SizeNESW" DragCompleted="OnDragEnded"></Thumb>
+ </Grid>
+ </Grid>
+ </Border>
+ </Grid>
+</local:ElementEditor>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml.cs
new file mode 100644
index 000000000..6428ccf1d
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Editors/DigitalOutElementEditor.xaml.cs
@@ -0,0 +1,90 @@
+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 DigitalOutElementEditor : ElementEditor
+ {
+ public DigitalOutElementEditor()
+ : base()
+ {
+ InitializeComponent();
+ }
+
+ public DigitalOutElementEditor(DigitalOutItem digitalOutItem)
+ : this()
+ {
+ DigitalOutItem = digitalOutItem;
+ DataContext = DigitalOutItem;
+ }
+
+ public DigitalOutElementEditor(DigitalOutItem digitalOutItem, Rect bounds)
+ : this(digitalOutItem)
+ {
+ Left = bounds.Left;
+ Top = bounds.Top;
+ Width = bounds.Width;
+ Height = bounds.Height;
+ }
+
+ private DigitalOutItem _digitalOutItem;
+
+ public DigitalOutItem DigitalOutItem
+ {
+ get { return _digitalOutItem; }
+ set { _digitalOutItem = value; RaisePropertyChanged(nameof(DigitalOutItem)); }
+ }
+
+
+ /// <summary>
+ /// Clones this instance.
+ /// </summary>
+ /// <returns></returns>
+ public override IElementEditor Clone()
+ {
+ try
+ {
+ var clonedItem = DigitalOutItem.Clone() as DigitalOutItem;
+ DigitalOutElementEditor cloned = new DigitalOutElementEditor(clonedItem);
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Gets the hosted element.
+ /// </summary>
+ [ParameterIgnore]
+ public override Object HostedElement
+ {
+ get { return DigitalOutItem; }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/digital-in.png b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/digital-in.png
new file mode 100644
index 000000000..3b5ebac18
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/Images/digital-in.png
Binary files differ
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml
new file mode 100644
index 000000000..1121fe9e1
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml
@@ -0,0 +1,33 @@
+<UserControl x:Class="Tango.MachineStudio.Technician.PropertiesTemplates.DigitalInTemplate"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:converters="clr-namespace:Tango.MachineStudio.Technician.Converters"
+ xmlns:items="clr-namespace:Tango.MachineStudio.Technician.TechItems"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:colorPicker="clr-namespace:Tango;assembly=Tango.ColorPicker"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Technician.PropertiesTemplates"
+ mc:Ignorable="d"
+ d:DesignHeight="500" d:DesignWidth="200" d:DataContext="{d:DesignInstance Type=items:DigitalOutItem, IsDesignTimeCreatable=False}">
+
+ <UserControl.Resources>
+ <converters:TechIosToDigitalInsConverter x:Key="TechIosToDigitalInsConverter" />
+
+ <Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
+ <Setter Property="mahapps:ControlsHelper.HeaderFontSize" Value="14" />
+ <Setter Property="Margin" Value="2" />
+ </Style>
+ </UserControl.Resources>
+
+ <Grid>
+ <StackPanel>
+ <GroupBox Header="INPUT">
+ <StackPanel>
+ <TextBlock FontSize="10">Selected Pin</TextBlock>
+ <ComboBox Margin="0 5 0 0" ItemsSource="{Binding Adapter.TechIos,Converter={StaticResource TechIosToDigitalInsConverter}}" SelectedItem="{Binding TechIo,Mode=TwoWay}" DisplayMemberPath="Description" />
+ </StackPanel>
+ </GroupBox>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml.cs
new file mode 100644
index 000000000..9862a95b9
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalInTemplate.xaml.cs
@@ -0,0 +1,28 @@
+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.MachineStudio.Technician.PropertiesTemplates
+{
+ /// <summary>
+ /// Interaction logic for MonitorTemplate.xaml
+ /// </summary>
+ public partial class DigitalInTemplate : UserControl
+ {
+ public DigitalInTemplate()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml
new file mode 100644
index 000000000..dafceefcb
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml
@@ -0,0 +1,33 @@
+<UserControl x:Class="Tango.MachineStudio.Technician.PropertiesTemplates.DigitalOutTemplate"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:converters="clr-namespace:Tango.MachineStudio.Technician.Converters"
+ xmlns:items="clr-namespace:Tango.MachineStudio.Technician.TechItems"
+ xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls"
+ xmlns:colorPicker="clr-namespace:Tango;assembly=Tango.ColorPicker"
+ xmlns:local="clr-namespace:Tango.MachineStudio.Technician.PropertiesTemplates"
+ mc:Ignorable="d"
+ d:DesignHeight="500" d:DesignWidth="200" d:DataContext="{d:DesignInstance Type=items:DigitalOutItem, IsDesignTimeCreatable=False}">
+
+ <UserControl.Resources>
+ <converters:TechIosToDigitalOutsConverter x:Key="TechIosToDigitalOutsConverter" />
+
+ <Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}">
+ <Setter Property="mahapps:ControlsHelper.HeaderFontSize" Value="14" />
+ <Setter Property="Margin" Value="2" />
+ </Style>
+ </UserControl.Resources>
+
+ <Grid>
+ <StackPanel>
+ <GroupBox Header="OUTPUT">
+ <StackPanel>
+ <TextBlock FontSize="10">Selected Pin</TextBlock>
+ <ComboBox Margin="0 5 0 0" ItemsSource="{Binding Adapter.TechIos,Converter={StaticResource TechIosToDigitalOutsConverter}}" SelectedItem="{Binding TechIo,Mode=TwoWay}" DisplayMemberPath="Description" />
+ </StackPanel>
+ </GroupBox>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml.cs
new file mode 100644
index 000000000..58a3fcb8f
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/PropertiesTemplates/DigitalOutTemplate.xaml.cs
@@ -0,0 +1,28 @@
+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.MachineStudio.Technician.PropertiesTemplates
+{
+ /// <summary>
+ /// Interaction logic for MonitorTemplate.xaml
+ /// </summary>
+ public partial class DigitalOutTemplate : UserControl
+ {
+ public DigitalOutTemplate()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalInItem.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalInItem.cs
new file mode 100644
index 000000000..7f1548254
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalInItem.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using System.Xml.Serialization;
+using Tango.Integration.Observables;
+using Tango.SharedUI.Helpers;
+
+namespace Tango.MachineStudio.Technician.TechItems
+{
+ /// <summary>
+ /// Represents a digital input pin item.
+ /// </summary>
+ /// <seealso cref="Tango.MachineStudio.Technician.TechItems.TechItem" />
+ [TechItem(0)]
+ public class DigitalInItem : TechItem
+ {
+ private TechIo _techIo;
+ /// <summary>
+ /// Gets or sets the DB tech item.
+ /// </summary>
+ [XmlIgnore]
+ public TechIo TechIo
+ {
+ get { return _techIo; }
+ set { _techIo = value; RaisePropertyChangedAuto(); TechName = _techIo != null ? _techIo.Description : null; ItemGuid = value != null ? value.Guid : null; }
+ }
+
+ private bool _value;
+ /// <summary>
+ /// Gets or sets whether the input is on.
+ /// </summary>
+ [XmlIgnore]
+ public bool Value
+ {
+ get { return _value; }
+ set { _value = value; RaisePropertyChangedAuto(); }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DigitalInItem"/> class.
+ /// </summary>
+ public DigitalInItem() : base()
+ {
+ Name = "Digital In";
+ Description = "Digital Input Pin LED";
+ Image = ResourceHelper.GetImageFromResources("Images/digital-in.png");
+ Color = Colors.White;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DigitalInItem"/> class.
+ /// </summary>
+ /// <param name="techIo">The db tech.</param>
+ public DigitalInItem(TechIo techIo) : this()
+ {
+ TechIo = techIo;
+ }
+
+ /// <summary>
+ /// Clones this instance.
+ /// </summary>
+ /// <returns></returns>
+ public override TechItem Clone()
+ {
+ DigitalInItem cloned = base.Clone() as DigitalInItem;
+ cloned.TechIo = TechIo;
+ return cloned;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalOutItem.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalOutItem.cs
new file mode 100644
index 000000000..2a0625c53
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/DigitalOutItem.cs
@@ -0,0 +1,98 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+using System.Xml.Serialization;
+using Tango.Integration.Observables;
+using Tango.SharedUI.Helpers;
+
+namespace Tango.MachineStudio.Technician.TechItems
+{
+ /// <summary>
+ /// Represents a digital output pin item.
+ /// </summary>
+ /// <seealso cref="Tango.MachineStudio.Technician.TechItems.TechItem" />
+ [TechItem(1)]
+ public class DigitalOutItem : TechItem
+ {
+ /// <summary>
+ /// Occurs when the user has changed the current value.
+ /// </summary>
+ public event EventHandler<bool> ValueChanged;
+
+ private TechIo _techIo;
+ /// <summary>
+ /// Gets or sets the db tech item.
+ /// </summary>
+ [XmlIgnore]
+ public TechIo TechIo
+ {
+ get { return _techIo; }
+ set { _techIo = value; RaisePropertyChangedAuto(); TechName = _techIo != null ? _techIo.Description : null; ItemGuid = value != null ? value.Guid : null; }
+ }
+
+ private bool _value;
+ /// <summary>
+ /// Gets or sets a value indicating whether this <see cref="DigitalOutItem"/> is on.
+ /// </summary>
+ [XmlIgnore]
+ public bool Value
+ {
+ get { return _value; }
+ set { _value = value; RaisePropertyChangedAuto(); ValueChanged?.Invoke(this, value); }
+ }
+
+ private bool _effectiveValue;
+ /// <summary>
+ /// Gets or sets the effective value received from the embedded device.
+ /// </summary>
+ [XmlIgnore]
+ public bool EffectiveValue
+ {
+ get { return _effectiveValue; }
+ set
+ {
+ if (_effectiveValue != value)
+ {
+ _effectiveValue = value;
+ RaisePropertyChangedAuto();
+ _value = value;
+ RaisePropertyChanged(nameof(Value));
+ }
+ }
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DigitalOutItem"/> class.
+ /// </summary>
+ public DigitalOutItem() : base()
+ {
+ Name = "Digital Out";
+ Description = "Digital Output Pin Controller";
+ Image = ResourceHelper.GetImageFromResources("Images/binary.png");
+ Color = Colors.White;
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DigitalOutItem"/> class.
+ /// </summary>
+ /// <param name="techIo">The db tech item.</param>
+ public DigitalOutItem(TechIo techIo) : this()
+ {
+ TechIo = techIo;
+ }
+
+ /// <summary>
+ /// Clones this instance.
+ /// </summary>
+ /// <returns></returns>
+ public override TechItem Clone()
+ {
+ DigitalOutItem cloned = base.Clone() as DigitalOutItem;
+ cloned.TechIo = TechIo;
+ return cloned;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/TechItemAttribute.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/TechItemAttribute.cs
new file mode 100644
index 000000000..fafd00954
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Technician/TechItems/TechItemAttribute.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.MachineStudio.Technician.TechItems
+{
+ /// <summary>
+ /// Represents a tech item attribute
+ /// </summary>
+ /// <seealso cref="System.Attribute" />
+ public class TechItemAttribute : Attribute
+ {
+ /// <summary>
+ /// Gets or sets the item index.
+ /// </summary>
+ public int Index { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="TechItemAttribute"/> class.
+ /// </summary>
+ /// <param name="index">The index.</param>
+ public TechItemAttribute(int index)
+ {
+ Index = index;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs
new file mode 100644
index 000000000..b77619ac2
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/DefaultDiagnosticsFrameProvider.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Integration.Operators;
+using Tango.MachineStudio.Common.StudioApplication;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.MachineStudio.Common.Diagnostics
+{
+ /// <summary>
+ /// Represents the default diagnostics frame provider.
+ /// </summary>
+ /// <seealso cref="Tango.MachineStudio.Common.Diagnostics.IDiagnosticsFrameProvider" />
+ public class DefaultDiagnosticsFrameProvider : IDiagnosticsFrameProvider
+ {
+ /// <summary>
+ /// Disables the frame delivery from the current connected machine and enables the manual push frame method.
+ /// </summary>
+ public bool Disable { get; set; }
+
+ /// <summary>
+ /// Occurs when a new data frame is available.
+ /// </summary>
+ public event EventHandler<PushDiagnosticsResponse> FrameReceived;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultDiagnosticsFrameProvider"/> class.
+ /// </summary>
+ /// <param name="applicationManager">The application manager.</param>
+ public DefaultDiagnosticsFrameProvider(IStudioApplicationManager 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, Integration.Services.IExternalBridgeClient machine)
+ {
+ if (machine != null)
+ {
+ (machine as MachineOperator).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, PushDiagnosticsResponse frame)
+ {
+ if (!Disable)
+ {
+ OnFrameReceived(frame);
+ }
+ }
+
+ /// <summary>
+ /// Push frames manual. (Only when Disable = true)
+ /// </summary>
+ /// <param name="frame">The frame.</param>
+ public void PushFrame(PushDiagnosticsResponse frame)
+ {
+ if (Disable)
+ {
+ OnFrameReceived(frame);
+ }
+ }
+
+ /// <summary>
+ /// Raises the <see cref="FrameReceived"/> event.
+ /// </summary>
+ /// <param name="frame">The frame.</param>
+ protected virtual void OnFrameReceived(PushDiagnosticsResponse frame)
+ {
+ FrameReceived?.Invoke(this, frame);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/IDiagnosticsFrameProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/IDiagnosticsFrameProvider.cs
new file mode 100644
index 000000000..0d63b59b6
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Diagnostics/IDiagnosticsFrameProvider.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PMR.Diagnostics;
+
+namespace Tango.MachineStudio.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<PushDiagnosticsResponse> 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(PushDiagnosticsResponse frame);
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/BarItem.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/BarItem.cs
new file mode 100644
index 000000000..8d3cefa40
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Notifications/BarItem.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.Core;
+
+namespace Tango.MachineStudio.Common.Notifications
+{
+ public class BarItem : ExtendedObject, IDisposable
+ {
+ private INotificationProvider _notificationProvider;
+
+ public FrameworkElement Element { get; set; }
+
+ public BarItem(INotificationProvider notificationProvider)
+ {
+ _notificationProvider = notificationProvider;
+ }
+
+ /// <summary>
+ /// Removed this item from the queue.
+ /// </summary>
+ public void Pop()
+ {
+ _notificationProvider.PopBarItem(this);
+ }
+
+ /// <summary>
+ /// Pushes this item to the queue.
+ /// </summary>
+ public void Push()
+ {
+ _notificationProvider.PushBarItem(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/MachineStudio/Tango.MachineStudio.Common/StudioModuleBase.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioModuleBase.cs
new file mode 100644
index 000000000..5c594ab70
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/StudioModuleBase.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media.Imaging;
+using Tango.Integration.Observables;
+
+namespace Tango.MachineStudio.Common
+{
+ /// <summary>
+ /// Represents a base class for studio modules.
+ /// </summary>
+ /// <seealso cref="Tango.MachineStudio.Common.IStudioModule" />
+ public abstract class StudioModuleBase : IStudioModule
+ {
+ private bool _isInitialized;
+ private bool _isLoaded;
+
+ /// <summary>
+ /// Occurs when the user has navigated into or out of this module.
+ /// </summary>
+ public event EventHandler<bool> IsLoadedChanged;
+
+ /// <summary>
+ /// Gets the module name.
+ /// </summary>
+ public abstract string Name { get; }
+
+ /// <summary>
+ /// Gets the module description.
+ /// </summary>
+ public abstract string Description { get; }
+
+ /// <summary>
+ /// Gets the module cover image.
+ /// </summary>
+ public abstract BitmapSource Image { get; }
+
+ /// <summary>
+ /// Gets the module entry point view.
+ /// </summary>
+ public abstract FrameworkElement MainView { get; }
+
+ /// <summary>
+ /// Gets the permission required to see and load this module.
+ /// </summary>
+ public abstract Permissions Permission { get; }
+
+ /// <summary>
+ /// Gets a value indicating whether this module has been initialized.
+ /// </summary>
+ public bool IsInitialized
+ {
+ get
+ {
+ return _isInitialized;
+ }
+ private set
+ {
+ _isInitialized = value;
+ }
+ }
+
+ /// <summary>
+ /// Sets a value indicating whether this module is loaded.
+ /// </summary>
+ public bool IsLoaded
+ {
+ get
+ {
+ return _isLoaded;
+ }
+ set
+ {
+ _isLoaded = value;
+ IsLoadedChanged?.Invoke(this, value);
+ }
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public abstract void Dispose();
+
+ /// <summary>
+ /// Perform any operations required to initialize this module.
+ /// </summary>
+ public void Initialize()
+ {
+ OnInitialized();
+ IsInitialized = true;
+ }
+
+ /// <summary>
+ /// Called when machine studio initializes this module.
+ /// </summary>
+ protected virtual void OnInitialized()
+ {
+
+ }
+
+ /// <summary>
+ /// Raises the <see cref="IsLoadedChanged"/> event.
+ /// </summary>
+ /// <param name="loaded">if set to <c>true</c> the module is loaded.</param>
+ protected virtual void OnLoadedChanged(bool loaded)
+ {
+
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/DefaultVideoCaptureProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/DefaultVideoCaptureProvider.cs
new file mode 100644
index 000000000..3aa9d4c88
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/DefaultVideoCaptureProvider.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Video.DirectCapture;
+
+namespace Tango.MachineStudio.Common.Video
+{
+ /// <summary>
+ /// Represents the default implementation of <see cref="IVideoCaptureProvider"/>.
+ /// </summary>
+ /// <seealso cref="Tango.MachineStudio.Common.Video.IVideoCaptureProvider" />
+ public class DefaultVideoCaptureProvider : IVideoCaptureProvider
+ {
+ /// <summary>
+ /// Gets the available capture devices.
+ /// </summary>
+ public ObservableCollection<CaptureDevice> AvailableCaptureDevices { get; private set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="DefaultVideoCaptureProvider"/> class.
+ /// </summary>
+ public DefaultVideoCaptureProvider()
+ {
+ AvailableCaptureDevices = new ObservableCollection<CaptureDevice>();
+
+ var availableDevices = CaptureDevice.GetAvailableCaptureDevices();
+
+ for (int i = 0; i < 3; i++)
+ {
+ if (i > availableDevices.Count - 1)
+ {
+ AvailableCaptureDevices.Add(new CaptureDevice() { Device = null });
+ }
+ else
+ {
+ AvailableCaptureDevices.Add(new CaptureDevice() { Device = availableDevices[i] });
+ }
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/IVideoCaptureProvider.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/IVideoCaptureProvider.cs
new file mode 100644
index 000000000..cd797dce2
--- /dev/null
+++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/Video/IVideoCaptureProvider.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Video.DirectCapture;
+
+namespace Tango.MachineStudio.Common.Video
+{
+ /// <summary>
+ /// Represents a video capturing device provider.
+ /// </summary>
+ public interface IVideoCaptureProvider
+ {
+ /// <summary>
+ /// Gets the available capture devices.
+ /// </summary>
+ ObservableCollection<CaptureDevice> AvailableCaptureDevices { get; }
+ }
+}