diff options
| author | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-05-08 17:01:22 +0300 |
|---|---|---|
| committer | Roy Ben-Shabat <Roy@Twine-s.com> | 2018-05-08 17:01:22 +0300 |
| commit | 113eaf4d8a37e212b8528d41e400b346ce9f51d2 (patch) | |
| tree | 757df6c19de09061fad3b5a0b3954f0bbc98747b /Software/Visual_Studio | |
| parent | cdba3267d2a47b3bff8cf3ec0219223e36e234ff (diff) | |
| download | Tango-113eaf4d8a37e212b8528d41e400b346ce9f51d2.tar.gz Tango-113eaf4d8a37e212b8528d41e400b346ce9f51d2.zip | |
Added improvements to stubs UI.
Implemented Bug Reporter engine!
Diffstat (limited to 'Software/Visual_Studio')
26 files changed, 1274 insertions, 337 deletions
diff --git a/Software/Visual_Studio/Tango.Scripting/CompilerError.cs b/Software/Visual_Studio/Tango.Scripting/CompilerError.cs new file mode 100644 index 000000000..367aba123 --- /dev/null +++ b/Software/Visual_Studio/Tango.Scripting/CompilerError.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.Scripting +{ + public class CompilerError + { + public String Error { get; set; } + + public override string ToString() + { + return Error; + } + } +} diff --git a/Software/Visual_Studio/Tango.Scripting/ScriptEngine.cs b/Software/Visual_Studio/Tango.Scripting/ScriptEngine.cs index d6f12967c..a8815406d 100644 --- a/Software/Visual_Studio/Tango.Scripting/ScriptEngine.cs +++ b/Software/Visual_Studio/Tango.Scripting/ScriptEngine.cs @@ -38,15 +38,51 @@ namespace Tango.Scripting /// <returns></returns> public async Task Run(String code) { + var options = CreateOptions(); + + String methodParameters = CreateMethodParameters(); + + _cancaller = new CancellationTokenSource(); + + await CSharpScript.RunAsync( + code + + Environment.NewLine + + Environment.NewLine + + "await Task.Factory.StartNew(() => { OnExecute(" + methodParameters + "); });", options: options, globals: _onExecuteParameters, cancellationToken: _cancaller.Token); + } + + public Task<List<CompilerError>> Compile(String code) + { + return Task.Factory.StartNew<List<CompilerError>>(() => + { + var options = CreateOptions(); + + String methodParameters = CreateMethodParameters(); + + _cancaller = new CancellationTokenSource(); + + var script = CSharpScript.Create( + code + + Environment.NewLine + + Environment.NewLine + + "await Task.Factory.StartNew(() => { OnExecute(" + methodParameters + "); });", options: options, globalsType: _onExecuteParameters.GetType()); + + var results = script.Compile(); + + return results.ToList().Select(x => new CompilerError() { Error = x.ToString() }).ToList(); + }); + } + + private String CreateMethodParameters() + { + return String.Join(", ", _onExecuteParameters.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name)); + } + + private ScriptOptions CreateOptions() + { //My References. var options = ScriptOptions.Default; - //External References. - //foreach (var r in item.References) - //{ - // options = options.AddReferences(r.FilePath); - //} - //My Assemblies. options = options.AddReferences(typeof(Form).Assembly.Location); options = options.AddReferences(typeof(Enumerable).Assembly.Location); @@ -67,14 +103,7 @@ namespace Tango.Scripting "System.Windows.Forms" ); - String methodParameters = String.Join(", ", _onExecuteParameters.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name)); - - _cancaller = new CancellationTokenSource(); - await CSharpScript.RunAsync( - code + - Environment.NewLine + - Environment.NewLine + - "await Task.Factory.StartNew(() => { OnExecute(" + methodParameters + "); });", options: options, globals: _onExecuteParameters, cancellationToken: _cancaller.Token); + return options; } /// <summary> diff --git a/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj b/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj index 1a6e660bd..f9842aeff 100644 --- a/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj +++ b/Software/Visual_Studio/Tango.Scripting/Tango.Scripting.csproj @@ -140,6 +140,7 @@ <Compile Include="..\Versioning\GlobalVersionInfo.cs"> <Link>GlobalVersionInfo.cs</Link> </Compile> + <Compile Include="CompilerError.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="ScriptEngine.cs" /> <Compile Include="OnExecuteParameters.cs" /> diff --git a/Software/Visual_Studio/Tango.SharedUI/Controls/ScriptEditorControl.xaml b/Software/Visual_Studio/Tango.SharedUI/Controls/ScriptEditorControl.xaml index 52f5a030f..817297191 100644 --- a/Software/Visual_Studio/Tango.SharedUI/Controls/ScriptEditorControl.xaml +++ b/Software/Visual_Studio/Tango.SharedUI/Controls/ScriptEditorControl.xaml @@ -81,6 +81,31 @@ FontSize="10pt" SyntaxHighlighting="C#" ShowLineNumbers="True"> + <avalonEdit:TextEditor.ContextMenu> + <ContextMenu> + <ContextMenu.Resources> + <Style TargetType="MenuItem" BasedOn="{StaticResource {x:Type MenuItem}}"> + <Setter Property="Foreground" Value="Gainsboro"></Setter> + </Style> + </ContextMenu.Resources> + <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> + </ContextMenu> + </avalonEdit:TextEditor.ContextMenu> </avalonEdit:TextEditor> </Border> </Grid> diff --git a/Software/Visual_Studio/Tango.TFS/Email.cs b/Software/Visual_Studio/Tango.TFS/Email.cs new file mode 100644 index 000000000..8e87a5f02 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/Email.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + /// <summary> + /// Represents a simple email. + /// </summary> + public class Email + { + /// <summary> + /// Gets or sets the subject. + /// </summary> + public String Subject { get; set; } + + /// <summary> + /// Gets or sets the body. + /// </summary> + public String Body { get; set; } + + /// <summary> + /// Gets or sets the sender member. + /// </summary> + public TeamMember From { get; set; } + + /// <summary> + /// Gets or sets the recipient members. + /// </summary> + public List<TeamMember> To { get; set; } + + /// <summary> + /// Gets or sets the optional attachments. + /// </summary> + public List<Attachment> Attachments { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="Email"/> class. + /// </summary> + public Email() + { + To = new List<TeamMember>(); + Attachments = new List<Attachment>(); + } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/ITeamFoundationEmailClient.cs b/Software/Visual_Studio/Tango.TFS/ITeamFoundationEmailClient.cs new file mode 100644 index 000000000..080d9fa93 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/ITeamFoundationEmailClient.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + /// <summary> + /// Represents an email client for sending emails to team members. + /// </summary> + public interface ITeamFoundationEmailClient + { + /// <summary> + /// Gets or sets the SMTP address. + /// </summary> + String SMTP { get; set; } + + /// <summary> + /// Gets or sets the SMTP port. + /// </summary> + int Port { get; set; } + + /// <summary> + /// Gets or sets the credentials used to authenticate against the SMTP server. + /// </summary> + NetworkCredential Credentials { get; set; } + + /// <summary> + /// Sends the specified email. + /// </summary> + /// <param name="email">The email.</param> + /// <returns></returns> + Task Send(Email email); + } +} diff --git a/Software/Visual_Studio/Tango.TFS/ITeamFoundationServiceClient.cs b/Software/Visual_Studio/Tango.TFS/ITeamFoundationServiceClient.cs index 1fe169218..ea6ed4a1e 100644 --- a/Software/Visual_Studio/Tango.TFS/ITeamFoundationServiceClient.cs +++ b/Software/Visual_Studio/Tango.TFS/ITeamFoundationServiceClient.cs @@ -35,6 +35,21 @@ namespace Tango.TFS Task<WorkItem> GetWorkItem(Project project, int id); /// <summary> + /// Gets all work items of the specified type + /// </summary> + /// <param name="project">The project.</param> + /// <param name="type">Work item type.</param> + /// <returns></returns> + Task<List<WorkItem>> GetWorkItemsByType(Project project, WorkItemType type); + + /// <summary> + /// Gets all work items of the specified project. + /// </summary> + /// <param name="project">The project.</param> + /// <returns></returns> + Task<List<WorkItem>> GetAllWorkItems(Project project); + + /// <summary> /// Gets all the work items created by the specified team member. /// </summary> /// <param name="project">The project.</param> diff --git a/Software/Visual_Studio/Tango.TFS/ResolvedReason.cs b/Software/Visual_Studio/Tango.TFS/ResolvedReason.cs index e1af689a2..bdd1bf797 100644 --- a/Software/Visual_Studio/Tango.TFS/ResolvedReason.cs +++ b/Software/Visual_Studio/Tango.TFS/ResolvedReason.cs @@ -21,6 +21,8 @@ namespace Tango.TFS Duplicate, [Description("Fixed")] Fixed, + [Description("Fixed and verified")] + FixedAndVerified, [Description("Obsolete")] Obsolete, } diff --git a/Software/Visual_Studio/Tango.TFS/Tango.TFS.csproj b/Software/Visual_Studio/Tango.TFS/Tango.TFS.csproj index cf15c2e9e..554636eba 100644 --- a/Software/Visual_Studio/Tango.TFS/Tango.TFS.csproj +++ b/Software/Visual_Studio/Tango.TFS/Tango.TFS.csproj @@ -201,6 +201,8 @@ </Compile> <Compile Include="Area.cs" /> <Compile Include="Attachment.cs" /> + <Compile Include="Email.cs" /> + <Compile Include="ITeamFoundationEmailClient.cs" /> <Compile Include="Iteration.cs" /> <Compile Include="Priority.cs" /> <Compile Include="Project.cs" /> @@ -208,6 +210,7 @@ <Compile Include="Severity.cs" /> <Compile Include="State.cs" /> <Compile Include="Tag.cs" /> + <Compile Include="TeamFoundationEmailClient.cs" /> <Compile Include="TeamFoundationServiceClient.cs" /> <Compile Include="TeamMember.cs" /> <Compile Include="WorkItem.cs" /> diff --git a/Software/Visual_Studio/Tango.TFS/TeamFoundationEmailClient.cs b/Software/Visual_Studio/Tango.TFS/TeamFoundationEmailClient.cs new file mode 100644 index 000000000..ac77cf470 --- /dev/null +++ b/Software/Visual_Studio/Tango.TFS/TeamFoundationEmailClient.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Mail; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.TFS +{ + /// <summary> + /// Represents an email client for sending emails to team members. + /// </summary> + /// <seealso cref="Tango.TFS.ITeamFoundationEmailClient" /> + public class TeamFoundationEmailClient : ITeamFoundationEmailClient + { + /// <summary> + /// Gets or sets the SMTP address. + /// </summary> + public String SMTP { get; set; } + + /// <summary> + /// Gets or sets the SMTP port. + /// </summary> + public int Port { get; set; } + + /// <summary> + /// Gets or sets the credentials used to authenticate against the SMTP server. + /// </summary> + public NetworkCredential Credentials { get; set; } + + /// <summary> + /// Initializes a new instance of the <see cref="TeamFoundationEmailClient"/> class. + /// </summary> + public TeamFoundationEmailClient() + { + SMTP = "smtp-mail.outlook.com"; + Port = 587; + } + + /// <summary> + /// Initializes a new instance of the <see cref="TeamFoundationEmailClient"/> class. + /// </summary> + /// <param name="credentials">The credentials.</param> + public TeamFoundationEmailClient(NetworkCredential credentials) : this() + { + Credentials = credentials; + } + + /// <summary> + /// Initializes a new instance of the <see cref="TeamFoundationEmailClient"/> class. + /// </summary> + /// <param name="smtp">The SMTP.</param> + /// <param name="port">The port.</param> + /// <param name="credentials">The credentials.</param> + public TeamFoundationEmailClient(String smtp, int port, NetworkCredential credentials) : this(credentials) + { + SMTP = smtp; + Port = port; + } + + /// <summary> + /// Sends the specified email. + /// </summary> + /// <param name="email">The email.</param> + /// <returns></returns> + public Task Send(Email email) + { + return Task.Factory.StartNew(() => + { + SmtpClient client = new SmtpClient(SMTP); + + client.Port = Port; + client.DeliveryMethod = SmtpDeliveryMethod.Network; + client.UseDefaultCredentials = false; + NetworkCredential credentials = Credentials; + client.EnableSsl = true; + client.Credentials = credentials; + + var mail = new MailMessage(); + mail.From = new MailAddress(email.From.Email); + + foreach (var member in email.To) + { + mail.To.Add(new MailAddress(member.Email)); + } + + foreach (var file in email.Attachments) + { + mail.Attachments.Add(new System.Net.Mail.Attachment(new FileStream(file.FilePath, FileMode.Open), file.Name)); + } + + mail.Subject = email.Subject; + mail.Body = email.Body; + client.Send(mail); + }); + } + } +} diff --git a/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs b/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs index 6eef1ef92..5665caf3c 100644 --- a/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs +++ b/Software/Visual_Studio/Tango.TFS/TeamFoundationServiceClient.cs @@ -395,6 +395,61 @@ namespace Tango.TFS } /// <summary> + /// Gets the type of the work items by. + /// </summary> + /// <param name="project">The project.</param> + /// <param name="type">The type.</param> + /// <returns></returns> + public Task<List<WorkItem>> GetWorkItemsByType(Project project, WorkItemType type) + { + return Task.Factory.StartNew<List<WorkItem>>(() => + { + var connection = CreateConnection(); + + var projCollection = new TfsTeamProjectCollection(new Uri(CollectionURL), connection.Credentials); + var store = projCollection.GetService<WorkItemStore>(); + + WorkItemCollection queryResults = store.Query(String.Format("Select [Id]" + "From WorkItems " + "Where [Work Item Type] = '{0}'", type.ToString())); + var ids = queryResults.OfType<Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem>().Where(x => x.Project.Name == project.Name).ToList().Select(x => x.Id).ToList(); + + if (ids.Count == 0) return new List<WorkItem>(); + + WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>(); + + var items = witClient.GetWorkItemsAsync(ids).Result; + + return items.Select(x => ConvertToWorkItem(project, x)).ToList(); + }); + } + + /// <summary> + /// Gets all work items of the specified project. + /// </summary> + /// <param name="project">The project.</param> + /// <returns></returns> + public Task<List<WorkItem>> GetAllWorkItems(Project project) + { + return Task.Factory.StartNew<List<WorkItem>>(() => + { + var connection = CreateConnection(); + + var projCollection = new TfsTeamProjectCollection(new Uri(CollectionURL), connection.Credentials); + var store = projCollection.GetService<WorkItemStore>(); + + WorkItemCollection queryResults = store.Query("Select [Id]" + "From WorkItems " + "Where [Work Item Type] = 'Bug' Or [Work Item Type] = 'Task'"); + var ids = queryResults.OfType<Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem>().Where(x => x.Project.Name == project.Name).ToList().Select(x => x.Id).ToList(); + + if (ids.Count == 0) return new List<WorkItem>(); + + WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>(); + + var items = witClient.GetWorkItemsAsync(ids).Result; + + return items.Select(x => ConvertToWorkItem(project, x)).ToList(); + }); + } + + /// <summary> /// Deletes the specified work item. /// </summary> /// <param name="project">The project.</param> @@ -667,13 +722,22 @@ namespace Tango.TFS workItem.State = (State)Enum.Parse(typeof(State), item.Fields[GetFieldNameForRead(CoreField.State)].ToString()); - workItem.Severity = ParseEnumByDescription<Severity>(item.Fields[ExtensionFields.SEVERITY].ToString()); + if (item.Fields.ContainsKey(ExtensionFields.SEVERITY)) + { + workItem.Severity = ParseEnumByDescription<Severity>(item.Fields[ExtensionFields.SEVERITY].ToString()); + } workItem.Priority = (Priority)int.Parse(item.Fields[ExtensionFields.PRIORITY].ToString()); - workItem.StepsToReproduce = TryGetField(item.Fields, ExtensionFields.STEPS_TO_REP).ToString(); + if (item.Fields.ContainsKey(ExtensionFields.STEPS_TO_REP)) + { + workItem.StepsToReproduce = TryGetField(item.Fields, ExtensionFields.STEPS_TO_REP).ToString(); + } - workItem.SystemInformation = TryGetField(item.Fields, ExtensionFields.SYSTEM_INFO).ToString(); + if (item.Fields.ContainsKey(ExtensionFields.SYSTEM_INFO)) + { + workItem.SystemInformation = TryGetField(item.Fields, ExtensionFields.SYSTEM_INFO).ToString(); + } workItem.Comment = TryGetField(item.Fields, GetFieldNameForRead(CoreField.History)).ToString(); diff --git a/Software/Visual_Studio/Tango.TFS/TeamMember.cs b/Software/Visual_Studio/Tango.TFS/TeamMember.cs index 747d550ca..bb4b8a21f 100644 --- a/Software/Visual_Studio/Tango.TFS/TeamMember.cs +++ b/Software/Visual_Studio/Tango.TFS/TeamMember.cs @@ -14,6 +14,11 @@ namespace Tango.TFS public String URL { get; set; } public String ImageURL { get; set; } + public String Email + { + get { return UniqueName; } + } + public String AssignName { get { return String.Format("{0} <{1}>", DisplayName, UniqueName); } diff --git a/Software/Visual_Studio/Tango.UnitTesting/Outlook_TST.cs b/Software/Visual_Studio/Tango.UnitTesting/Outlook_TST.cs index b34db8578..57a22dbd9 100644 --- a/Software/Visual_Studio/Tango.UnitTesting/Outlook_TST.cs +++ b/Software/Visual_Studio/Tango.UnitTesting/Outlook_TST.cs @@ -2,7 +2,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Net.Mail; using System.Text; using System.Threading.Tasks; using Outlook = Microsoft.Office.Interop.Outlook; @@ -14,7 +16,7 @@ namespace Tango.UnitTesting public class Outlook_TST { [TestMethod] - public void Send_Email_With_Logs() + public void Send_Email_With_Logs_Using_Outlook() { Application app = new Application(); MailItem email = (MailItem)app.CreateItem(OlItemType.olMailItem); @@ -31,5 +33,34 @@ namespace Tango.UnitTesting email.Importance = OlImportance.olImportanceNormal; email.Send(); } + + [TestMethod] + public void Send_Email_With_Logs_With_Outlook_SMTP() + { + String sender = "roy@twine-s.com"; + String recipient = "roy@twine-s.com"; + + SmtpClient client = new SmtpClient("smtp-mail.outlook.com"); + + client.Port = 587; + client.DeliveryMethod = SmtpDeliveryMethod.Network; + client.UseDefaultCredentials = false; + System.Net.NetworkCredential credentials = new System.Net.NetworkCredential(sender, "Maya2018"); + client.EnableSsl = true; + client.Credentials = credentials; + + try + { + var mail = new MailMessage(sender.Trim(), recipient.Trim()); + mail.Attachments.Add(new System.Net.Mail.Attachment(new FileStream("D:\\C#.txt", FileMode.Open), "C# Code")); + mail.Subject = "Test Email"; + mail.Body = "This is a test."; + client.Send(mail); + } + catch (System.Exception ex) + { + throw ex; + } + } } } diff --git a/Software/Visual_Studio/Tango.sln b/Software/Visual_Studio/Tango.sln index d845eb0ab..180c9ae10 100644 --- a/Software/Visual_Studio/Tango.sln +++ b/Software/Visual_Studio/Tango.sln @@ -167,6 +167,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.Documents", "Tango.Do EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.TFS", "Tango.TFS\Tango.TFS.csproj", "{998F8471-DC1B-41B6-9D96-354E1B4E7A32}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tango.BugReporter", "Utilities\Tango.BugReporter\Tango.BugReporter.csproj", "{C8F14D59-B18D-469C-8B1B-2D23072ED16A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -2226,6 +2228,36 @@ Global {998F8471-DC1B-41B6-9D96-354E1B4E7A32}.Release|x64.Build.0 = Release|Any CPU {998F8471-DC1B-41B6-9D96-354E1B4E7A32}.Release|x86.ActiveCfg = Release|Any CPU {998F8471-DC1B-41B6-9D96-354E1B4E7A32}.Release|x86.Build.0 = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|ARM.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|ARM64.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|ARM64.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|x64.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|x64.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|x86.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Debug|x86.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|Any CPU.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|Any CPU.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|ARM.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|ARM.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|ARM64.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|ARM64.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|x64.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|x64.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|x86.ActiveCfg = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.DefaultBuild|x86.Build.0 = Debug|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|Any CPU.Build.0 = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|ARM.ActiveCfg = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|ARM.Build.0 = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|ARM64.ActiveCfg = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|ARM64.Build.0 = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|x64.ActiveCfg = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|x64.Build.0 = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|x86.ActiveCfg = Release|Any CPU + {C8F14D59-B18D-469C-8B1B-2D23072ED16A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -2275,6 +2307,7 @@ Global {88028F14-0028-4DED-B119-19B8EE23CF32} = {B2AF4F3F-2828-47C3-8F3E-A0EA0BD66FF8} {1674F726-0E66-414F-B9FD-C6F20D7F07C7} = {B2AF4F3F-2828-47C3-8F3E-A0EA0BD66FF8} {12CC222B-D0F5-4048-B790-D283235F540D} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} + {C8F14D59-B18D-469C-8B1B-2D23072ED16A} = {5F6BBAA8-EAD0-4B18-97E5-55B4F56DD760} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7986F7F4-A86A-4994-B1B6-0988D7F057B6} diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/App.config b/Software/Visual_Studio/Utilities/Tango.BugReporter/App.config new file mode 100644 index 000000000..b93a07aa7 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/App.config @@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<configuration> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" /> + </startup> + <runtime> + <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> + <dependentAssembly> + <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" /> + <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" /> + </dependentAssembly> + </assemblyBinding> + </runtime> +</configuration>
\ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/Program.cs b/Software/Visual_Studio/Utilities/Tango.BugReporter/Program.cs new file mode 100644 index 000000000..b9b1897b1 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/Program.cs @@ -0,0 +1,258 @@ +using MigraDoc.DocumentObjectModel; +using MigraDoc.DocumentObjectModel.Shapes.Charts; +using MigraDoc.DocumentObjectModel.Tables; +using MigraDoc.Rendering; +using PdfSharp.Drawing; +using PdfSharp.Pdf; +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Tango.Core.Helpers; +using Tango.TFS; + +namespace Tango.BugReporter +{ + class Program + { + private static List<Color> _colors = new List<Color>() + { + Colors.Crimson, + Colors.Coral, + Colors.Khaki, + Colors.Wheat, + Colors.PaleGreen, + Colors.PaleTurquoise, + Colors.CadetBlue, + Colors.Lavender, + Colors.SlateBlue, + Colors.LightSteelBlue, + Colors.PowderBlue, + Colors.Silver, + Colors.SlateGray, + }; + + static void Main(string[] args) + { + String startPath = AssemblyHelper.GetCurrentAssemblyFolder(); + + ITeamFoundationServiceClient tfs = new TeamFoundationServiceClient("https://twinetfs.visualstudio.com/DefaultCollection", String.Empty, "szzfokrceo4rhd4eqi5qpmxn3pa5iwl3q7tlqd36l2m7smz2ynoa"); + var project = tfs.GetProject("Tango").Result; + + var allItems = tfs.GetAllWorkItems(project).Result.OrderByDescending(x => x.Type).OrderBy(x => x.Severity).ToList(); + var activeItems = allItems.Where(x => x.State == State.Active || x.State == State.New).ToList(); + var resolvedItems = allItems.Where(x => x.State == State.Resolved).ToList(); + + Document document = new Document(); + document.Info.Title = "Tango Bug Report"; + document.Info.Author = "Twine Solutions LTD"; + + document.DefaultPageSetup.TopMargin = 5; + document.DefaultPageSetup.RightMargin = 5; + document.DefaultPageSetup.LeftMargin = 5; + + Style style = document.Styles["Normal"]; + style.Font.Size = 7; + + var section = document.AddSection(); + section.PageSetup.PageFormat = PageFormat.A4; + + + + var headParagraph = section.AddParagraph(); + headParagraph.Format.Alignment = ParagraphAlignment.Left; + headParagraph.Format.Font.Size = 16; + headParagraph.Format.Font.Bold = true; + headParagraph.Format.SpaceBefore = "8mm"; + headParagraph.Format.SpaceAfter = "5mm"; + headParagraph.Format.RightIndent = "5mm"; + headParagraph.Format.Font.Color = Colors.DimGray; + + var img = headParagraph.AddImage(Path.Combine(startPath, "twine-logo.jpg")); + headParagraph.AddSpace(5); + var t = headParagraph.AddText(" Twine Solutions VSTS Report"); + + var pp = section.AddParagraph(String.Format("This report was generated on {0}. Below you can find a daily summery of the Tango project, work items state and urgency.", DateTime.Now.ToShortDateString())); + pp.Format.LeftIndent = "2cm"; + + AddTable(section, "All Active Items", activeItems); + + section.AddPageBreak(); + + AddTable(section, "Created Today", activeItems.Where(x => x.CreatedDate.Date == DateTime.Now.Date)); + + section.AddPageBreak(); + + AddTable(section, "Resolved Today", resolvedItems.Where(x => x.ResolvedDate.Date == DateTime.Now.Date)); + + section.AddPageBreak(); + + AddChart(section, ChartType.Column2D, "Items Per Member", activeItems.GroupBy(x => x.AssignedTo), nameof(TeamMember.DisplayName)); + + section.AddPageBreak(); + + AddChart(section, ChartType.Bar2D, "Items Per Area", activeItems.GroupBy(x => x.Area.Name), null); + + section.AddPageBreak(); + + foreach (var g in activeItems.GroupBy(x => x.Area.Name)) + { + AddTable(section, g.Key + " Items", g); + + section.AddPageBreak(); + } + + var group = activeItems.GroupBy(x => x.AssignedTo); + + var file = PathHelper.GetTempFilePath(); + + PdfDocumentRenderer pdfRenderer = new PdfDocumentRenderer(false, PdfFontEmbedding.None); + pdfRenderer.Document = document; + pdfRenderer.RenderDocument(); + pdfRenderer.PdfDocument.Save(file); + + ITeamFoundationEmailClient emailClient = new TeamFoundationEmailClient(new System.Net.NetworkCredential("roy@twine-s.com", "Maya2018")); + + Email mail = new Email(); + mail.Attachments.Add(new Attachment() { FilePath = file, Name = "VSTS-REPORT.pdf" }); + mail.From = project.Members.SingleOrDefault(x => x.DisplayName.Contains("Roy")); + mail.To.Add(mail.From); + mail.Subject = "VSTS Daily Report"; + mail.Body = "Attached is a daily report containing Tango project work items."; + + emailClient.Send(mail).Wait(); + + PathHelper.TryDeleteFile(file); + } + + private static Chart AddChart<T>(Section section, ChartType chartType, String header, IEnumerable<IGrouping<T, WorkItem>> workItemGroups, String propName) + { + var headParagraph = section.AddParagraph(header); + headParagraph.Format.Alignment = ParagraphAlignment.Left; + headParagraph.Format.Font.Size = 16; + headParagraph.Format.Font.Bold = true; + headParagraph.Format.SpaceBefore = "8mm"; + headParagraph.Format.SpaceAfter = "5mm"; + + Chart chart = section.AddChart(chartType); + chart.Width = section.Document.DefaultPageSetup.PageWidth - 5; + chart.Height = "10cm"; + + workItemGroups = workItemGroups.OrderByDescending(x => x.Count()); + + Series series = chart.SeriesCollection.AddSeries(); + series.Add(workItemGroups.Select(x => (double)x.Count()).ToArray()); + + XSeries xseries = chart.XValues.AddXSeries(); + + if (propName != null) + { + xseries.Add(workItemGroups.Select(x => x.Key.GetType().GetProperty(propName, BindingFlags.Public | BindingFlags.Instance).GetValue(x.Key).ToString()).ToArray()); + } + else + { + xseries.Add(workItemGroups.Select(x => x.Key.ToString()).ToArray()); + } + + var elements = series.Elements.Cast<Point>().ToArray(); + + for (int i = 0; i < elements.Length; i++) + { + elements[i].FillFormat.Color = _colors[i]; + } + + chart.XAxis.MajorTickMark = TickMarkType.Outside; + chart.XAxis.Title.Caption = propName; + chart.YAxis.MajorTickMark = TickMarkType.Outside; + chart.YAxis.HasMajorGridlines = true; + chart.PlotArea.LineFormat.Color = Colors.White; + chart.PlotArea.LineFormat.Width = 1; + chart.PlotArea.LineFormat.Visible = true; + return chart; + } + + private static Table AddTable(Section section, String header, IEnumerable<WorkItem> workItems) + { + String startPath = AssemblyHelper.GetCurrentAssemblyFolder(); + + var headParagraph = section.AddParagraph(header); + headParagraph.Format.Alignment = ParagraphAlignment.Left; + headParagraph.Format.Font.Size = 16; + headParagraph.Format.Font.Bold = true; + headParagraph.Format.SpaceBefore = "8mm"; + headParagraph.Format.SpaceAfter = "5mm"; + + + var table = section.AddTable(); + + table.Borders.Color = Colors.Black; + table.Borders.Width = 0.25; + table.Borders.Left.Width = 0.5; + table.Borders.Right.Width = 0.5; + table.Rows.LeftIndent = 0; + + table.BottomPadding = "2mm"; + table.TopPadding = "2mm"; + table.LeftPadding = "2mm"; + table.RightPadding = "2mm"; + + + // Before you can add a row, you must define the columns + table.AddColumn("1cm"); + table.AddColumn(); + table.AddColumn("4cm"); + table.AddColumn(); + table.AddColumn(); + table.AddColumn(); + table.AddColumn("1.5cm"); + table.AddColumn("1.5cm"); + table.AddColumn("1.5cm"); + + // Create the header of the table + Row row = table.AddRow(); + row.HeadingFormat = true; + row.Shading.Color = Colors.Gainsboro; + row.Cells[0].AddParagraph("Work Item"); + row.Cells[1].AddParagraph("Created Date"); + row.Cells[2].AddParagraph("Title"); + row.Cells[3].AddParagraph("Area"); + row.Cells[4].AddParagraph("Created By"); + row.Cells[5].AddParagraph("Assigned To"); + row.Cells[6].AddParagraph("Severity"); + row.Cells[7].AddParagraph("Priority"); + row.Cells[8].AddParagraph("State"); + + foreach (var item in workItems) + { + Row r = table.AddRow(); + var image = r.Cells[0].AddImage(Path.Combine(startPath, item.Type == WorkItemType.Bug ? "bug.png" : "task.png")); + image.Width = 15; + image.Height = 15; + r.Cells[1].AddParagraph(item.CreatedDate.ToShortDateString()); + + var linkParagraph = r.Cells[2].AddParagraph(); + var link = linkParagraph.AddHyperlink(String.Format("https://twinetfs.visualstudio.com/DefaultCollection/Tango/_queries?id={0}&_a=edit", item.ID), HyperlinkType.Web); + link.AddFormattedText(item.Title); + + r.Cells[3].AddParagraph(item.Area.Name); + r.Cells[4].AddParagraph(item.CreatedBy.DisplayName); + r.Cells[5].AddParagraph(item.AssignedTo.DisplayName); + var p = r.Cells[6].AddParagraph(item.Severity.ToString()); + + if (item.Severity == Severity.Critical || item.Severity == Severity.High) + { + p.Format.Font.Color = Colors.Red; + } + + r.Cells[7].AddParagraph(item.Priority.ToDescription()); + r.Cells[8].AddParagraph(item.State.ToString()); + } + + return table; + } + } +} diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/Properties/AssemblyInfo.cs b/Software/Visual_Studio/Utilities/Tango.BugReporter/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..0d86baa04 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Tango.BugReporter")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Tango.BugReporter")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("c8f14d59-b18d-469c-8b1b-2d23072ed16a")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/Tango.BugReporter.csproj b/Software/Visual_Studio/Utilities/Tango.BugReporter/Tango.BugReporter.csproj new file mode 100644 index 000000000..e0450c4bf --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/Tango.BugReporter.csproj @@ -0,0 +1,90 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{C8F14D59-B18D-469C-8B1B-2D23072ED16A}</ProjectGuid> + <OutputType>Exe</OutputType> + <RootNamespace>Tango.BugReporter</RootNamespace> + <AssemblyName>Tango.BugReporter</AssemblyName> + <TargetFrameworkVersion>v4.6</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> + <PlatformTarget>AnyCPU</PlatformTarget> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <Reference Include="MigraDoc.DocumentObjectModel, Version=1.32.4334.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\MigraDoc.DocumentObjectModel.dll</HintPath> + </Reference> + <Reference Include="MigraDoc.Rendering, Version=1.32.4334.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\MigraDoc.Rendering.dll</HintPath> + </Reference> + <Reference Include="MigraDoc.RtfRendering, Version=1.32.4334.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\MigraDoc.RtfRendering.dll</HintPath> + </Reference> + <Reference Include="PdfSharp, Version=1.32.3057.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\PdfSharp.dll</HintPath> + </Reference> + <Reference Include="PdfSharp.Charting, Version=1.32.3057.0, Culture=neutral, PublicKeyToken=f94615aa0424f9eb, processorArchitecture=MSIL"> + <HintPath>..\..\packages\PDFsharp-MigraDoc-GDI.1.32.4334.0\lib\net20\PdfSharp.Charting.dll</HintPath> + </Reference> + <Reference Include="System" /> + <Reference Include="System.Core" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Data" /> + <Reference Include="System.Net.Http" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="App.config" /> + <None Include="packages.config" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj"> + <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project> + <Name>Tango.Core</Name> + </ProjectReference> + <ProjectReference Include="..\..\Tango.TFS\Tango.TFS.csproj"> + <Project>{998f8471-dc1b-41b6-9d96-354e1b4e7a32}</Project> + <Name>Tango.TFS</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Content Include="bug.png"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Include="task.png"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + <Content Include="twine-logo.jpg"> + <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> + </Content> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> +</Project>
\ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/bug.png b/Software/Visual_Studio/Utilities/Tango.BugReporter/bug.png Binary files differnew file mode 100644 index 000000000..5565739f6 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/bug.png diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/packages.config b/Software/Visual_Studio/Utilities/Tango.BugReporter/packages.config new file mode 100644 index 000000000..8181da7e7 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/packages.config @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<packages> + <package id="PDFsharp" version="1.32.3057.0" targetFramework="net46" /> + <package id="PDFsharp-MigraDoc-GDI" version="1.32.4334.0" targetFramework="net46" /> +</packages>
\ No newline at end of file diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/task.png b/Software/Visual_Studio/Utilities/Tango.BugReporter/task.png Binary files differnew file mode 100644 index 000000000..ec611d786 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/task.png diff --git a/Software/Visual_Studio/Utilities/Tango.BugReporter/twine-logo.jpg b/Software/Visual_Studio/Utilities/Tango.BugReporter/twine-logo.jpg Binary files differnew file mode 100644 index 000000000..56d8702c5 --- /dev/null +++ b/Software/Visual_Studio/Utilities/Tango.BugReporter/twine-logo.jpg diff --git a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Resources/CodeTabTemplate.cs b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Resources/CodeTabTemplate.cs index 2a721184b..bce014952 100644 --- a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Resources/CodeTabTemplate.cs +++ b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Resources/CodeTabTemplate.cs @@ -14,12 +14,15 @@ public void OnExecute(StubManager stubManager) { for (int i = 0; i < 10; i++) { - var response = stubManager.Run<CalculateResponse>("calculate", 10, 5); - - if (response.Sum == 15) + 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/Utilities/Tango.Stubs.UI/ViewModels/CodeTabVM.cs b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/ViewModels/CodeTabVM.cs index 6a8d9d370..a56ad7aca 100644 --- a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/ViewModels/CodeTabVM.cs +++ b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/ViewModels/CodeTabVM.cs @@ -1,10 +1,12 @@ 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.UI.ViewModels @@ -77,6 +79,16 @@ namespace Tango.Stubs.UI.ViewModels 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> @@ -84,6 +96,7 @@ namespace Tango.Stubs.UI.ViewModels { Title = "untitled"; Code = Properties.Resources.CodeTabTemplate; + Errors = new ObservableCollection<CompilerError>(); } /// <summary> diff --git a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/ViewModels/MainViewVM.cs index 6c038eadf..c25a92495 100644 --- a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/ViewModels/MainViewVM.cs @@ -162,6 +162,11 @@ namespace Tango.Stubs.UI.ViewModels 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; } @@ -220,7 +225,6 @@ namespace Tango.Stubs.UI.ViewModels /// Gets or sets the create example command. /// </summary> public RelayCommand<ExampleVM> CreateExampleCommand { get; set; } - #endregion #region Constructors @@ -235,6 +239,7 @@ namespace Tango.Stubs.UI.ViewModels 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); @@ -472,7 +477,7 @@ namespace Tango.Stubs.UI.ViewModels /// <summary> /// Saves the selected script file. /// </summary> - private void SaveFile() + private async void SaveFile() { if (SelectedCodeTab != null) { @@ -482,7 +487,10 @@ namespace Tango.Stubs.UI.ViewModels } else { + Status = "Saving " + SelectedCodeTab.File + "..."; File.WriteAllText(SelectedCodeTab.File, SelectedCodeTab.Code); + await Task.Delay(1000); + Status = "Ready"; } } } @@ -490,7 +498,7 @@ namespace Tango.Stubs.UI.ViewModels /// <summary> /// Saves the selected script file. /// </summary> - private void SaveAsFile() + private async void SaveAsFile() { if (SelectedCodeTab != null) { @@ -499,8 +507,11 @@ namespace Tango.Stubs.UI.ViewModels 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"; } } } @@ -576,6 +587,10 @@ namespace Tango.Stubs.UI.ViewModels /// </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; @@ -623,6 +638,45 @@ namespace Tango.Stubs.UI.ViewModels } /// <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).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() @@ -711,10 +765,10 @@ namespace Tango.Stubs.UI.ViewModels { InvokeUI(() => { - if (_logTextBox.Text.Length > 99999) - { - _logTextBox.Clear(); - } + if (_logTextBox.Text.Length > 99999) + { + _logTextBox.Clear(); + } _logTextBox.AppendText(log); }); } diff --git a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Views/MainView.xaml b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Views/MainView.xaml index 82c1b8e00..bc1ebc403 100644 --- a/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Views/MainView.xaml +++ b/Software/Visual_Studio/Utilities/Tango.Stubs.UI/Views/MainView.xaml @@ -15,330 +15,383 @@ mc:Ignorable="d" d:DesignHeight="720" d:DesignWidth="1280"> - <UserControl.Resources> + <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> - <ObjectDataProvider x:Key="baudRates" MethodName="GetValues" + <UserControl.Resources> + + <ObjectDataProvider x:Key="baudRates" MethodName="GetValues" ObjectType="{x:Type System:Enum}"> - <ObjectDataProvider.MethodParameters> - <x:Type TypeName="transport:UsbSerialBaudRates"/> - </ObjectDataProvider.MethodParameters> - </ObjectDataProvider> + <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"> - <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> - </DataTemplate> - </Setter.Value> - </Setter> - </Style> - </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> + <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> - <Menu IsMainMenu="True" BorderThickness="0"> - <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}"> - <MenuItem.Icon> - <fa:ImageAwesome Icon="Save" Width="12" Foreground="Gainsboro" Margin="2" /> - </MenuItem.Icon> - </MenuItem> - <MenuItem Header="Save as" Command="{Binding SaveAsCommand}"> - <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> + <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> - <TextBlock Text="{Binding Name}" ToolTip="{Binding Code}"></TextBlock> + <fa:ImageAwesome Icon="ExclamationTriangle" Width="16" Foreground="#FF5C5C" /> </DataTemplate> - </MenuItem.ItemTemplate> - </MenuItem> - <MenuItem Header="Build"> - <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> + </DataGridTemplateColumn.CellTemplate> + </DataGridTemplateColumn> + <DataGridTextColumn Header="ERROR" Binding="{Binding}"></DataGridTextColumn> + </DataGrid.Columns> + </DataGrid> + </Border> + </Grid> + </Grid> + </DataTemplate> + </Setter.Value> + </Setter> + </Style> + </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 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> + <Menu IsMainMenu="True" BorderThickness="0"> + <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> - <TabControl x:Name="tabControl" Margin="5" ItemsSource="{Binding CodeTabs}" SelectedItem="{Binding SelectedCodeTab}"> + <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> - </TabControl> + <Grid> + <TabControl x:Name="tabControl" Margin="5" ItemsSource="{Binding CodeTabs}" SelectedItem="{Binding SelectedCodeTab}"> - <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> + </TabControl> - <Grid Grid.Column="1" Grid.RowSpan="3"> - <Grid VerticalAlignment="Bottom" Height="25" Background="#007ACC"> + <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"> - <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> + </Grid> + <DockPanel> + <GroupBox Header="COMMUNICATION PORT" VerticalAlignment="Top" DockPanel.Dock="Top" Margin="0 2 0 0"> + <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"> - <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="CONNECTION" DockPanel.Dock="Bottom" VerticalAlignment="Bottom" Margin="0 10 0 25"> + <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 0"> - <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> + <GroupBox Header="STUB SNIPPETS" Margin="0 10 0 0"> + <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> + <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> + <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> + <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> |
