diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-07-03 16:36:54 +0300 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-07-03 16:36:54 +0300 |
| commit | 856773f7eafb9d04500ede0cfae9c0e75231418b (patch) | |
| tree | d1b4f9577b5a47dd10fa7243823fd1016de1418e /Software/Visual_Studio/Tango.Stubs | |
| parent | 94e4072838c235be4d48a4635e47204a39cdd78b (diff) | |
| download | Tango-856773f7eafb9d04500ede0cfae9c0e75231418b.tar.gz Tango-856773f7eafb9d04500ede0cfae9c0e75231418b.zip | |
Implemented StubsView & VM !!!
Diffstat (limited to 'Software/Visual_Studio/Tango.Stubs')
37 files changed, 2724 insertions, 339 deletions
diff --git a/Software/Visual_Studio/Tango.Stubs/AvailableStub.cs b/Software/Visual_Studio/Tango.Stubs/AvailableStub.cs deleted file mode 100644 index 64fbfbe9b..000000000 --- a/Software/Visual_Studio/Tango.Stubs/AvailableStub.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Transport; - -namespace Tango.Stubs -{ - public class AvailableStub - { - public Type Type { get; set; } - - public String Name { get; set; } - - public String Description { get; set; } - - public AvailableStub(Type type, String name, String description) - { - Type = type; - Name = name; - Description = description; - } - - public StubBase CreateInstance(ITransporter transporter) - { - return Activator.CreateInstance(Type, transporter) as StubBase; - } - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/StubDirection.cs b/Software/Visual_Studio/Tango.Stubs/ConnectionMode.cs index 121818865..bd62ab54d 100644 --- a/Software/Visual_Studio/Tango.Stubs/StubDirection.cs +++ b/Software/Visual_Studio/Tango.Stubs/ConnectionMode.cs @@ -6,10 +6,9 @@ using System.Threading.Tasks; namespace Tango.Stubs { - public enum StubDirection + public enum ConnectionMode { - ToMachine, - ToMobile, - Both = ToMachine | ToMobile, + Internal, + External } } diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/BasicRequest.cs b/Software/Visual_Studio/Tango.Stubs/Examples/BasicRequest.cs new file mode 100644 index 000000000..69b06330b --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/BasicRequest.cs @@ -0,0 +1,35 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + + // Request ---- + // Double : A + // Double : B + + // Response ---- + // Double : Sum + var response = stubManager.Run<CalculateResponse>("CalculateRequest", 10, 5); + + if (response.Sum == 15) + { + + stubManager.WriteLine("Sum is " + response.Sum); + + } + else + { + stubManager.WriteLine("Sum is incorrect!"); + } + +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/BasicRequestPolling.cs b/Software/Visual_Studio/Tango.Stubs/Examples/BasicRequestPolling.cs new file mode 100644 index 000000000..50c805d6a --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/BasicRequestPolling.cs @@ -0,0 +1,28 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + int sum = 0; + int a = 0; + + while (sum < 100) + { + a = a + 1; + var response = stubManager.Run<CalculateResponse>("CalculateRequest", 0, a); + sum = response.Sum; + stubManager.WriteLine(sum); + } + + stubManager.WriteLine("Polling completed!"); + +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/ContinuousResponse.cs b/Software/Visual_Studio/Tango.Stubs/Examples/ContinuousResponse.cs new file mode 100644 index 000000000..9e173052b --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/ContinuousResponse.cs @@ -0,0 +1,25 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + + + // Request ---- + // Int32 : Amount + // Int32 : Delay + + // Response ---- + // Double : Progress + stubManager.RunContinuous<ProgressResponse>("ProgressRequest", null, 100, 1); //Put null in the callback and let our application log the response automatically.. + +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/ContinuousResponseAdvanced.cs b/Software/Visual_Studio/Tango.Stubs/Examples/ContinuousResponseAdvanced.cs new file mode 100644 index 000000000..781ed2d60 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/ContinuousResponseAdvanced.cs @@ -0,0 +1,35 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + + // Request ---- + // Int32 : Amount + // Int32 : Delay + + // Response ---- + // Double : Progress + + + ProgressRequest request = new ProgressRequest(); + request.Amount = 100; + request.Delay = 1; + + stubManager.RunContinuous<ProgressResponse>(request, (response) => + { + + stubManager.WriteLine(response.Progress); + + }); + +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/InvokeResponseWindow.cs b/Software/Visual_Studio/Tango.Stubs/Examples/InvokeResponseWindow.cs new file mode 100644 index 000000000..8dce2b327 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/InvokeResponseWindow.cs @@ -0,0 +1,28 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + String response = null; + + //Invoke the response window with default parameters. + response = stubManager.ShowResponseWindow(); + stubManager.WriteLine(response); + + //Invoke the response window with custom message. + response = stubManager.ShowResponseWindow("Please enter response:"); + stubManager.WriteLine(response); + + //Invoke the response window with custom message and default response. + response = stubManager.ShowResponseWindow("Please enter response:", "Default response"); + stubManager.WriteLine(response); +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/ManualRequestInitialization.cs b/Software/Visual_Studio/Tango.Stubs/Examples/ManualRequestInitialization.cs new file mode 100644 index 000000000..da9110838 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/ManualRequestInitialization.cs @@ -0,0 +1,26 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + + + CalculateRequest calculateRequest = new CalculateRequest(); + calculateRequest.A = 10; + calculateRequest.B = 15; + + var response = stubManager.Run<CalculateResponse>(calculateRequest); + + stubManager.WriteLine("The response sum is: " + response.Sum); + + +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/RequestTimeout.cs b/Software/Visual_Studio/Tango.Stubs/Examples/RequestTimeout.cs new file mode 100644 index 000000000..edfbfa15c --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/RequestTimeout.cs @@ -0,0 +1,19 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + + stubManager.RequestTimeout = 5000; //Set request timeout to 5 seconds. + + var response = stubManager.Run<CalculateResponse>("CalculateRequest", 10, 5); +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/Sleep.cs b/Software/Visual_Studio/Tango.Stubs/Examples/Sleep.cs new file mode 100644 index 000000000..62257ed5f --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/Sleep.cs @@ -0,0 +1,30 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + int sum = 0; + int a = 0; + + while (sum < 100) + { + a = a + 1; + var response = stubManager.Run<CalculateResponse>("CalculateRequest", 0, a); + sum = response.Sum; + stubManager.WriteLine(sum); + + Thread.Sleep(10); //Sleep for 10 milli. + } + + stubManager.WriteLine("Polling completed!"); + +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Examples/WriteToFile.cs b/Software/Visual_Studio/Tango.Stubs/Examples/WriteToFile.cs new file mode 100644 index 000000000..73d8dde6f --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Examples/WriteToFile.cs @@ -0,0 +1,29 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +private const string FILE_PATH = "D:\\logFile.txt"; + +public void OnExecute(StubManager stubManager) +{ + //This will overwrite existing file. + stubManager.WriteToFile(FILE_PATH, "Writing to file..."); + + for (int i = 0; i < 10; i++) + { + //This will append the contents to the end of the file. + stubManager.AppendToFile(FILE_PATH, i.ToString() + " Some text..."); + } + + stubManager.AppendToFile(FILE_PATH, "Done"); + + stubManager.WriteLine("Done writing to the file."); +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/IStub.cs b/Software/Visual_Studio/Tango.Stubs/IStub.cs deleted file mode 100644 index 70629ea8f..000000000 --- a/Software/Visual_Studio/Tango.Stubs/IStub.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Core; - -namespace Tango.Stubs -{ - public interface IStub : IParameterized - { - StubState State { get; } - Task<String> Run(Action<String> multiResponseCallback); - Task<String> Cancel(); - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/Properties/Resources.Designer.cs b/Software/Visual_Studio/Tango.Stubs/Properties/Resources.Designer.cs new file mode 100644 index 000000000..7d3a76e9a --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Properties/Resources.Designer.cs @@ -0,0 +1,92 @@ +//------------------------------------------------------------------------------ +// <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.Stubs.Properties { + using System; + + + /// <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 (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Tango.Stubs.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; + } + } + + /// <summary> + /// Looks up a localized string similar to using System; + ///using System.Text; + ///using System.Linq; + ///using System.Drawing; + ///using System.Diagnostics; + ///using System.Windows.Forms; + ///using System.Threading; + ///using System.Threading.Tasks; + ///using System.Collections.Generic; + ///using Tango.PMR.Stubs; + ///using Tango.Stubs; + /// + ///public void OnExecute(StubManager stubManager) + ///{ + /// for (int i = 0; i < 10; i++) + /// { + /// var response = stubManager.Run<CalculateResponse>("calculate", 1, i); + /// + /// if (response.Sum == 10) + /// { + /// stubManag [rest of string was truncated]";. + /// </summary> + internal static string CodeTabTemplate { + get { + return ResourceManager.GetString("CodeTabTemplate", resourceCulture); + } + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/Properties/Resources.resx b/Software/Visual_Studio/Tango.Stubs/Properties/Resources.resx new file mode 100644 index 000000000..7693cadac --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Properties/Resources.resx @@ -0,0 +1,124 @@ +<?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.Runtime.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:import namespace="http://www.w3.org/XML/1998/namespace" /> + <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" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </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" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" /> + <data name="CodeTabTemplate" type="System.Resources.ResXFileRef, System.Windows.Forms"> + <value>..\Resources\CodeTabTemplate.cs;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;Windows-1252</value> + </data> +</root>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/Resources/CodeTabTemplate.cs b/Software/Visual_Studio/Tango.Stubs/Resources/CodeTabTemplate.cs new file mode 100644 index 000000000..c9b619677 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Resources/CodeTabTemplate.cs @@ -0,0 +1,28 @@ +using System; +using System.Text; +using System.Linq; +using System.Drawing; +using System.Diagnostics; +using System.Windows.Forms; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using Tango.PMR.Stubs; +using Tango.Stubs; + +public void OnExecute(StubManager stubManager) +{ + for (int i = 0; i < 10; i++) + { + var response = stubManager.Run<CalculateResponse>("calculate", 1, i); + + if (response.Sum == 10) + { + stubManager.WriteLine("OK!"); + } + else + { + stubManager.WriteLine(response.Sum); + } + } +}
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/StubAttribute.cs b/Software/Visual_Studio/Tango.Stubs/StubAttribute.cs deleted file mode 100644 index c7611e606..000000000 --- a/Software/Visual_Studio/Tango.Stubs/StubAttribute.cs +++ /dev/null @@ -1,24 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.Stubs -{ - public class StubAttribute : Attribute - { - public String Name { get; set; } - - public String Description { get; set; } - - public StubDirection Direction { get; set; } - - public StubAttribute(String name, String description, StubDirection direction) - { - Name = name; - Description = description; - Direction = direction; - } - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/StubBase.cs b/Software/Visual_Studio/Tango.Stubs/StubBase.cs deleted file mode 100644 index 61a2f63c5..000000000 --- a/Software/Visual_Studio/Tango.Stubs/StubBase.cs +++ /dev/null @@ -1,96 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.Linq; -using System.Reflection; -using System.Text; -using System.Threading.Tasks; -using Tango.Core; -using Tango.Logging; -using Tango.PMR; -using Tango.Transport; - -namespace Tango.Stubs -{ - public abstract class StubBase : ExtendedObject, IStub - { - [ParameterIgnore] - public ITransporter Transporter { get; set; } - - [ParameterIgnore] - public ReadOnlyObservableCollection<ParameterItem> Parameters { get; set; } - - private StubState _state; - [ParameterIgnore] - public StubState State - { - get { return _state; } - protected set { _state = value; RaisePropertyChanged(nameof(State)); } - } - - public StubBase(ITransporter transporter) - { - Transporter = transporter; - Parameters = new ReadOnlyObservableCollection<ParameterItem>(this.CreateParametersCollection(ParameterItemMode.Event)); - } - - public virtual Task<String> Cancel() - { - return Task<String>.Factory.StartNew(() => - { - return ""; - }); - } - - public async virtual Task<String> Run(Action<String> multiResponseCallback) - { - String response = String.Empty; - - try - { - LogManager.Log("Executing stub " + this.GetType().Name + "..."); - State = StubState.Running; - response = await OnRun(multiResponseCallback); - State = StubState.Passed; - LogManager.Log("Stub completed successfully."); - } - catch (Exception ex) - { - State = StubState.Failed; - response = LogManager.Log(ex, "Stub failed.").ToString(); - } - - return response; - } - - protected abstract Task<String> OnRun(Action<String> multiResponseCallback); - - public static List<AvailableStub> GetAvailableStubs(StubDirection direction) - { - List<AvailableStub> results = new List<AvailableStub>(); - - foreach (Type type in Assembly.GetAssembly(typeof(StubBase)).GetTypes().Where(myType => myType.IsClass && !myType.IsAbstract && myType.IsSubclassOf(typeof(StubBase)))) - { - StubAttribute att = type.GetCustomAttributes(typeof(StubAttribute), true).FirstOrDefault() as StubAttribute; - - if (att.Direction.HasFlag(direction)) - { - AvailableStub availableStub = new AvailableStub(type, att.Name, att.Description); - results.Add(availableStub); - } - } - - return results; - } - - public static List<Type> GetAvailableRequestStubs() - { - return typeof(MessageFactory).Assembly.GetTypes().Where(x => x.Namespace != null && x.Namespace.Contains("Stubs") && x.Name.Contains("Request") && !x.Name.Contains("Reflection")).ToList(); - } - - public static List<Type> GetAvailableRequestResponseStubs() - { - return typeof(MessageFactory).Assembly.GetTypes().Where(x => x.Namespace != null && x.Namespace.Contains("Stubs") && !x.Name.Contains("Reflection")).ToList(); - } - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/StubManager.cs b/Software/Visual_Studio/Tango.Stubs/StubManager.cs new file mode 100644 index 000000000..d8058ee07 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/StubManager.cs @@ -0,0 +1,406 @@ +using Google.Protobuf; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using Tango.Integration.Operation; +using Tango.PMR; +using Tango.PMR.Common; +using Tango.Stubs.Windows; +using Tango.Transport.Adapters; + +namespace Tango.Stubs +{ + /// <summary> + /// Represents a manager capable of executing stub scripts asynchronously. + /// </summary> + public class StubManager + { + private IMachineOperator _machineOperator; + private Action<String> _writeLine; + private Action<String> _write; + private Action _clear; + + /// <summary> + /// Occurs when the stub has failed to execute. + /// </summary> + public event EventHandler<Exception> Failed; + + /// <summary> + /// Occurs when the stub has completed successfully. + /// </summary> + public event EventHandler<String> Completed; + + /// <summary> + /// Occurs when the stub has been initialized and executed. + /// </summary> + public event EventHandler<String> Executed; + + /// <summary> + /// Gets a value indicating whether this <see cref="StubManager"/> is aborted. + /// </summary> + internal bool Aborted { get; private set; } + + /// <summary> + /// Gets or sets a value indicating whether [automatic log]. + /// </summary> + public bool AutoLog { get; set; } + + /// <summary> + /// Gets or sets the request timeout. + /// </summary> + public int RequestTimeout { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="StubManager"/> class. + /// </summary> + /// <param name="adapter">The adapter.</param> + public StubManager(IMachineOperator machineOperator, Action<String> writeLine, Action<String> write, Action clear) + { + _writeLine = writeLine; + _write = write; + _clear = clear; + + _machineOperator = machineOperator; + RequestTimeout = 2; + } + + /// <summary> + /// Aborts the current script. + /// </summary> + internal void Abort() + { + Aborted = true; + } + + /// <summary> + /// Runs the specified stub name. + /// </summary> + /// <param name="stubName">Name of the stub.</param> + /// <param name="args">The arguments.</param> + public IMessage Run(String stubName, params Object[] args) + { + if (Aborted) return null; + + var stubType = MessageFactory.GetAvailableRequestStubs().SingleOrDefault(x => x.Name.ToLower() == stubName.ToLower() || x.Name.Replace("Request", "").ToLower() == stubName.ToLower()); + if (stubType == null) + { + OnFailed(new ArgumentException("Invalid stub '" + stubName + "'.")); + return null; + } + + var stubProps = stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance); + + if (stubProps.Length > args.Length) + { + OnFailed(new ArgumentOutOfRangeException("Not enough arguments for " + stubType.Name + ".")); + return null; + } + + Executed?.Invoke(this, stubType.Name); + + try + { + Object request = Activator.CreateInstance(stubType); + + int argIndex = 0; + foreach (var prop in stubProps) + { + Object arg = args[argIndex++]; + + if (prop.PropertyType == typeof(UInt32)) + { + prop.SetValue(request, UInt32.Parse(arg.ToString())); + } + else if (prop.PropertyType == typeof(bool)) + { + prop.SetValue(request, bool.Parse(arg.ToString())); + } + else if (prop.PropertyType.IsPrimitive) + { + object converted = Convert.ChangeType(arg, prop.PropertyType); + prop.SetValue(request, converted); + } + else + { + prop.SetValue(request, arg); + } + } + + return Run(request as IMessage); + } + catch (Exception ex) + { + OnFailed(ex); + } + + return null; + } + + /// <summary> + /// Runs the specified stub name. + /// </summary> + /// <param name="stubName">Name of the stub.</param> + /// <param name="args">The arguments.</param> + public IMessage Run(IMessage stub) + { + if (Aborted) return null; + + Executed?.Invoke(this, stub.GetType().Name); + + try + { + try + { + IMessage response = null; + bool done = false; + + Task.Factory.StartNew(() => + { + try + { + response = _machineOperator.SendRequest(stub, TimeSpan.FromSeconds(RequestTimeout)).Result; + OnCompleted(JsonConvert.SerializeObject(response, Formatting.Indented)); + done = true; + } + catch (Exception ex) + { + done = true; + OnFailed(ex); + } + }); + + while (!done) + { + Thread.Sleep(2); + } + + return response; + } + catch (Exception ex) + { + OnFailed(ex); + return null; + } + } + catch (Exception ex) + { + OnFailed(ex); + return null; + } + } + + public T Run<T>(String stubName, params Object[] args) where T : class, IMessage + { + return Run(stubName, args) as T; + } + + public T Run<T>(IMessage stub) where T : class, IMessage + { + return Run(stub) as T; + } + + /// <summary> + /// Runs the specified stub name. + /// </summary> + /// <param name="stubName">Name of the stub.</param> + /// <param name="args">The arguments.</param> + public void RunContinuous<T>(IMessage stub, Action<T> callback) where T : class, IMessage + { + if (Aborted) return; + + try + { + Type stubType = stub.GetType(); + + Executed?.Invoke(this, stubType.Name); + + try + { + _machineOperator.SendContinuousRequest(stub, TimeSpan.FromSeconds(RequestTimeout)).Subscribe((msg) => + { + callback?.Invoke(msg as T); + + if (AutoLog) + { + WriteLine(JsonConvert.SerializeObject(msg, Formatting.Indented)); + } + + //Next + }, (ex) => + { + OnFailed(ex); + //Error + }, () => + { + OnCompleted("Continuous request completed."); + //Completed + }); + + } + catch (Exception ex) + { + OnFailed(ex); + } + } + catch (Exception ex) + { + OnFailed(ex); + } + } + + /// + /// <summary> + /// Runs the specified stub name. + /// </summary> + /// <param name="stubName">Name of the stub.</param> + /// <param name="args">The arguments.</param> + public void RunContinuous<T>(String stubName, Action<T> callback, params Object[] args) where T : class, IMessage + { + if (Aborted) return; + + var stubType = MessageFactory.GetAvailableRequestStubs().SingleOrDefault(x => x.Name.ToLower() == stubName.ToLower() || x.Name.Replace("Request", "").ToLower() == stubName.ToLower()); + if (stubType == null) + { + OnFailed(new ArgumentException("Invalid stub '" + stubName + "'.")); + return; + } + + var stubProps = stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance); + + if (stubProps.Length > args.Length) + { + OnFailed(new ArgumentOutOfRangeException("Not enough arguments for " + stubType.Name + ".")); + return; + } + + try + { + Object request = Activator.CreateInstance(stubType); + + int argIndex = 0; + foreach (var prop in stubProps) + { + Object arg = args[argIndex++]; + + if (prop.PropertyType == typeof(UInt32)) + { + prop.SetValue(request, UInt32.Parse(arg.ToString())); + } + else if (prop.PropertyType == typeof(bool)) + { + prop.SetValue(request, bool.Parse(arg.ToString())); + } + else if (prop.PropertyType.IsPrimitive) + { + object converted = Convert.ChangeType(arg, prop.PropertyType); + prop.SetValue(request, converted); + } + else + { + prop.SetValue(request, arg); + } + } + + RunContinuous<T>(request as IMessage, callback); + } + catch (Exception ex) + { + OnFailed(ex); + } + } + + public void WriteLine(Object obj) + { + _writeLine(obj != null ? obj.ToString() : "null"); + } + + public void Write(Object obj) + { + _write(obj != null ? obj.ToString() : "null"); + } + + public void WriteLineHex(Object number, int digits) + { + _writeLine("#" + Convert.ToInt32(number).ToString("X" + digits.ToString())); + } + + public void WriteHex(Object number, int digits) + { + _write("#" + Convert.ToInt32(number).ToString("X" + digits.ToString())); + } + + public void Clear() + { + _clear(); + } + + public String ShowResponseWindow(String message, String defaultResponse) + { + String response = null; + bool closed = false; + + Application.Current.Dispatcher.Invoke(() => + { + TextInputWindow dlg = new TextInputWindow(message, defaultResponse); + dlg.WindowStartupLocation = WindowStartupLocation.CenterOwner; + dlg.Owner = Application.Current.MainWindow; + dlg.ShowDialog(); + response = dlg.Response; + closed = true; + }); + + while (!closed) + { + Thread.Sleep(10); + } + + return response; + } + + public String ShowResponseWindow(String message) + { + return ShowResponseWindow(message, null); + } + + public String ShowResponseWindow() + { + return ShowResponseWindow(null); + } + + public void WriteToFile(String filePath, String content) + { + File.WriteAllText(filePath, content + Environment.NewLine); + } + + public void AppendToFile(String filePath, String content) + { + File.AppendAllText(filePath, content + Environment.NewLine); + } + + /// <summary> + /// Raises the <see cref="Failed"/> event. + /// </summary> + /// <param name="ex">The exception.</param> + protected virtual void OnFailed(Exception ex) + { + Failed?.Invoke(this, ex); + } + + /// <summary> + /// Raises the <see cref="Completed"/> event. + /// </summary> + /// <param name="response">The response.</param> + protected virtual void OnCompleted(String response) + { + Completed?.Invoke(this, response); + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/StubOnExecuteParameters.cs b/Software/Visual_Studio/Tango.Stubs/StubOnExecuteParameters.cs new file mode 100644 index 000000000..5c734d2bb --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/StubOnExecuteParameters.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Scripting; + +namespace Tango.Stubs +{ + /// <summary> + /// Represents the global object which will be sent to the scripting engine. + /// </summary> + /// <seealso cref="Tango.Scripting.OnExecuteParameters" /> + public class StubOnExecuteParameters : OnExecuteParameters + { + /// <summary> + /// Provides access to the script stub manager. + /// </summary> + public StubManager stubManager; + + /// <summary> + /// Initializes a new instance of the <see cref="StubOnExecuteParameters"/> class. + /// </summary> + /// <param name="manager">The manager.</param> + public StubOnExecuteParameters(StubManager manager) + { + stubManager = manager; + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/StubState.cs b/Software/Visual_Studio/Tango.Stubs/StubState.cs deleted file mode 100644 index 1839bc3dc..000000000 --- a/Software/Visual_Studio/Tango.Stubs/StubState.cs +++ /dev/null @@ -1,17 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Tango.Stubs -{ - public enum StubState - { - Stopped, - Running, - Passed, - Failed, - Canceled, - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/Stubs/BigData.cs b/Software/Visual_Studio/Tango.Stubs/Stubs/BigData.cs deleted file mode 100644 index a0d84558b..000000000 --- a/Software/Visual_Studio/Tango.Stubs/Stubs/BigData.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Core; -using Tango.Logging; -using Tango.PMR; -using Tango.PMR.Integration; -using Tango.PMR.Stubs; -using Tango.Transport; - -namespace Tango.Stubs.Stubs -{ - [Stub("Big Data", "Sends a lot of bytes.", StubDirection.Both)] - public class BigData : StubBase - { - public BigData(ITransporter transporter) : base(transporter) - { - } - - [ParameterItem(Minimum = null, Maximum = null)] - public double NumberA { get; set; } - - [ParameterItem(Minimum = null, Maximum = null)] - public double NumberB { get; set; } - - protected async override Task<string> OnRun(Action<String> multiResponseCallback) - { - try - { - var response = await Transporter.SendRequest<DirectSynchronizationRequest, DirectSynchronizationResponse>( - new DirectSynchronizationRequest() - { - - } - ); - - return response.Message.LocalDB.Length.ToString(); - } - catch (Exception ex) - { - return ex.Message; - } - } - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/Stubs/Calculate.cs b/Software/Visual_Studio/Tango.Stubs/Stubs/Calculate.cs deleted file mode 100644 index b0cfc6e08..000000000 --- a/Software/Visual_Studio/Tango.Stubs/Stubs/Calculate.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Core; -using Tango.Logging; -using Tango.PMR; -using Tango.PMR.Stubs; -using Tango.Transport; - -namespace Tango.Stubs.Stubs -{ - [Stub("Calculate", "Calculate two numbers and return the result.", StubDirection.Both)] - public class Calculate : StubBase - { - public Calculate(ITransporter transporter) : base(transporter) - { - } - - [ParameterItem(Minimum = null, Maximum = null)] - public double NumberA { get; set; } - - [ParameterItem(Minimum = null, Maximum = null)] - public double NumberB { get; set; } - - protected async override Task<string> OnRun(Action<String> multiResponseCallback) - { - try - { - var response = await Transporter.SendRequest<CalculateRequest, CalculateResponse>( - new CalculateRequest() - { - A = NumberA, - B = NumberB - } - ); - - return response.Message.Sum.ToString(); - } - catch (Exception ex) - { - return ex.Message; - } - } - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/Stubs/Progress.cs b/Software/Visual_Studio/Tango.Stubs/Stubs/Progress.cs deleted file mode 100644 index 9ce96e633..000000000 --- a/Software/Visual_Studio/Tango.Stubs/Stubs/Progress.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Tango.Core; -using Tango.Logging; -using Tango.PMR; -using Tango.PMR.Stubs; -using Tango.Transport; - -namespace Tango.Stubs.Stubs -{ - [Stub("Progress", "Check for multiple response request", StubDirection.ToMachine)] - public class Progress : StubBase - { - public Progress(ITransporter transporter) : base(transporter) - { - Amount = 100; - Delay = 4; - } - - [ParameterItem(Minimum = null, Maximum = null, Default = 100.0)] - public double Amount { get; set; } - - [ParameterItem(Minimum = null, Maximum = null, Default = 4.0)] - public double Delay { get; set; } - - protected override Task<string> OnRun(Action<String> multiResponseCallback) - { - Transporter.SendContinuousRequest<ProgressRequest, ProgressResponse>(MessageFactory.CreateTangoMessage<ProgressRequest>(new ProgressRequest() - { - Amount = (int)Amount, - Delay = (int)Delay, - })).Subscribe((x) => - { - multiResponseCallback(x.Message.Progress.ToString()); - }, (ex) => - { - multiResponseCallback(ex.Message); - }, () => - { - multiResponseCallback("Completed!"); - }); - - return Task.FromResult<String>(""); - } - } -} diff --git a/Software/Visual_Studio/Tango.Stubs/StubsSettings.cs b/Software/Visual_Studio/Tango.Stubs/StubsSettings.cs new file mode 100644 index 000000000..da3a41473 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/StubsSettings.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Settings; +using Tango.Transport.Adapters; + +namespace Tango.Stubs +{ + public class StubsSettings : SettingsBase + { + /// <summary> + /// Gets or sets the selected port. + /// </summary> + public String SelectedPort { get; set; } + + /// <summary> + /// Gets or sets the baud rate. + /// </summary> + public UsbSerialBaudRates BaudRate { get; set; } + + /// <summary> + /// Gets or sets the last tabs. + /// </summary> + public List<String> LastTabs { get; set; } + + /// <summary> + /// Gets or sets a value indicating whether [automatic log response]. + /// </summary> + public bool AutoLogResponse { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="StubsUI"/> class. + /// </summary> + public StubsSettings() + { + BaudRate = UsbSerialBaudRates.BR_9600; + LastTabs = new List<string>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj b/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj index 00895f19b..5333cbaca 100644 --- a/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj +++ b/Software/Visual_Studio/Tango.Stubs/Tango.Stubs.csproj @@ -31,9 +31,20 @@ <WarningLevel>4</WarningLevel> </PropertyGroup> <ItemGroup> + <Reference Include="FontAwesome.WPF, Version=4.7.0.37774, Culture=neutral, PublicKeyToken=0758b07a11a4f466, processorArchitecture=MSIL"> + <HintPath>..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath> + </Reference> <Reference Include="Google.Protobuf, Version=3.4.1.0, Culture=neutral, PublicKeyToken=a7d26565bac4d604, processorArchitecture=MSIL"> <HintPath>..\packages\Google.Protobuf.3.4.1\lib\net45\Google.Protobuf.dll</HintPath> </Reference> + <Reference Include="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="Newtonsoft.Json, Version=8.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> + <HintPath>..\packages\Newtonsoft.Json.8.0.3\lib\net45\Newtonsoft.Json.dll</HintPath> + </Reference> + <Reference Include="PresentationCore" /> + <Reference Include="PresentationFramework" /> <Reference Include="System" /> <Reference Include="System.Core" /> <Reference Include="System.Reactive.Core, Version=3.0.3000.0, Culture=neutral, PublicKeyToken=94bc3704cddfc263, processorArchitecture=MSIL"> @@ -52,6 +63,10 @@ <HintPath>..\packages\System.Reactive.Windows.Threading.3.1.1\lib\net45\System.Reactive.Windows.Threading.dll</HintPath> </Reference> <Reference Include="System.Windows" /> + <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.Xaml" /> <Reference Include="System.Xml.Linq" /> <Reference Include="System.Data.DataSetExtensions" /> <Reference Include="Microsoft.CSharp" /> @@ -64,16 +79,42 @@ <Compile Include="..\Versioning\Core.cs"> <Link>Core.cs</Link> </Compile> - <Compile Include="AvailableStub.cs" /> - <Compile Include="IStub.cs" /> + <EmbeddedResource Include="Examples\BasicRequest.cs" /> + <EmbeddedResource Include="Examples\BasicRequestPolling.cs" /> + <EmbeddedResource Include="Examples\ContinuousResponse.cs" /> + <EmbeddedResource Include="Examples\ContinuousResponseAdvanced.cs" /> + <EmbeddedResource Include="Examples\InvokeResponseWindow.cs" /> + <EmbeddedResource Include="Examples\ManualRequestInitialization.cs" /> + <EmbeddedResource Include="Examples\RequestTimeout.cs" /> + <EmbeddedResource Include="Examples\Sleep.cs" /> + <EmbeddedResource Include="Examples\WriteToFile.cs" /> + <Compile Include="ConnectionMode.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> - <Compile Include="StubDirection.cs" /> - <Compile Include="Stubs\BigData.cs" /> - <Compile Include="Stubs\Progress.cs" /> - <Compile Include="Stubs\Calculate.cs" /> - <Compile Include="StubAttribute.cs" /> - <Compile Include="StubBase.cs" /> - <Compile Include="StubState.cs" /> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <None Include="Resources\CodeTabTemplate.cs" /> + <Compile Include="ViewModels\CodeTabVM.cs" /> + <Compile Include="ViewModels\CreateGroupVM.cs" /> + <Compile Include="ViewModels\CreateItemVM.cs" /> + <Compile Include="ViewModels\ExampleVM.cs" /> + <Compile Include="ViewModels\StubsViewVM.cs" /> + <Compile Include="ViewModels\StubSnippetVM.cs" /> + <Compile Include="Views\StubsView.xaml.cs"> + <DependentUpon>StubsView.xaml</DependentUpon> + </Compile> + <Compile Include="Windows\TextInputWindow.xaml.cs"> + <DependentUpon>TextInputWindow.xaml</DependentUpon> + </Compile> + <Compile Include="StubManager.cs" /> + <Compile Include="StubOnExecuteParameters.cs" /> + <Compile Include="StubsSettings.cs" /> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> </ItemGroup> <ItemGroup> <ProjectReference Include="..\Tango.BL\Tango.BL.csproj"> @@ -88,6 +129,10 @@ <Project>{63561e19-ff5a-414b-a5ef-e30711543e1d}</Project> <Name>Tango.Emulations</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> @@ -100,6 +145,18 @@ <Project>{40073806-914e-4e78-97ab-fa9639308ebe}</Project> <Name>Tango.Protobuf</Name> </ProjectReference> + <ProjectReference Include="..\Tango.Scripting\Tango.Scripting.csproj"> + <Project>{401989e7-ae1e-4002-b0ee-9a9f63740b97}</Project> + <Name>Tango.Scripting</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> @@ -109,5 +166,15 @@ <None Include="app.config" /> <None Include="packages.config" /> </ItemGroup> + <ItemGroup> + <Page Include="Views\StubsView.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Page Include="Windows\TextInputWindow.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + </ItemGroup> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> </Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/ViewModels/CodeTabVM.cs b/Software/Visual_Studio/Tango.Stubs/ViewModels/CodeTabVM.cs new file mode 100644 index 000000000..7e27259a4 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/ViewModels/CodeTabVM.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Commands; +using Tango.Scripting; +using Tango.SharedUI; + +namespace Tango.Stubs.ViewModels +{ + /// <summary> + /// Represents a single script editor tab view model; + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel" /> + public class CodeTabVM : ViewModel + { + private String _title; + /// <summary> + /// Gets or sets the script title/file name. + /// </summary> + public String Title + { + get + { + return File != null ? Path.GetFileName(File) : _title; + } + set + { + _title = value; + RaisePropertyChanged(nameof(Title)); + } + } + + private String _file; + /// <summary> + /// Gets or sets the full script file path. + /// </summary> + public String File + { + get { return _file; } + set + { + _file = value; + RaisePropertyChanged(nameof(File)); + RaisePropertyChanged(nameof(Title)); + } + } + + private String _code; + /// <summary> + /// Gets or sets the script code. + /// </summary> + public String Code + { + get { return _code; } + set { _code = value; RaisePropertyChanged(nameof(Code)); } + } + + private bool _isRunning; + /// <summary> + /// Gets or sets a value indicating whether this instance is running. + /// </summary> + public bool IsRunning + { + get { return _isRunning; } + set { _isRunning = value; RaisePropertyChangedAuto(); } + } + + private RelayCommand _insertCodeSnippetCommand; + /// <summary> + /// Gets or sets the insert snippet command. (Inserts stub snippet to editor) + /// </summary> + public RelayCommand InsertSnippetCommand + { + get { return _insertCodeSnippetCommand; } + set { _insertCodeSnippetCommand = value; RaisePropertyChanged(nameof(InsertSnippetCommand)); } + } + + private ObservableCollection<CompilerError> _errors; + /// <summary> + /// Gets or sets the errors. + /// </summary> + public ObservableCollection<CompilerError> Errors + { + get { return _errors; } + set { _errors = value; RaisePropertyChangedAuto(); } + } + + /// <summary> + /// Initializes a new instance of the <see cref="CodeTabVM"/> class. + /// </summary> + public CodeTabVM() + { + Title = "untitled"; + Code = Properties.Resources.CodeTabTemplate; + Errors = new ObservableCollection<CompilerError>(); + } + + /// <summary> + /// Returns a <see cref="System.String" /> that represents this instance. + /// </summary> + /// <returns> + /// A <see cref="System.String" /> that represents this instance. + /// </returns> + public override string ToString() + { + return Title; + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/ViewModels/CreateGroupVM.cs b/Software/Visual_Studio/Tango.Stubs/ViewModels/CreateGroupVM.cs new file mode 100644 index 000000000..dc5ce591f --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/ViewModels/CreateGroupVM.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; + +namespace Tango.Stubs.ViewModels +{ + public class CreateGroupVM : ExtendedObject + { + public String Name { get; set; } + + public List<CreateItemVM> Items { get; set; } + + public CreateGroupVM() + { + Items = new List<CreateItemVM>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/ViewModels/CreateItemVM.cs b/Software/Visual_Studio/Tango.Stubs/ViewModels/CreateItemVM.cs new file mode 100644 index 000000000..dafdca60e --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/ViewModels/CreateItemVM.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.Core; + +namespace Tango.Stubs.ViewModels +{ + public class CreateItemVM : ExtendedObject + { + public Type Type { get; set; } + + public String Name { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/ViewModels/ExampleVM.cs b/Software/Visual_Studio/Tango.Stubs/ViewModels/ExampleVM.cs new file mode 100644 index 000000000..4f2efc78a --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/ViewModels/ExampleVM.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Stubs.ViewModels +{ + public class ExampleVM + { + public String Name { get; set; } + + public String Code { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/ViewModels/StubSnippetVM.cs b/Software/Visual_Studio/Tango.Stubs/ViewModels/StubSnippetVM.cs new file mode 100644 index 000000000..9d0f636f0 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/ViewModels/StubSnippetVM.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.SharedUI; + +namespace Tango.Stubs.ViewModels +{ + /// <summary> + /// Represents a single stub snippet view model. + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel" /> + public class StubSnippetVM : ViewModel + { + private String _name; + /// <summary> + /// Gets or sets the stub name. + /// </summary> + public String Name + { + get { return _name; } + set { _name = value; RaisePropertyChanged(nameof(Name)); } + } + + private String _code; + /// <summary> + /// Gets or sets the snippet code. + /// </summary> + public String Code + { + get { return _code; } + set { _code = value; RaisePropertyChanged(nameof(Code)); } + } + + /// <summary> + /// Returns a <see cref="System.String" /> that represents this instance. + /// </summary> + /// <returns> + /// A <see cref="System.String" /> that represents this instance. + /// </returns> + public override string ToString() + { + return Name; + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/ViewModels/StubsViewVM.cs b/Software/Visual_Studio/Tango.Stubs/ViewModels/StubsViewVM.cs new file mode 100644 index 000000000..dbcf0887b --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/ViewModels/StubsViewVM.cs @@ -0,0 +1,847 @@ +using Google.Protobuf; +using Google.Protobuf.Collections; +using Microsoft.Win32; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Threading; +using Tango.Core.Commands; +using Tango.Integration.Operation; +using Tango.PMR; +using Tango.Scripting; +using Tango.Settings; +using Tango.SharedUI; +using Tango.Stubs.Views; +using Tango.Transport; +using Tango.Transport.Adapters; + +namespace Tango.Stubs.ViewModels +{ + /// <summary> + /// Represents the script execution utility main view model. + /// </summary> + /// <seealso cref="Tango.SharedUI.ViewModel" /> + public class StubsViewVM : ViewModel + { + private StubManager _stubManager; + private TextBox _logTextBox; + private StubsSettings _settings; + + #region Properties + + public ITransportAdapter OverrideAdapter { get; set; } + + public List<CreateGroupVM> CreateGroups { get; set; } + + public List<ExampleVM> Examples { get; set; } + + private IMachineOperator _machineOperator; + /// <summary> + /// Gets or sets the machine operator. + /// </summary> + public IMachineOperator MachineOperator + { + get { return _machineOperator; } + set { _machineOperator = value; RaisePropertyChangedAuto(); } + } + + /// <summary> + /// Gets or sets the code tabs. + /// </summary> + public ObservableCollection<CodeTabVM> CodeTabs { get; set; } + + /// <summary> + /// Gets or sets the additional highlight C# types. + /// </summary> + public ObservableCollection<KeyValuePair<String, Type>> HighlightTypes { get; set; } + + /// <summary> + /// Gets or sets the intellisense types. + /// </summary> + public ObservableCollection<KeyValuePair<String, Type>> IntellisenseTypes { get; set; } + + /// <summary> + /// Gets or sets the collection of stub snippets. + /// </summary> + public ObservableCollection<StubSnippetVM> StubSnippets { get; set; } + + private StubSnippetVM _selectedStubSnippet; + /// <summary> + /// Gets or sets the selected stub snippet. + /// </summary> + public StubSnippetVM SelectedStubSnippet + { + get { return _selectedStubSnippet; } + set { _selectedStubSnippet = value; RaisePropertyChanged(nameof(SelectedStubSnippet)); } + } + + private CodeTabVM _selectedCodeTab; + /// <summary> + /// Gets or sets the selected code tab. + /// </summary> + public CodeTabVM SelectedCodeTab + { + get { return _selectedCodeTab; } + set { _selectedCodeTab = value; RaisePropertyChanged(nameof(SelectedCodeTab)); InvalidateRelayCommands(); } + } + + private bool _isConnected; + /// <summary> + /// Gets or sets a value indicating whether the USB adapter is connected. + /// </summary> + public bool IsConnected + { + get { return _isConnected; } + set { _isConnected = value; RaisePropertyChanged(nameof(IsConnected)); InvalidateRelayCommands(); } + } + + private List<String> _ports; + /// <summary> + /// Gets or sets the available USB ports. + /// </summary> + public List<String> Ports + { + get { return _ports; } + set { _ports = value; RaisePropertyChanged(nameof(Ports)); } + } + + private String _selectedPort; + /// <summary> + /// Gets or sets the selected USB port. + /// </summary> + public String SelectedPort + { + get { return _selectedPort; } + set { _selectedPort = value; RaisePropertyChanged(nameof(SelectedPort)); InvalidateRelayCommands(); } + } + + private String _status; + /// <summary> + /// Gets or sets the current status bar text. + /// </summary> + public String Status + { + get { return _status; } + set { _status = value; RaisePropertyChanged(nameof(Status)); } + } + + private bool _isRunning; + /// <summary> + /// Gets or sets a value indicating whether a stub is currently running. + /// </summary> + public bool IsRunning + { + get { return _isRunning; } + set { _isRunning = value; RaisePropertyChanged(nameof(IsRunning)); InvalidateRelayCommands(); } + } + + private bool _appendLogAuto; + /// <summary> + /// Gets or sets a value indicating whether the logs automatically. + /// </summary> + public bool AppendLogAuto + { + get { return _appendLogAuto; } + set { _appendLogAuto = value; RaisePropertyChangedAuto(); } + } + + private UsbSerialBaudRates _baudRate; + /// <summary> + /// Gets or sets the baud rate. + /// </summary> + public UsbSerialBaudRates BaudRate + { + get { return _baudRate; } + set { _baudRate = value; RaisePropertyChangedAuto(); } + } + + private ConnectionMode _connectionMode; + /// <summary> + /// Gets or sets the connection mode. + /// </summary> + public ConnectionMode ConnectionMode + { + get { return _connectionMode; } + set { _connectionMode = value; RaisePropertyChangedAuto(); } + } + + private bool _displayConnectionPane; + /// <summary> + /// Gets or sets a value indicating whether [hide connection pane]. + /// </summary> + public bool DisplayConnectionPane + { + get { return _displayConnectionPane; } + set { _displayConnectionPane = value; RaisePropertyChangedAuto(); } + } + + #endregion + + #region Commands + + /// <summary> + /// Gets or sets the new command. + /// </summary> + public RelayCommand NewCommand { get; set; } + + /// <summary> + /// Gets or sets the close tab command. + /// </summary> + public RelayCommand<CodeTabVM> CloseTabCommand { get; set; } + + /// <summary> + /// Gets or sets the build command. + /// </summary> + public RelayCommand BuildCommand { get; set; } + + /// <summary> + /// Gets or sets the run command. + /// </summary> + public RelayCommand RunCommand { get; set; } + + /// <summary> + /// Gets or sets the stop command. + /// </summary> + public RelayCommand StopCommand { get; set; } + + /// <summary> + /// Gets or sets the toggle connection command. + /// </summary> + public RelayCommand ToggleConnectionCommand { get; set; } + + /// <summary> + /// Gets or sets the open command. + /// </summary> + public RelayCommand OpenCommand { get; set; } + + /// <summary> + /// Gets or sets the save command. + /// </summary> + public RelayCommand SaveCommand { get; set; } + + /// <summary> + /// Gets or sets the save as command. + /// </summary> + public RelayCommand SaveAsCommand { get; set; } + + /// <summary> + /// Gets or sets the clear command. + /// </summary> + public RelayCommand ClearCommand { get; set; } + + /// <summary> + /// Gets or sets the stub snippet selected command. + /// </summary> + public RelayCommand StubSnippetSelectedCommand { get; set; } + + /// <summary> + /// Gets or sets the insert snippet command. + /// </summary> + public RelayCommand<String> InsertSnippetCommand { get; set; } + + /// <summary> + /// Gets or sets the exit command. + /// </summary> + public RelayCommand ExitCommand { get; set; } + + /// <summary> + /// Gets or sets the create item command. + /// </summary> + public RelayCommand<CreateItemVM> CreateItemCommand { get; set; } + + /// <summary> + /// Gets or sets the create example command. + /// </summary> + public RelayCommand<ExampleVM> CreateExampleCommand { get; set; } + #endregion + + #region Constructors + + /// <summary> + /// Initializes a new instance of the <see cref="StubsViewVM"/> class. + /// </summary> + public StubsViewVM() + { + DisplayConnectionPane = true; + + _settings = SettingsManager.Default.GetOrCreate<StubsSettings>(); + + Examples = new List<ExampleVM>(); + CodeTabs = new ObservableCollection<CodeTabVM>(); + NewCommand = new RelayCommand(CreateNewTab); + CloseTabCommand = new RelayCommand<CodeTabVM>(OnTabClosing); + RunCommand = new RelayCommand(RunTab, (x) => IsConnected && !IsRunning && SelectedCodeTab != null); + BuildCommand = new RelayCommand(async () => await BuildTab(), (x) => !IsRunning && SelectedCodeTab != null); + StopCommand = new RelayCommand(StopTab, (x) => IsConnected && IsRunning && SelectedCodeTab != null); + InsertSnippetCommand = new RelayCommand<string>((x) => { }); + CreateExampleCommand = new RelayCommand<ExampleVM>(CreateExample); + + HighlightTypes = new ObservableCollection<KeyValuePair<string, Type>>(); + IntellisenseTypes = new ObservableCollection<KeyValuePair<string, Type>>(); + + IntellisenseTypes.Add(new KeyValuePair<string, Type>("stubManager", typeof(StubManager))); + + foreach (var stubType in typeof(PMR.Common.MessageContainer).Assembly.GetTypes().Where(x => typeof(IMessage).IsAssignableFrom(x))) + { + HighlightTypes.Add(new KeyValuePair<string, Type>(stubType.Name, stubType)); + } + + HighlightTypes.Add(new KeyValuePair<string, Type>("Thread", typeof(Thread))); + HighlightTypes.Add(new KeyValuePair<string, Type>("DateTime", typeof(DateTime))); + HighlightTypes.Add(new KeyValuePair<string, Type>("TimeSpan", typeof(TimeSpan))); + HighlightTypes.Add(new KeyValuePair<string, Type>("Dispatcher", typeof(Dispatcher))); + HighlightTypes.Add(new KeyValuePair<string, Type>("Task", typeof(Task))); + HighlightTypes.Add(new KeyValuePair<string, Type>("List", typeof(IList<Object>))); + HighlightTypes.Add(new KeyValuePair<string, Type>("int", typeof(Int32))); + HighlightTypes.Add(new KeyValuePair<string, Type>("double", typeof(Double))); + HighlightTypes.Add(new KeyValuePair<string, Type>("String", typeof(String))); + HighlightTypes.Add(new KeyValuePair<string, Type>("string", typeof(String))); + + foreach (var item in HighlightTypes) + { + IntellisenseTypes.Add(item); + } + + StubSnippets = new ObservableCollection<StubSnippetVM>(); + + foreach (var stubType in MessageFactory.GetAvailableRequestStubs()) + { + StubSnippetVM snippet = new StubSnippetVM(); + snippet.Name = stubType.Name.Replace("Stub", "").Replace("Request", "").ToWords(); + + snippet.Code = String.Empty; + + snippet.Code += "// " + "Request ----" + Environment.NewLine; + + foreach (var prop in stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) + { + snippet.Code += "// " + prop.PropertyType.Name + " : " + prop.Name + Environment.NewLine; + } + + Type responseType = MessageFactory.GetAvailableRequestResponseStubs().SingleOrDefault(x => x.Name == stubType.Name.Replace("Request", "Response")); + + if (responseType != null) + { + snippet.Code += Environment.NewLine + "// " + "Response ----" + Environment.NewLine; + + foreach (var prop in responseType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) + { + snippet.Code += "// " + prop.PropertyType.Name + " : " + prop.Name + Environment.NewLine; + } + } + + snippet.Code += String.Format("var response = stubManager.Run<{2}>(\"{0}\" ,{1});", stubType.Name, String.Join(", ", stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.PropertyType.Name == "string" ? "\"string\"" : x.PropertyType.Name)), stubType.Name.Replace("Request", "Response")); + StubSnippets.Add(snippet); + } + + ToggleConnectionCommand = new RelayCommand(ToggleConnection, (x) => !IsRunning); + OpenCommand = new RelayCommand(OpenFile); + SaveCommand = new RelayCommand(SaveFile); + SaveAsCommand = new RelayCommand(SaveAsFile); + StubSnippetSelectedCommand = new RelayCommand(OnStubSnippetSelected); + ExitCommand = new RelayCommand(() => Application.Current.Shutdown()); + ClearCommand = new RelayCommand(ClearLog); + + Ports = new List<string>(); + + for (int i = 1; i < 100; i++) + { + Ports.Add("COM" + i); + } + + SelectedPort = _settings.SelectedPort != null ? _settings.SelectedPort : Ports.First(); + BaudRate = _settings.BaudRate; + AppendLogAuto = _settings.AutoLogResponse; + + Status = "Ready"; + + if (_settings.LastTabs.Count > 0) + { + foreach (var file in _settings.LastTabs) + { + if (File.Exists(file)) + { + OpenFile(file); + } + } + } + else + { + CreateNewTab(); + } + + CreateGroups = new List<CreateGroupVM>(); + + foreach (var typesGroup in typeof(PMR.Common.MessageContainer).Assembly.GetTypes().Where(x => x.IsClass && !x.IsGenericType && !x.Name.Contains("Reflection") && typeof(IMessage).IsAssignableFrom(x)).GroupBy(x => x.Namespace)) + { + CreateGroupVM group = new CreateGroupVM(); + group.Name = typesGroup.First().Namespace.Split('.').Last(); + + foreach (var type in typesGroup) + { + group.Items.Add(new CreateItemVM() + { + Name = type.Name, + Type = type, + }); + } + + CreateGroups.Add(group); + } + + CreateItemCommand = new RelayCommand<CreateItemVM>(CreateItem); + + foreach (var name in typeof(StubsViewVM).Assembly.GetManifestResourceNames()) + { + if (name.Contains(".Examples.")) + { + using (Stream stream = typeof(StubsViewVM).Assembly.GetManifestResourceStream(name)) + { + StreamReader reader = new StreamReader(stream); + + ExampleVM example = new ExampleVM(); + String[] str = name.Split('.'); + example.Name = str[str.Length - 2].ToWords(); + example.Code = reader.ReadToEnd(); + Examples.Add(example); + } + } + } + + Examples = Examples.OrderBy(x => x.Name).ToList(); + + Application.Current.Exit += Current_Exit; + + LogManager.RegisterLogger(new Logging.FileLogger() { Enabled = true }); + LogManager.Log("Application Started!"); + } + + public StubsViewVM(ConnectionMode connectionMode) : this() + { + ConnectionMode = connectionMode; + + if (ConnectionMode == ConnectionMode.External) + { + IsConnected = true; + DisplayConnectionPane = false; + } + } + + #endregion + + #region Virtual Methods + + /// <summary> + /// Called when a stub snippet is double clicked. + /// </summary> + protected virtual void OnStubSnippetSelected() + { + if (SelectedStubSnippet != null) + { + if (InsertSnippetCommand != null) + { + InsertSnippetCommand.Execute(SelectedStubSnippet.Code); + } + } + } + + /// <summary> + /// Called when user closes a script tab. + /// </summary> + /// <param name="codeTab">The code tab.</param> + protected virtual void OnTabClosing(CodeTabVM codeTab) + { + CodeTabs.Remove(codeTab); + } + + #endregion + + #region Private Methods + + private void CreateExample(ExampleVM example) + { + CreateNewTab(); + SelectedCodeTab.Code = example.Code; + SelectedCodeTab.Title = example.Name; + } + + private void CreateItem(CreateItemVM item) + { + if (item != null) + { + if (InsertSnippetCommand != null) + { + String code = String.Empty; + + FormatProperties(item.Type, ref code); + + InsertSnippetCommand.Execute(code); + } + } + } + + private void FormatProperties(Type type, ref String code) + { + code += Environment.NewLine + String.Format("{0} {1} = new {0}();", type.Name, type.Name.ToCamelCase()) + Environment.NewLine; + + foreach (var prop in type.GetProperties(BindingFlags.Instance | BindingFlags.Public)) + { + if (prop.PropertyType == typeof(String)) + { + code += String.Format("{0}.{1} = {2};", type.Name.ToCamelCase(), prop.Name, "null") + Environment.NewLine; + } + else if (prop.PropertyType.IsEnum) + { + code += String.Format("{0}.{1} = {2};", type.Name.ToCamelCase(), prop.Name, Activator.CreateInstance(prop.PropertyType).GetType().FullName + "." + Activator.CreateInstance(prop.PropertyType).ToString()) + Environment.NewLine; + } + else if (!prop.PropertyType.IsClass) + { + code += String.Format("{0}.{1} = {2};", type.Name.ToCamelCase(), prop.Name, Activator.CreateInstance(prop.PropertyType).ToString().ToLower()) + Environment.NewLine; + } + else if (prop.PropertyType.IsGenericType) + { + Type genericType = prop.PropertyType.GenericTypeArguments[0]; + FormatProperties(genericType, ref code); + code += String.Format("{0}.{1}.Add({2});", type.Name.ToCamelCase(), prop.Name, genericType.Name.ToCamelCase()) + Environment.NewLine; + } + else + { + FormatProperties(prop.PropertyType, ref code); + code += Environment.NewLine + String.Format("{0}.{1} = {2};", type.Name.ToCamelCase(), prop.Name, prop.Name.ToCamelCase()) + Environment.NewLine; + } + } + } + + /// <summary> + /// Clears the log. + /// </summary> + private void ClearLog() + { + _logTextBox.Clear(); + } + + /// <summary> + /// Saves the selected script file. + /// </summary> + private async void SaveFile() + { + if (SelectedCodeTab != null) + { + if (SelectedCodeTab.File == null) + { + SaveAsFile(); + } + else + { + Status = "Saving " + SelectedCodeTab.File + "..."; + File.WriteAllText(SelectedCodeTab.File, SelectedCodeTab.Code); + await Task.Delay(1000); + Status = "Ready"; + } + } + } + + /// <summary> + /// Saves the selected script file. + /// </summary> + private async void SaveAsFile() + { + if (SelectedCodeTab != null) + { + SaveFileDialog dlg = new SaveFileDialog(); + dlg.Filter = "C# Script Files|*.cs"; + dlg.DefaultExt = ".cs"; + if (dlg.ShowDialog().Value) + { + Status = "Saving " + dlg.FileName + "..."; + File.WriteAllText(dlg.FileName, SelectedCodeTab.Code); + SelectedCodeTab.File = dlg.FileName; + await Task.Delay(1000); + Status = "Ready"; + } + } + } + + /// <summary> + /// Opens a script from HD. + /// </summary> + private void OpenFile() + { + OpenFileDialog dlg = new OpenFileDialog(); + dlg.Filter = "C# Script Files|*.cs"; + dlg.Multiselect = true; + if (dlg.ShowDialog().Value) + { + foreach (var file in dlg.FileNames) + { + OpenFile(file); + } + } + } + + /// <summary> + /// Opens the file. + /// </summary> + /// <param name="file">The file.</param> + private void OpenFile(String file) + { + var newTab = new CodeTabVM(); + newTab.File = file; + newTab.Code = File.ReadAllText(file); + CodeTabs.Add(newTab); + SelectedCodeTab = newTab; + } + + /// <summary> + /// Toggles the USB adapter connection. + /// </summary> + private void ToggleConnection() + { + try + { + if (!IsConnected) + { + _machineOperator = new MachineOperator(); + _machineOperator.Adapter = new UsbTransportAdapter(SelectedPort, BaudRate); + _machineOperator.Connect().Wait(); + IsConnected = true; + } + else + { + _machineOperator.Disconnect().Wait(); + IsConnected = false; + } + } + catch (Exception ex) + { + MessageBox.Show(ex.ToString(), "Tango"); + } + } + + /// <summary> + /// Creates a new script tab. + /// </summary> + private void CreateNewTab() + { + var newTab = new CodeTabVM(); + CodeTabs.Add(newTab); + SelectedCodeTab = newTab; + } + + /// <summary> + /// Runs the selected script tab. + /// </summary> + private async void RunTab() + { + await BuildTab(); + + if (SelectedCodeTab.Errors.Count > 0) return; + + IsRunning = true; + SelectedCodeTab.IsRunning = true; + _logTextBox.Text = (DateTime.Now.ToTimeString() + ": ") + "Executing script '" + SelectedCodeTab.Title + "'..." + Environment.NewLine; + + await Task.Factory.StartNew(async () => + { + try + { + _stubManager = new StubManager(_machineOperator, (txt) => + { + AppendTextLog(txt + Environment.NewLine); + }, (txt) => + { + AppendTextLog(txt); + }, () => + { + + }); + var thisStubManager = _stubManager; + _stubManager.Completed += Manager_Completed; + _stubManager.Failed += Manager_Failed; + _stubManager.Executed += Manager_Executed; + _stubManager.AutoLog = AppendLogAuto; + + ScriptEngine engine = new ScriptEngine(new StubOnExecuteParameters(_stubManager)); + + engine.ReferencedAssemblies.Add(this.GetType()); + engine.ReferencedAssemblies.Add(typeof(PMR.Stubs.CalculateRequest)); + engine.ReferencedAssemblies.Add(typeof(IMessage)); + await engine.Run(SelectedCodeTab.Code, Path.GetDirectoryName(SelectedCodeTab.File)); + + if (!thisStubManager.Aborted) + { + IsRunning = false; + SelectedCodeTab.IsRunning = false; + } + } + catch (Exception ex) + { + IsRunning = false; + SelectedCodeTab.IsRunning = false; + MessageBox.Show(ex.Message, "Tango"); + } + }); + } + + /// <summary> + /// Builds the tab. + /// </summary> + private Task BuildTab() + { + return Task.Factory.StartNew(() => + { + try + { + Status = "Compiling " + SelectedCodeTab.Title + "..."; + + var thisStubManager = _stubManager; + + ScriptEngine engine = new ScriptEngine(new StubOnExecuteParameters(_stubManager)); + + engine.ReferencedAssemblies.Add(this.GetType()); + engine.ReferencedAssemblies.Add(typeof(PMR.Stubs.CalculateRequest)); + engine.ReferencedAssemblies.Add(typeof(IMessage)); + var results = engine.Compile(SelectedCodeTab.Code, Path.GetDirectoryName(SelectedCodeTab.File)).Result; + + if (results.Count == 0) + { + SelectedCodeTab.Errors = new ObservableCollection<CompilerError>(); + Status = "Compiled successfully."; + } + else + { + SelectedCodeTab.Errors = results.ToObservableCollection(); + Status = results.Count + " compilation errors found!"; + } + } + catch (Exception ex) + { + Status = "Error compiling!"; + SelectedCodeTab.Errors = new ObservableCollection<CompilerError>() { new CompilerError() { Error = ex.Message } }; + } + }); + } + + /// <summary> + /// Stops the currently current script. + /// </summary> + private void StopTab() + { + if (_stubManager != null) + { + _stubManager.Abort(); + IsRunning = false; + SelectedCodeTab.IsRunning = false; + Status = "Stopped!"; + AppendTextLog((DateTime.Now.ToTimeString() + ": ") + "Stopped!" + Environment.NewLine); + } + } + + #endregion + + #region Public Methods + + public void SetLogTextBox(TextBox logTextBox) + { + _logTextBox = logTextBox; + } + + #endregion + + #region Event Handlers + + /// <summary> + /// Handled the <see cref="StubManager"/> Executed event. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="stubName">Name of the stub.</param> + private void Manager_Executed(object sender, string stubName) + { + if (AppendLogAuto) + { + AppendTextLog((DateTime.Now.ToTimeString() + ": ") + "Executing '" + stubName + "'..." + Environment.NewLine); + } + + Status = "Executing " + stubName + "..."; + } + + /// <summary> + /// Handled the <see cref="StubManager"/> Failed event. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="ex">The exception.</param> + private void Manager_Failed(object sender, Exception ex) + { + if (IsRunning) + { + if (AppendLogAuto) + { + AppendTextLog((DateTime.Now.ToTimeString() + ": ") + ex.Message + Environment.NewLine); + } + + Status = "Failed!"; + } + } + + /// <summary> + /// Handled the <see cref="StubManager"/> Completed event. + /// </summary> + /// <param name="sender">The sender.</param> + /// <param name="response">The response.</param> + private void Manager_Completed(object sender, string response) + { + if (AppendLogAuto) + { + AppendTextLog((DateTime.Now.ToTimeString() + ": ") + "Response Received:" + Environment.NewLine); + AppendTextLog((DateTime.Now.ToTimeString() + ": ") + response + Environment.NewLine); + } + Status = "Completed"; + } + + private void Current_Exit(object sender, ExitEventArgs e) + { + LogManager.OverrideQueue = true; + LogManager.Log("Application Terminated"); + _settings.AutoLogResponse = AppendLogAuto; + _settings.SelectedPort = SelectedPort; + _settings.BaudRate = BaudRate; + _settings.LastTabs = CodeTabs.Select(x => x.File).ToList(); + _settings.Save(); + } + + private void AppendTextLog(String log) + { + LogManager.Log(log); + + InvokeUI(() => + { + if (_logTextBox.Text.Length > 99999) + { + _logTextBox.Clear(); + } + _logTextBox.AppendText(log); + }); + } + + private void ClearTextLog() + { + LogManager.Log("Log Cleared -----------------------------------------------------------------"); + + InvokeUI(() => + { + _logTextBox.Text = String.Empty; + }); + } + + #endregion + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml b/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml new file mode 100644 index 000000000..c27109232 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml @@ -0,0 +1,432 @@ +<UserControl x:Class="Tango.Stubs.Views.StubsView" + 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:mahapps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:views="clr-namespace:Tango.Stubs.Views" + xmlns:fa="http://schemas.fontawesome.io/icons/" + xmlns:local="clr-namespace:Tango.Stubs.Views" + xmlns:vm="clr-namespace:Tango.Stubs.ViewModels" + xmlns:System="clr-namespace:System;assembly=mscorlib" + xmlns:converters="clr-namespace:Tango.SharedUI.Converters;assembly=Tango.SharedUI" + xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI" + xmlns:transport="clr-namespace:Tango.Transport.Adapters;assembly=Tango.Transport" + mc:Ignorable="d" + d:DesignHeight="720" d:DesignWidth="1280" Background="#202020" Foreground="Gainsboro" d:DataContext="{d:DesignInstance Type=vm:StubsViewVM, IsDesignTimeCreatable=False}"> + + + + <UserControl.InputBindings> + <KeyBinding Key="S" Modifiers="Control" Command="{Binding SaveCommand}"/> + <KeyBinding Key="S" Modifiers="Ctrl+Shift" Command="{Binding SaveAsCommand}"/> + <KeyBinding Key="F6" Command="{Binding BuildCommand}"/> + </UserControl.InputBindings> + + <UserControl.Resources> + + <ResourceDictionary> + <ResourceDictionary.MergedDictionaries> + <!-- MahApps.Metro resource dictionaries. Make sure that all file names are Case Sensitive! --> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" /> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" /> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colors.xaml" /> + + <!-- Accent and AppTheme setting --> + + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseDark.xaml" /> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/FlatButton.xaml" /> + + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Colors.xaml" /> + <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/VS/Styles.xaml" /> + + <ResourceDictionary> + <ObjectDataProvider x:Key="baudRates" MethodName="GetValues" + ObjectType="{x:Type System:Enum}"> + <ObjectDataProvider.MethodParameters> + <x:Type TypeName="transport:UsbSerialBaudRates"/> + </ObjectDataProvider.MethodParameters> + </ObjectDataProvider> + + <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter> + <converters:EnumToDescriptionConverter x:Key="EnumToDescriptionConverter" /> + <Style BasedOn="{StaticResource MetroTabItem}" TargetType="{x:Type TabItem}"> + <Style.Triggers> + <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=IsSelected}" Value="True"> + <Setter Property="Background" Value="#007ACC"></Setter> + </DataTrigger> + </Style.Triggers> + <Setter Property="mahapps:ControlsHelper.HeaderFontSize" Value="12"></Setter> + <Setter Property="HeaderTemplate"> + <Setter.Value> + <DataTemplate> + <Border> + <StackPanel Orientation="Horizontal"> + <mahapps:ProgressRing Width="5" Height="5" Margin="0 0 5 0" Foreground="White" Visibility="{Binding IsRunning,Converter={StaticResource BooleanToVisibilityConverter}}"></mahapps:ProgressRing> + <TextBlock Text="{Binding Title}" ToolTip="{Binding File}" Foreground="Gainsboro" VerticalAlignment="Center"></TextBlock> + <Button Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.CloseTabCommand}" CommandParameter="{Binding}" Margin="5 0 0 0" Cursor="Hand" Width="24" Height="24" VerticalAlignment="Center" Style="{DynamicResource MetroCircleButtonStyle}" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0"> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Width="10" Height="10" Icon="Close" Foreground="Gainsboro"></fa:ImageAwesome> + </StackPanel> + </Button> + </StackPanel> + </Border> + </DataTemplate> + </Setter.Value> + </Setter> + <Setter Property="ContentTemplate"> + <Setter.Value> + <DataTemplate> + <Grid Background="#181818"> + <Grid.RowDefinitions> + <RowDefinition Height="1*" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <controls:ScriptEditorControl Text="{Binding Code,Mode=TwoWay}" InsertSnippetCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.InsertSnippetCommand,Mode=TwoWay}" SaveCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.SaveCommand}" HighlightTypes="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.HighlightTypes}" IntellisenseTypes="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.IntellisenseTypes}" RunCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.RunCommand}" StopCommand="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.StopCommand}" /> + + <Grid Grid.Row="1"> + <Grid.Style> + <Style TargetType="Grid"> + <Setter Property="Visibility" Value="Visible"></Setter> + <Style.Triggers> + <DataTrigger Binding="{Binding Errors.Count}" Value="0"> + <Setter Property="Visibility" Value="Collapsed"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Grid.Style> + <Border BorderThickness="1" BorderBrush="#4B4B4B" Margin="10"> + <DataGrid ItemsSource="{Binding Errors}" AutoGenerateColumns="False" Focusable="False" IsReadOnly="True" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeColumns="False" CanUserSortColumns="False" HeadersVisibility="None"> + <DataGrid.Columns> + <DataGridTemplateColumn Header="#" Width="50"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <fa:ImageAwesome Icon="ExclamationTriangle" Width="16" Foreground="#FF5C5C" /> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTextColumn Header="ERROR" Binding="{Binding Error}" MinWidth="200"></DataGridTextColumn> + <DataGridTemplateColumn Header="FILE" MinWidth="200"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock><Run>'</Run><Run Text="{Binding File}"></Run><Run>'</Run></TextBlock> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTemplateColumn Header="POSITION"> + <DataGridTemplateColumn.CellTemplate> + <DataTemplate> + <TextBlock><Run>(</Run><Run Text="{Binding Line}"></Run><Run>,</Run><Run Text="{Binding Character}"></Run><Run>)</Run></TextBlock> + </DataTemplate> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + </DataGrid.Columns> + </DataGrid> + </Border> + </Grid> + </Grid> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + </ResourceDictionary> + </ResourceDictionary.MergedDictionaries> + </ResourceDictionary> + </UserControl.Resources> + <UserControl.Style> + <Style TargetType="UserControl"> + <Style.Triggers> + <DataTrigger Binding="{Binding IsRunning}" Value="True"> + <Setter Property="Cursor" Value="AppStarting"></Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </UserControl.Style> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="Auto"/> + <RowDefinition Height="1*"/> + </Grid.RowDefinitions> + + <Grid> + <Menu IsMainMenu="True" BorderThickness="0" Padding="0 8"> + <MenuItem Header="File"> + <MenuItem Header="New" Command="{Binding NewCommand}"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="FileOutline" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Open" MinWidth="150" Command="{Binding OpenCommand}"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="FolderOutline" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Save" Command="{Binding SaveCommand}" InputGestureText="Ctrl+S"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Save" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Save as" Command="{Binding SaveAsCommand}" InputGestureText="Ctrl+Shift+S"> + <MenuItem.Icon> + <Grid> + <fa:ImageAwesome Icon="Save" Width="10" Foreground="Gainsboro" Margin="2" /> + <fa:ImageAwesome Icon="Save" Width="10" Foreground="Gainsboro" Margin="2 -5 -5 2" /> + </Grid> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Exit" Command="{Binding ExitCommand}"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="SignOut" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + </MenuItem> + <MenuItem Header="Edit"> + <MenuItem Header="Cut" MinWidth="150" Command="Cut"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Cut" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Copy" Command="Copy"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Copy" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Paste" Command="Paste"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Paste" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <Separator/> + <MenuItem Header="Undo" Command="Undo"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Undo" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Redo" Command="Redo"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Repeat" Width="12" Foreground="Gainsboro" Margin="2" /> + </MenuItem.Icon> + </MenuItem> + </MenuItem> + <MenuItem Header="Wizard" ItemsSource="{Binding CreateGroups}"> + <MenuItem.ItemContainerStyle> + <Style TargetType="{x:Type MenuItem}"> + <Setter Property="Padding" Value="2"></Setter> + <Setter Property="Command" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.CreateItemCommand}" /> + <Setter Property="CommandParameter" Value="{Binding}"></Setter> + </Style> + </MenuItem.ItemContainerStyle> + <MenuItem.ItemTemplate> + <HierarchicalDataTemplate DataType="{x:Type vm:CreateGroupVM}" ItemsSource="{Binding Path=Items}"> + <TextBlock Text="{Binding Name}"/> + </HierarchicalDataTemplate> + </MenuItem.ItemTemplate> + </MenuItem> + <MenuItem Header="Examples" ItemsSource="{Binding Examples}"> + <MenuItem.ItemContainerStyle> + <Style TargetType="{x:Type MenuItem}"> + <Setter Property="Padding" Value="2"></Setter> + <Setter Property="Command" Value="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.CreateExampleCommand}" /> + <Setter Property="CommandParameter" Value="{Binding}"></Setter> + </Style> + </MenuItem.ItemContainerStyle> + <MenuItem.ItemTemplate> + <DataTemplate> + <TextBlock Text="{Binding Name}" ToolTip="{Binding Code}"></TextBlock> + </DataTemplate> + </MenuItem.ItemTemplate> + </MenuItem> + <MenuItem Header="Debug"> + <MenuItem Header="Build (F6)" MinWidth="150" Command="{Binding BuildCommand}" > + <MenuItem.Icon> + <fa:ImageAwesome Icon="Cog" Width="12" Margin="2"> + <fa:ImageAwesome.Style> + <Style TargetType="fa:ImageAwesome"> + <Setter Property="Foreground" Value="#EF8E29"></Setter> + <Style.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="Gray"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </fa:ImageAwesome.Style> + </fa:ImageAwesome> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Run (F5)" MinWidth="150" Command="{Binding RunCommand}" > + <MenuItem.Icon> + <fa:ImageAwesome Icon="Play" Width="12" Margin="2"> + <fa:ImageAwesome.Style> + <Style TargetType="fa:ImageAwesome"> + <Setter Property="Foreground" Value="#8DD28A"></Setter> + <Style.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="Gray"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </fa:ImageAwesome.Style> + </fa:ImageAwesome> + </MenuItem.Icon> + </MenuItem> + <MenuItem Header="Stop" Command="{Binding StopCommand}" IsEnabled="False"> + <MenuItem.Icon> + <fa:ImageAwesome Icon="Stop" Width="12" Margin="2"> + <fa:ImageAwesome.Style> + <Style TargetType="fa:ImageAwesome"> + <Setter Property="Foreground" Value="#F38B76"></Setter> + <Style.Triggers> + <Trigger Property="IsEnabled" Value="False"> + <Setter Property="Foreground" Value="Gray"></Setter> + </Trigger> + </Style.Triggers> + </Style> + </fa:ImageAwesome.Style> + </fa:ImageAwesome> + </MenuItem.Icon> + </MenuItem> + </MenuItem> + </Menu> + </Grid> + + <Grid Grid.Row="2"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="1019*"/> + <ColumnDefinition Width="220"/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="1*"/> + <RowDefinition Height="5"/> + <RowDefinition Height="0.5*"/> + </Grid.RowDefinitions> + + <Grid> + <TabControl x:Name="tabControl" Margin="5" ItemsSource="{Binding CodeTabs}" SelectedItem="{Binding SelectedCodeTab}"> + + </TabControl> + + <Grid HorizontalAlignment="Right" Margin="0 45 40 0" VerticalAlignment="Top" Visibility="{Binding IsRunning,Converter={StaticResource BooleanToVisibilityConverter}}"> + <StackPanel Orientation="Horizontal"> + <mahapps:ProgressRing Foreground="#007ACC" Width="20" Height="20"></mahapps:ProgressRing> + <TextBlock Text="Running..." FontStyle="Italic" Margin="10 0 0 0" FontSize="14" VerticalAlignment="Center"></TextBlock> + </StackPanel> + </Grid> + </Grid> + + <Grid Grid.Column="1" Grid.RowSpan="3"> + <Grid VerticalAlignment="Bottom" Height="25" Background="#007ACC"> + + </Grid> + <DockPanel> + <GroupBox Header="COMMUNICATION PORT" VerticalAlignment="Top" DockPanel.Dock="Top" Margin="0 2 0 0" Visibility="{Binding DisplayConnectionPane,Converter={StaticResource BooleanToVisibilityConverter}}"> + <StackPanel> + <ComboBox Margin="0 10 0 0" BorderThickness="0" ItemsSource="{Binding Ports}" Height="35" SelectedItem="{Binding SelectedPort}"></ComboBox> + <ComboBox Margin="0 10 0 0" BorderThickness="0" ItemsSource="{Binding Source={StaticResource baudRates}}" Height="35" SelectedItem="{Binding BaudRate}" SelectedIndex="0"> + <ComboBox.ItemTemplate> + <DataTemplate> + <TextBlock Text="{Binding Path=.,Converter={StaticResource EnumToDescriptionConverter}}" /> + </DataTemplate> + </ComboBox.ItemTemplate> + </ComboBox> + </StackPanel> + </GroupBox> + + <GroupBox Header="CONNECTION" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" Margin="0 10 0 25" Visibility="{Binding DisplayConnectionPane,Converter={StaticResource BooleanToVisibilityConverter}}"> + <StackPanel> + <Button Height="50" MinWidth="100" mahapps:ButtonHelper.PreserveTextCase="True" BorderThickness="0" Command="{Binding ToggleConnectionCommand}"> + <Button.Style> + <Style TargetType="Button" BasedOn="{StaticResource AccentedSquareButtonStyle}"> + <Style.Triggers> + <DataTrigger Binding="{Binding IsConnected}" Value="False"> + <Setter Property="Content"> + <Setter.Value> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="Link" Width="16"></fa:ImageAwesome> + <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">CONNECT</TextBlock> + </StackPanel> + </Setter.Value> + </Setter> + </DataTrigger> + <DataTrigger Binding="{Binding IsConnected}" Value="True"> + <Setter Property="Content"> + <Setter.Value> + <StackPanel Orientation="Horizontal"> + <fa:ImageAwesome Icon="Unlink" Width="16"></fa:ImageAwesome> + <TextBlock VerticalAlignment="Center" Margin="10 0 10 0">DISCONNECT</TextBlock> + </StackPanel> + </Setter.Value> + </Setter> + </DataTrigger> + </Style.Triggers> + </Style> + </Button.Style> + </Button> + </StackPanel> + </GroupBox> + + <GroupBox Header="STUB SNIPPETS" Margin="0 10 0 30"> + <Grid> + <ListBox BorderThickness="0" ItemsSource="{Binding StubSnippets}" HorizontalContentAlignment="Stretch" SelectedItem="{Binding SelectedStubSnippet}"> + <ListBox.ItemContainerStyle> + <Style TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}"> + <Setter Property="Padding" Value="0"></Setter> + <Setter Property="Margin" Value="0 2 0 2"></Setter> + <Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter> + </Style> + </ListBox.ItemContainerStyle> + <ListBox.ItemTemplate> + <DataTemplate> + <Border BorderThickness="1" BorderBrush="#007ACC" Padding="8" Background="Transparent"> + <Border.InputBindings> + <MouseBinding Gesture="LeftDoubleClick" Command="{Binding RelativeSource={RelativeSource AncestorType=UserControl},Path=DataContext.StubSnippetSelectedCommand}"/> + </Border.InputBindings> + <Grid> + <fa:ImageAwesome Icon="ArrowLeft" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5 0 0 0" Foreground="#007ACC" Width="16" Height="16"></fa:ImageAwesome> + <TextBlock VerticalAlignment="Center" FontSize="11" HorizontalAlignment="Center" Text="{Binding Name}"></TextBlock> + </Grid> + </Border> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + </Grid> + </GroupBox> + </DockPanel> + </Grid> + + <GridSplitter Margin="5 0 5 0" Grid.Row="1" Height="5" HorizontalAlignment="Stretch" VerticalAlignment="Center"> + <GridSplitter.Background> + <LinearGradientBrush> + <GradientStop/> + <GradientStop Color="#007ACC" Offset="0.5"/> + <GradientStop Offset="1"/> + </LinearGradientBrush> + </GridSplitter.Background> + </GridSplitter> + + <Grid Grid.Row="2"> + <Grid.RowDefinitions> + <RowDefinition Height="1*"/> + <RowDefinition Height="25"/> + </Grid.RowDefinitions> + <GroupBox Header="Response"> + <Grid Background="#151515"> + <TextBox x:Name="txtLog" PreviewMouseDown="txtLog_PreviewMouseUp" FontFamily="Lucida Console" TextChanged="TextBox_TextChanged" Background="Transparent" BorderThickness="0" AcceptsReturn="True" VerticalScrollBarVisibility="Visible" Padding="5" IsReadOnly="True" TextWrapping="Wrap" FontSize="11" Foreground="Gainsboro"></TextBox> + + <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 -32 -6 0"> + <CheckBox VerticalAlignment="Center" Margin="0 0 20 0" IsChecked="{Binding AppendLogAuto}">Auto Logging</CheckBox> + <CheckBox x:Name="chkScroll" IsChecked="True" VerticalAlignment="Center" Margin="0 0 20 0">Scroll To End</CheckBox> + <Button Width="80" Height="25" Command="{Binding ClearCommand}">CLEAR</Button> + </StackPanel> + </Grid> + </GroupBox> + <StatusBar Background="#007ACC" Grid.Row="1"> + <TextBlock Text="{Binding Status}"></TextBlock> + </StatusBar> + </Grid> + </Grid> + </Grid> +</UserControl> diff --git a/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml.cs b/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml.cs new file mode 100644 index 000000000..0f772f4ba --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Views/StubsView.xaml.cs @@ -0,0 +1,56 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; +using Tango.SharedUI.Controls; +using Tango.Stubs.ViewModels; + +namespace Tango.Stubs.Views +{ + /// <summary> + /// Interaction logic for MainView.xaml + /// </summary> + public partial class StubsView : UserControl + { + private StubsViewVM _vm; + + public StubsView() : base() + { + InitializeComponent(); + + Loaded += (_, __) => + { + _vm = DataContext as StubsViewVM; + _vm.SetLogTextBox(txtLog); + + + }; + } + + //Auto scroll to bottom of response log each time it is changed. + private void TextBox_TextChanged(object sender, TextChangedEventArgs e) + { + if (chkScroll.IsChecked.Value) + { + txtLog.SelectionStart = txtLog.Text.Length; + txtLog.ScrollToEnd(); + } + } + + private void txtLog_PreviewMouseUp(object sender, MouseButtonEventArgs e) + { + chkScroll.IsChecked = false; + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/Windows/TextInputWindow.xaml b/Software/Visual_Studio/Tango.Stubs/Windows/TextInputWindow.xaml new file mode 100644 index 000000000..f7668c1f1 --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Windows/TextInputWindow.xaml @@ -0,0 +1,25 @@ +<mahapps:MetroWindow x:Class="Tango.Stubs.Windows.TextInputWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:d="http://schemas.microsoft.com/expression/blend/2008" + xmlns:mahapps="http://metro.mahapps.com/winfx/xaml/controls" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:local="clr-namespace:Tango.Stubs.Windows" + mc:Ignorable="d" + Title="Tango Stubs Execution Utility" ResizeMode="NoResize" ShowInTaskbar="False" ShowIconOnTitleBar="False" TitlebarHeight="40" TitleCaps="False" BorderBrush="Gray" BorderThickness="1" Height="200" Width="500" WindowStartupLocation="CenterScreen" Background="#202020" Foreground="Gainsboro" DataContext="{Binding RelativeSource={RelativeSource Self}}"> + <Grid> + <Grid Margin="10"> + <Grid.RowDefinitions> + <RowDefinition Height="40*"/> + <RowDefinition Height="71*"/> + <RowDefinition Height="60"/> + </Grid.RowDefinitions> + + <TextBlock x:Name="lbMessage" VerticalAlignment="Center">The current operation requires you to provide some response in string format.</TextBlock> + + <TextBox x:Name="txtText" Grid.Row="1" Background="#151515" Foreground="Gainsboro" VerticalAlignment="Center" BorderBrush="DimGray"></TextBox> + + <Button Click="Button_Click" Grid.Row="2" HorizontalAlignment="Right" BorderThickness="0" Width="140" Height="35" VerticalAlignment="Bottom" IsDefault="True" mahapps:ButtonHelper.PreserveTextCase="True" Style="{StaticResource AccentedSquareButtonStyle}">OK</Button> + </Grid> + </Grid> +</mahapps:MetroWindow> diff --git a/Software/Visual_Studio/Tango.Stubs/Windows/TextInputWindow.xaml.cs b/Software/Visual_Studio/Tango.Stubs/Windows/TextInputWindow.xaml.cs new file mode 100644 index 000000000..cdc02917a --- /dev/null +++ b/Software/Visual_Studio/Tango.Stubs/Windows/TextInputWindow.xaml.cs @@ -0,0 +1,53 @@ +using MahApps.Metro.Controls; +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.Shapes; + +namespace Tango.Stubs.Windows +{ + /// <summary> + /// Interaction logic for TextInputWindow.xaml + /// </summary> + public partial class TextInputWindow : MetroWindow + { + public String Response { get; set; } + + public TextInputWindow() + { + InitializeComponent(); + this.Loaded += TextInputWindow_Loaded; + } + + private void TextInputWindow_Loaded(object sender, RoutedEventArgs e) + { + txtText.Focus(); + } + + public TextInputWindow(String message, String defaultResponse) : this() + { + txtText.Text = defaultResponse; + + if (message != null) + { + lbMessage.Text = message; + } + } + + private void Button_Click(object sender, RoutedEventArgs e) + { + Response = txtText.Text; + DialogResult = true; + Close(); + } + } +} diff --git a/Software/Visual_Studio/Tango.Stubs/app.config b/Software/Visual_Studio/Tango.Stubs/app.config index cacd4cd77..5d794b958 100644 --- a/Software/Visual_Studio/Tango.Stubs/app.config +++ b/Software/Visual_Studio/Tango.Stubs/app.config @@ -6,6 +6,46 @@ <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" /> </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" /> + </dependentAssembly> + <dependentAssembly> + <assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" /> + </dependentAssembly> </assemblyBinding> </runtime> </configuration>
\ No newline at end of file diff --git a/Software/Visual_Studio/Tango.Stubs/packages.config b/Software/Visual_Studio/Tango.Stubs/packages.config index c8a2e03ee..1e9950efc 100644 --- a/Software/Visual_Studio/Tango.Stubs/packages.config +++ b/Software/Visual_Studio/Tango.Stubs/packages.config @@ -1,6 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <packages> + <package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net46" /> <package id="Google.Protobuf" version="3.4.1" targetFramework="net46" /> + <package id="MahApps.Metro" version="1.5.0" targetFramework="net46" /> + <package id="Newtonsoft.Json" version="8.0.3" targetFramework="net46" /> <package id="System.Reactive" version="3.1.1" targetFramework="net46" /> <package id="System.Reactive.Core" version="3.1.1" targetFramework="net46" /> <package id="System.Reactive.Interfaces" version="3.1.1" targetFramework="net46" /> |
