aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC
diff options
context:
space:
mode:
authorRoy Ben-Shabat <Roy@Twine-s.com>2019-12-15 13:12:20 +0200
committerRoy Ben-Shabat <Roy@Twine-s.com>2019-12-15 13:12:20 +0200
commit13c57f7ccabadd3ed75ffaef195d35c15c2a8c68 (patch)
tree938bd6dd844cf2645510aa3d42f3bfbe24e52a7e /Software/Visual_Studio/PPC
parentd1859415972bb991cba6639482c1cd2a9e19e8d8 (diff)
parent957ca86b8e899eb488626c456d9c37dd4545bd80 (diff)
downloadTango-13c57f7ccabadd3ed75ffaef195d35c15c2a8c68.tar.gz
Tango-13c57f7ccabadd3ed75ffaef195d35c15c2a8c68.zip
Merge branch 'master' of https://twinetfs.visualstudio.com/_git/Tango
Diffstat (limited to 'Software/Visual_Studio/PPC')
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/App.xaml11
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Attributes/BoundObjectAttribute.cs20
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BoundsObjects/KeyboardHandler.cs41
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BrowserModule.cs101
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/CefSharpOutput.zipbin0 -> 143444091 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Helpers/BoundObjectsHelper.cs72
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Images/browser.pngbin0 -> 2539 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Navigation/BrowserNavigationRequest.cs19
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/AssemblyInfo.cs20
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.Designer.cs63
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.resx117
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.Designer.cs26
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.settings7
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/RequestHandlers/ChromiumRequestHandler.cs114
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Scripts/keyboard.js21
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Tango.PPC.Browser.csproj199
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewContracts/IBrowserView.cs18
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModelLocator.cs32
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModels/BrowserViewVM.cs119
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml76
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml.cs207
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml23
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml.cs29
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/app.config90
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/packages.config11
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml3
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/RunningJobViewer.xaml3
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent.jpgbin0 -> 27097 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent_small.jpgbin0 -> 10743 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.pngbin0 -> 6743 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.pngbin0 -> 4127 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs32
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml26
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs30
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj17
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs69
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs40
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml232
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs84
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml59
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/browser.pngbin0 -> 2539 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.pngbin0 -> 4127 bytes
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj18
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs12
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/CatalogViewVM.cs23
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs41
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs6
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml32
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml1
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/PackagesView.xaml2
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml133
-rw-r--r--Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs28
-rw-r--r--Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/CefInstaller.cs59
-rw-r--r--Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Properties/AssemblyInfo.cs36
-rw-r--r--Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj69
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs10
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs18
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/KeyboardHelper.cs24
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs12
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs9
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs493
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Models/FineTuneItem.cs2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs47
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs7
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs6
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs554
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs26
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs15
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs23
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs47
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj16
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/DefaultPackageRunner.cs22
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/IPackageRunner.cs1
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageContext.cs8
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageProgressEventArgs.cs17
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateRequest.cs1
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs22
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs25
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs25
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs16
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs5
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs36
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs14
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs27
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs26
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config6
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs54
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Properties/AssemblyInfo.cs36
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj63
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/App.config3
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs6
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml32
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml.cs34
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs128
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml12
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Images/power_off.gifbin0 -> 397334 bytes
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Images/powerup.gifbin0 -> 380322 bytes
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/InternalModule.cs84
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Modules/DefaultStudioModuleLoader.cs2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs173
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs58
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj39
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs32
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/InternalModuleViewVM.cs17
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs13
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs32
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MainViewVM.cs85
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/PowerOffViewVM.cs30
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml18
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml.cs28
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml2
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml5
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml20
-rw-r--r--Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml.cs28
119 files changed, 4800 insertions, 328 deletions
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/App.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/App.xaml
new file mode 100644
index 000000000..576597134
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/App.xaml
@@ -0,0 +1,11 @@
+<Application x:Class="Tango.PPC.Browser.App"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
+ <Application.Resources>
+ <ResourceDictionary>
+ <ResourceDictionary.MergedDictionaries>
+ <ResourceDictionary Source="pack://application:,,,/Tango.PPC.Common;component/Resources/Merged.xaml" />
+ </ResourceDictionary.MergedDictionaries>
+ </ResourceDictionary>
+ </Application.Resources>
+</Application> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Attributes/BoundObjectAttribute.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Attributes/BoundObjectAttribute.cs
new file mode 100644
index 000000000..b4e822f1e
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Attributes/BoundObjectAttribute.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Browser.Attributes
+{
+ public class BoundObjectAttribute : Attribute
+ {
+ public String Name { get; set; }
+ public String ScriptFile { get; set; }
+
+ public BoundObjectAttribute(String name,String scriptFile)
+ {
+ Name = name;
+ ScriptFile = scriptFile;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BoundsObjects/KeyboardHandler.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BoundsObjects/KeyboardHandler.cs
new file mode 100644
index 000000000..50df8ae0c
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BoundsObjects/KeyboardHandler.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using Tango.PPC.Browser.Attributes;
+using Tango.PPC.Common.Helpers;
+using Tango.Touch.Keyboard;
+
+namespace Tango.PPC.Browser.BoundsObjects
+{
+ [BoundObject("keyboard", "keyboard.js")]
+ public class KeyboardHandler
+ {
+ public void openKeyboard(String inputType)
+ {
+ Application.Current.Dispatcher.BeginInvoke(new Action(() =>
+ {
+ switch (inputType)
+ {
+ case "search":
+ KeyboardHelper.OpenKeyboard(KeyboardActionKeyMode.Go);
+ break;
+ default:
+ KeyboardHelper.OpenKeyboard(KeyboardActionKeyMode.Next);
+ break;
+ }
+ }));
+ }
+
+ public void closeKeyboard()
+ {
+ Application.Current.Dispatcher.BeginInvoke(new Action(() =>
+ {
+ KeyboardHelper.CloseKeyboard();
+ }));
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BrowserModule.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BrowserModule.cs
new file mode 100644
index 000000000..dc7b294d5
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/BrowserModule.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media.Imaging;
+using Tango.BL.Enumerations;
+using Tango.PPC.Common;
+using Tango.PPC.Browser.Views;
+using Tango.SharedUI.Helpers;
+using Tango.Core.DI;
+using Tango.PPC.Common.Application;
+using System.IO;
+using Tango.Core.Helpers;
+
+namespace Tango.PPC.Browser
+{
+ /// <summary>
+ /// Represents a PPC <see cref="BrowserModule"/>.
+ /// </summary>
+ /// <seealso cref="Tango.PPC.Common.PPCModuleBase" />
+ [PPCModule(10)]
+ public class BrowserModule : PPCModuleBase
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="BrowserModule"/> class.
+ /// </summary>
+ public BrowserModule()
+ {
+ IsVisibleInMenu = false;
+ }
+
+ /// <summary>
+ /// Gets the module name.
+ /// </summary>
+ public override string Name
+ {
+ get
+ {
+ return "Browser";
+ }
+ }
+
+ /// <summary>
+ /// Gets the module description.
+ /// </summary>
+ public override string Description
+ {
+ get
+ {
+ return "Browser module";
+ }
+ }
+
+ /// <summary>
+ /// Gets the module cover image.
+ /// </summary>
+ public override BitmapSource Image
+ {
+ get
+ {
+ return ResourceHelper.GetImageFromResources("Images/browser.png");
+ }
+ }
+
+ /// <summary>
+ /// Gets the module entry point view type.
+ /// </summary>
+ public override Type MainViewType
+ {
+ get
+ {
+ return IsCefAvailable() ? typeof(BrowserView) : typeof(ErrorView);
+ }
+ }
+
+ /// <summary>
+ /// Gets the permission required to see and load this module.
+ /// </summary>
+ public override Permissions Permission
+ {
+ get
+ {
+ return Permissions.RunPPC;
+ }
+ }
+
+ private bool IsCefAvailable()
+ {
+ return File.Exists(Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "x86", "CefSharp.Core.dll"));
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public override void Dispose()
+ {
+ //Dispose module here...
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/CefSharpOutput.zip b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/CefSharpOutput.zip
new file mode 100644
index 000000000..8c68cedb7
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/CefSharpOutput.zip
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Helpers/BoundObjectsHelper.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Helpers/BoundObjectsHelper.cs
new file mode 100644
index 000000000..fe68ee848
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Helpers/BoundObjectsHelper.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Reflection;
+using Tango.PPC.Browser.Attributes;
+using CefSharp;
+using CefSharp.Wpf;
+using Tango.Core.Helpers;
+using System.Windows.Threading;
+
+namespace Tango.PPC.Browser.Helpers
+{
+ public static class BoundObjectsHelper
+ {
+ private static DispatcherTimer _timer;
+ private static Dispatcher _dispatcher;
+ private static ChromiumWebBrowser _browser;
+
+ private static List<String> _scripts = new List<string>();
+
+ public static void RegisterAllBoundObjects(ChromiumWebBrowser browser, Dispatcher dispatcher)
+ {
+ _dispatcher = dispatcher;
+ _browser = browser;
+
+ _timer = new DispatcherTimer(DispatcherPriority.Background, dispatcher);
+ _timer.Tick += _timer_Tick;
+ _timer.Interval = TimeSpan.FromSeconds(2);
+ _timer.Stop();
+
+ foreach (var type in typeof(BoundObjectsHelper).Assembly.GetTypes().Where(x => x.GetCustomAttribute<BoundObjectAttribute>() != null))
+ {
+ var att = type.GetCustomAttribute<BoundObjectAttribute>();
+
+ var script = EmbeddedResourceHelper.GetEmbeddedResourceText($"Tango.PPC.Browser.Scripts.{att.ScriptFile}");
+ _scripts.Add(script);
+
+ browser.JavascriptObjectRepository.Register(att.Name, Activator.CreateInstance(type), true);
+
+ browser.FrameLoadEnd += Browser_FrameLoadEnd;
+ }
+ }
+
+ private static void Browser_FrameLoadEnd(object sender, FrameLoadEndEventArgs e)
+ {
+ _timer.Stop();
+ _timer.Start();
+ }
+
+ private static void _timer_Tick(object sender, EventArgs e)
+ {
+ try
+ {
+ _timer.Stop();
+
+ _dispatcher.BeginInvoke(new Action(() =>
+ {
+ foreach (var script in _scripts)
+ {
+ _browser.GetMainFrame().ExecuteJavaScriptAsync(script);
+ }
+ }));
+ }
+ catch
+ {
+ _timer.Start();
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Images/browser.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Images/browser.png
new file mode 100644
index 000000000..ebb975b6f
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Images/browser.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Navigation/BrowserNavigationRequest.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Navigation/BrowserNavigationRequest.cs
new file mode 100644
index 000000000..a8becf251
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Navigation/BrowserNavigationRequest.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Browser.Navigation
+{
+ public class BrowserNavigationRequest
+ {
+ public String Address { get; set; }
+ public bool DisplayAddressBar { get; set; }
+
+ public BrowserNavigationRequest()
+ {
+ DisplayAddressBar = true;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/AssemblyInfo.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..70edee491
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/AssemblyInfo.cs
@@ -0,0 +1,20 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("Tango Web Browser Module")]
+[assembly: AssemblyVersion("2.0.1.1407")]
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.Designer.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.Designer.cs
new file mode 100644
index 000000000..01c0a8851
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.PPC.Browser.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", "15.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.PPC.Browser.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ /// <summary>
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ /// </summary>
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.resx b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.resx
new file mode 100644
index 000000000..af7dbebba
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Resources.resx
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+ <!--
+ Microsoft ResX Schema
+
+ Version 2.0
+
+ The primary goals of this format is to allow a simple XML format
+ that is mostly human readable. The generation and parsing of the
+ various data types are done through the TypeConverter classes
+ associated with the data types.
+
+ Example:
+
+ ... ado.net/XML headers & schema ...
+ <resheader name="resmimetype">text/microsoft-resx</resheader>
+ <resheader name="version">2.0</resheader>
+ <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+ <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+ <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+ <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+ <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+ <value>[base64 mime encoded serialized .NET Framework object]</value>
+ </data>
+ <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+ <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+ <comment>This is a comment</comment>
+ </data>
+
+ There are any number of "resheader" rows that contain simple
+ name/value pairs.
+
+ Each data row contains a name, and value. The row also contains a
+ type or mimetype. Type corresponds to a .NET class that support
+ text/value conversion through the TypeConverter architecture.
+ Classes that don't support this are serialized and stored with the
+ mimetype set.
+
+ The mimetype is used for serialized objects, and tells the
+ ResXResourceReader how to depersist the object. This is currently not
+ extensible. For a given mimetype the value must be set accordingly:
+
+ Note - application/x-microsoft.net.object.binary.base64 is the format
+ that the ResXResourceWriter will generate, however the reader can
+ read any of the formats listed below.
+
+ mimetype: application/x-microsoft.net.object.binary.base64
+ value : The object must be serialized with
+ : System.Serialization.Formatters.Binary.BinaryFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.soap.base64
+ value : The object must be serialized with
+ : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+ : and then encoded with base64 encoding.
+
+ mimetype: application/x-microsoft.net.object.bytearray.base64
+ value : The object must be serialized into a byte array
+ : using a System.ComponentModel.TypeConverter
+ : and then encoded with base64 encoding.
+ -->
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.Designer.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.Designer.cs
new file mode 100644
index 000000000..f464e258d
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace Tango.PPC.Browser.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.settings b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.settings
new file mode 100644
index 000000000..033d7a5e9
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Properties/Settings.settings
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+ <Profiles>
+ <Profile Name="(Default)" />
+ </Profiles>
+ <Settings />
+</SettingsFile> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/RequestHandlers/ChromiumRequestHandler.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/RequestHandlers/ChromiumRequestHandler.cs
new file mode 100644
index 000000000..fc6cb119c
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/RequestHandlers/ChromiumRequestHandler.cs
@@ -0,0 +1,114 @@
+using CefSharp;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Browser.RequestHandlers
+{
+ public class ChromiumRequestHandler : IRequestHandler
+ {
+ public event EventHandler<String> AddressChanged;
+
+ public bool GetAuthCredentials(IWebBrowser browserControl, IBrowser browser, IFrame frame, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
+ {
+ return false;
+ }
+
+ public bool OnBeforeBrowse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, bool isRedirect)
+ {
+ // You can check the Request object for the URL Here
+ return false;
+ }
+
+ public CefReturnValue OnBeforeResourceLoad(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IRequestCallback callback)
+ {
+ // You can also check the URL here
+ callback.Dispose();
+ return CefReturnValue.Continue;
+ }
+
+ public bool OnCertificateError(IWebBrowser browserControl, IBrowser browser, CefErrorCode errorCode, string requestUrl, ISslInfo sslInfo, IRequestCallback callback)
+ {
+ callback.Dispose();
+ return false;
+ }
+
+ public bool OnOpenUrlFromTab(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, WindowOpenDisposition targetDisposition, bool userGesture)
+ {
+ return false;
+ }
+
+ public void OnPluginCrashed(IWebBrowser browserControl, IBrowser browser, string pluginPath)
+ {
+ }
+
+ public bool OnProtocolExecution(IWebBrowser browserControl, IBrowser browser, string url)
+ {
+ return false;
+ }
+
+ public bool OnQuotaRequest(IWebBrowser browserControl, IBrowser browser, string originUrl, long newSize, IRequestCallback callback)
+ {
+ callback.Dispose();
+ return false;
+ }
+
+ public void OnRenderProcessTerminated(IWebBrowser browserControl, IBrowser browser, CefTerminationStatus status)
+ {
+ }
+
+ public void OnRenderViewReady(IWebBrowser browserControl, IBrowser browser)
+ {
+ }
+
+ public void OnResourceLoadComplete(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, UrlRequestStatus status, long receivedContentLength)
+ {
+ // You can also check the request URL here
+ }
+
+ public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, ref string newUrl)
+ {
+ }
+
+ public bool OnResourceResponse(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
+ {
+ return false;
+ }
+
+
+ public IResponseFilter GetResourceResponseFilter(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response)
+ {
+ return null;
+ }
+
+
+ public void OnResourceRedirect(IWebBrowser browserControl, IBrowser browser, IFrame frame, IRequest request, IResponse response, ref string newUrl)
+ {
+ }
+
+ public bool OnSelectClientCertificate(IWebBrowser browserControl, IBrowser browser, bool isProxy, string host, int port, System.Security.Cryptography.X509Certificates.X509Certificate2Collection certificates, ISelectClientCertificateCallback callback)
+ {
+ callback.Dispose();
+ return false;
+ }
+
+ public bool OnBeforeBrowse(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool userGesture, bool isRedirect)
+ {
+ AddressChanged?.Invoke(this, request.Url);
+ return false;
+ }
+
+ public IResourceRequestHandler GetResourceRequestHandler(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IRequest request, bool isNavigation, bool isDownload, string requestInitiator, ref bool disableDefaultHandling)
+ {
+ return null;
+ }
+
+ public bool GetAuthCredentials(IWebBrowser chromiumWebBrowser, IBrowser browser, string originUrl, bool isProxy, string host, int port, string realm, string scheme, IAuthCallback callback)
+ {
+ callback.Dispose();
+ return false;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Scripts/keyboard.js b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Scripts/keyboard.js
new file mode 100644
index 000000000..21771eb8e
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Scripts/keyboard.js
@@ -0,0 +1,21 @@
+(async function () {
+ await CefSharp.BindObjectAsync("keyboard", "bound");
+
+ var inputs = document.getElementsByTagName('input');
+ var i = 0;
+
+ do {
+
+ var type = inputs[i].type;
+
+ if (type == 'text' || type == 'email' || type == 'password' || type == 'search' || type == 'date' || type == 'url' || type == 'time' || type == 'tel' || type == 'number') {
+ inputs[i].onfocus = function () {
+ keyboard.openKeyboard(type);
+ }
+ inputs[i].onblur = function () {
+ keyboard.closeKeyboard();
+ }
+ }
+ }
+ while (inputs[++i])
+})(); \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Tango.PPC.Browser.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Tango.PPC.Browser.csproj
new file mode 100644
index 000000000..b742d4d75
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Tango.PPC.Browser.csproj
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.props" Condition="Exists('..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.props')" />
+ <Import Project="..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.props" Condition="Exists('..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.props')" />
+ <Import Project="..\..\..\packages\cef.redist.x86.75.1.14\build\cef.redist.x86.props" Condition="Exists('..\..\..\packages\cef.redist.x86.75.1.14\build\cef.redist.x86.props')" />
+ <Import Project="..\..\..\packages\cef.redist.x64.75.1.14\build\cef.redist.x64.props" Condition="Exists('..\..\..\packages\cef.redist.x64.75.1.14\build\cef.redist.x64.props')" />
+ <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
+ <PropertyGroup>
+ <CefSharpAnyCpuSupport>true</CefSharpAnyCpuSupport>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ProjectGuid>{F02EAA84-AD59-465B-99A2-4422C13BFB72}</ProjectGuid>
+ <OutputType>library</OutputType>
+ <RootNamespace>Tango.PPC.Browser</RootNamespace>
+ <AssemblyName>Tango.PPC.Browser</AssemblyName>
+ <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <WarningLevel>4</WarningLevel>
+ <TargetFrameworkProfile />
+ <NuGetPackageImportStamp>
+ </NuGetPackageImportStamp>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\Build\PPC\Debug\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>bin\Release\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.dll</HintPath>
+ <Private>True</Private>
+ </Reference>
+ <Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\EntityFramework.6.0.0\lib\net45\EntityFramework.SqlServer.dll</HintPath>
+ </Reference>
+ <Reference Include="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="System" />
+ <Reference Include="System.ComponentModel.DataAnnotations" />
+ <Reference Include="System.Data" />
+ <Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
+ <HintPath>..\..\..\packages\Expression.Blend.Sdk.1.0.2\lib\net45\System.Windows.Interactivity.dll</HintPath>
+ </Reference>
+ <Reference Include="System.Xml" />
+ <Reference Include="Microsoft.CSharp" />
+ <Reference Include="System.Core" />
+ <Reference Include="System.Xml.Linq" />
+ <Reference Include="System.Data.DataSetExtensions" />
+ <Reference Include="System.Net.Http" />
+ <Reference Include="System.Xaml">
+ <RequiredTargetFramework>4.0</RequiredTargetFramework>
+ </Reference>
+ <Reference Include="WindowsBase" />
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
+ </ItemGroup>
+ <ItemGroup>
+ <Page Include="App.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
+ <Page Include="Views\BrowserView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ <Page Include="Views\ErrorView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="..\..\..\Versioning\GlobalVersionInfo.cs">
+ <Link>GlobalVersionInfo.cs</Link>
+ </Compile>
+ <Compile Include="Attributes\BoundObjectAttribute.cs" />
+ <Compile Include="BoundsObjects\KeyboardHandler.cs" />
+ <Compile Include="BrowserModule.cs" />
+ <Compile Include="Helpers\BoundObjectsHelper.cs" />
+ <Compile Include="Navigation\BrowserNavigationRequest.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ <Compile Include="Properties\Resources.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DesignTime>True</DesignTime>
+ <DependentUpon>Resources.resx</DependentUpon>
+ </Compile>
+ <Compile Include="Properties\Settings.Designer.cs">
+ <AutoGen>True</AutoGen>
+ <DependentUpon>Settings.settings</DependentUpon>
+ <DesignTimeSharedInput>True</DesignTimeSharedInput>
+ </Compile>
+ <Compile Include="RequestHandlers\ChromiumRequestHandler.cs" />
+ <Compile Include="ViewContracts\IBrowserView.cs" />
+ <Compile Include="ViewModelLocator.cs" />
+ <Compile Include="ViewModels\BrowserViewVM.cs" />
+ <Compile Include="Views\BrowserView.xaml.cs">
+ <DependentUpon>BrowserView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Views\ErrorView.xaml.cs">
+ <DependentUpon>ErrorView.xaml</DependentUpon>
+ </Compile>
+ <EmbeddedResource Include="Properties\Resources.resx">
+ <Generator>ResXFileCodeGenerator</Generator>
+ <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+ </EmbeddedResource>
+ <None Include="app.config" />
+ <None Include="CefSharpOutput.zip" />
+ <None Include="packages.config" />
+ <None Include="Properties\Settings.settings">
+ <Generator>SettingsSingleFileGenerator</Generator>
+ <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Tango.BL\Tango.BL.csproj">
+ <Project>{f441feee-322a-4943-b566-110e12fd3b72}</Project>
+ <Name>Tango.BL</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.DragAndDrop\Tango.DragAndDrop.csproj">
+ <Project>{b112d89a-a106-41ae-a0c1-4abc84c477f5}</Project>
+ <Name>Tango.DragAndDrop</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Logging\Tango.Logging.csproj">
+ <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
+ <Name>Tango.Logging</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.PMR\Tango.PMR.csproj">
+ <Project>{e4927038-348d-4295-aaf4-861c58cb3943}</Project>
+ <Name>Tango.PMR</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Settings\Tango.Settings.csproj">
+ <Project>{d8f1ad85-526a-4f50-b6dc-d437af63d8d8}</Project>
+ <Name>Tango.Settings</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.SharedUI\Tango.SharedUI.csproj">
+ <Project>{8491d07b-c1f6-4b62-a412-41b9fd2d6538}</Project>
+ <Name>Tango.SharedUI</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Touch\Tango.Touch.csproj">
+ <Project>{fd86424c-6e84-491b-8df9-3d0f5c236a2a}</Project>
+ <Name>Tango.Touch</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Transport\Tango.Transport.csproj">
+ <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project>
+ <Name>Tango.Transport</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.PPC.Common\Tango.PPC.Common.csproj">
+ <Project>{0be74eee-22cb-4dba-b896-793b9e1a3ac0}</Project>
+ <Name>Tango.PPC.Common</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\browser.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <EmbeddedResource Include="Scripts\keyboard.js" />
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+ <ProjectExtensions>
+ <VisualStudio>
+ <UserProperties BuildVersion_StartDate="2000/1/1" BuildVersion_UseGlobalSettings="False" BuildVersion_BuildVersioningStyle="None.None.Increment.TimeStamp" BuildVersion_UpdateAssemblyVersion="True" BuildVersion_AssemblyInfoFilename="Properties\AssemblyInfo.cs" />
+ </VisualStudio>
+ </ProjectExtensions>
+ <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
+ <PropertyGroup>
+ <ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
+ </PropertyGroup>
+ <Error Condition="!Exists('..\..\..\packages\cef.redist.x64.75.1.14\build\cef.redist.x64.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\cef.redist.x64.75.1.14\build\cef.redist.x64.props'))" />
+ <Error Condition="!Exists('..\..\..\packages\cef.redist.x86.75.1.14\build\cef.redist.x86.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\cef.redist.x86.75.1.14\build\cef.redist.x86.props'))" />
+ <Error Condition="!Exists('..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.props'))" />
+ <Error Condition="!Exists('..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.targets'))" />
+ <Error Condition="!Exists('..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.props'))" />
+ <Error Condition="!Exists('..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.targets'))" />
+ </Target>
+ <Import Project="..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.targets" Condition="Exists('..\..\..\packages\CefSharp.Common.75.1.143\build\CefSharp.Common.targets')" />
+ <Import Project="..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.targets" Condition="Exists('..\..\..\packages\CefSharp.Wpf.75.1.143\build\CefSharp.Wpf.targets')" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewContracts/IBrowserView.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewContracts/IBrowserView.cs
new file mode 100644
index 000000000..8369209a3
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewContracts/IBrowserView.cs
@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PPC.Common;
+using Tango.SharedUI;
+
+namespace Tango.PPC.Browser.ViewContracts
+{
+ public interface IBrowserView : IPPCView
+ {
+ event EventHandler<String> AddressChanged;
+ bool CanGoBack();
+ void NavigateTo(String address);
+ void GoBack();
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModelLocator.cs
new file mode 100644
index 000000000..054310e99
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModelLocator.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.DI;
+using Tango.PPC.Browser.ViewModels;
+
+namespace Tango.PPC.Browser
+{
+ public static class ViewModelLocator
+ {
+ /// <summary>
+ /// Initializes a new instance of the ViewModelLocator class.
+ /// </summary>
+ static ViewModelLocator()
+ {
+ TangoIOC.Default.Register<BrowserViewVM>();
+ }
+
+ /// <summary>
+ /// Gets the main view VM.
+ /// </summary>
+ public static BrowserViewVM BrowserViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<BrowserViewVM>();
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModels/BrowserViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModels/BrowserViewVM.cs
new file mode 100644
index 000000000..9650aa342
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/ViewModels/BrowserViewVM.cs
@@ -0,0 +1,119 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.PPC.Browser.Navigation;
+using Tango.PPC.Browser.ViewContracts;
+using Tango.PPC.Common;
+using Tango.PPC.Common.Navigation;
+using Tango.Touch.Keyboard;
+
+namespace Tango.PPC.Browser.ViewModels
+{
+ /// <summary>
+ /// Represents the main view VM and entry point for <see cref="Synchronization.MyModule"/>.
+ /// </summary>
+ /// <seealso cref="Tango.PPC.Common.PPCViewModel" />
+ public class BrowserViewVM : PPCViewModel<IBrowserView>, INavigationObjectReceiver<BrowserNavigationRequest>
+ {
+ private bool _isFromObject;
+
+ private String _address;
+ public String Address
+ {
+ get { return _address; }
+ set { _address = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _displayAddressBar;
+ public bool DisplayAddressBar
+ {
+ get { return _displayAddressBar; }
+ set { _displayAddressBar = value; RaisePropertyChangedAuto(); }
+ }
+
+ public RelayCommand GoCommand { get; set; }
+
+ public BrowserViewVM()
+ {
+ DisplayAddressBar = true;
+
+ GoCommand = new RelayCommand(Go);
+ }
+
+ public override void OnViewAttached()
+ {
+ base.OnViewAttached();
+ View.AddressChanged += View_AddressChanged;
+ }
+
+ private void View_AddressChanged(object sender, string address)
+ {
+ Address = address;
+ }
+
+ public override void OnNavigatedTo()
+ {
+ base.OnNavigatedTo();
+
+ KeyboardView.Default.OutputMode = KeyboardOutputMode.Windows;
+
+ if (!_isFromObject)
+ {
+ DisplayAddressBar = true;
+ }
+
+ _isFromObject = false;
+ }
+
+ public override void OnNavigatedFrom()
+ {
+ base.OnNavigatedFrom();
+ KeyboardView.Default.OutputMode = KeyboardOutputMode.Wpf;
+ }
+
+ public override Task<bool> OnNavigateBackRequest()
+ {
+ if (View != null && View.CanGoBack())
+ {
+ View.GoBack();
+ return Task.FromResult(false);
+ }
+ else
+ {
+ return Task.FromResult(true);
+ }
+ }
+
+ /// <summary>
+ /// Called when the application has been started
+ /// </summary>
+ public override void OnApplicationStarted()
+ {
+
+ }
+
+ private void Go()
+ {
+ if (View != null)
+ {
+ View.NavigateTo(Address);
+ }
+ }
+
+ public void OnNavigatedToWithObject(BrowserNavigationRequest obj)
+ {
+ _isFromObject = true;
+
+ DisplayAddressBar = obj.DisplayAddressBar;
+
+ if (obj.Address != null)
+ {
+ Address = obj.Address;
+ Go();
+ }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml
new file mode 100644
index 000000000..6e2076c98
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml
@@ -0,0 +1,76 @@
+<UserControl x:Class="Tango.PPC.Browser.Views.BrowserView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:vm="clr-namespace:Tango.PPC.Browser.ViewModels"
+ xmlns:wpf="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
+ xmlns:global="clr-namespace:Tango.PPC.Browser"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:keyboard="clr-namespace:Tango.Touch.Keyboard;assembly=Tango.Touch"
+ xmlns:local="clr-namespace:Tango.PPC.Browser.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="1280" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:BrowserViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.BrowserViewVM}" Background="{StaticResource TangoPrimaryBackgroundBrush}">
+ <Grid>
+ <DockPanel>
+ <Border DockPanel.Dock="Top" Padding="10" BorderBrush="{StaticResource TangoGrayBrush}" BorderThickness="0 0 0 1" Visibility="{Binding DisplayAddressBar,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <DockPanel>
+ <touch:TouchButton Command="{Binding GoCommand}" DockPanel.Dock="Right" Padding="10" Width="150" CornerRadius="20" Margin="20 0 0 0">
+ <touch:TouchIcon Icon="ArrowRightBold" Height="20" />
+ </touch:TouchButton>
+ <Grid>
+ <Border Background="{StaticResource TangoMidBackgroundBrush}" Padding="2" BorderBrush="{StaticResource TangoLightBorderBrush}" BorderThickness="1" CornerRadius="20">
+ <TextBox x:Name="txtAddress" PreviewMouseDoubleClick="TxtAddress_PreviewMouseDoubleClick" GotFocus="TxtAddress_GotFocus" PreviewMouseUp="TxtAddress_MouseUp" LostFocus="TxtAddress_LostFocus" KeyDown="TxtAddress_KeyDown" VerticalContentAlignment="Center" Text="{Binding Address,UpdateSourceTrigger=PropertyChanged}" BorderThickness="0" FontSize="{StaticResource TangoDefaultFontSize}" Padding="5" Background="Transparent"></TextBox>
+ </Border>
+ <Border CornerRadius="20" IsHitTestVisible="False" Visibility="{Binding ElementName=Browser,Path=IsLoading,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <Border.Background>
+ <LinearGradientBrush>
+ <GradientStop Offset="0" Color="Transparent" />
+ <GradientStop Offset="0.5" Color="#7612D433" />
+ <GradientStop Offset="1" Color="Transparent" />
+ </LinearGradientBrush>
+ </Border.Background>
+ <Border.Style>
+ <Style TargetType="Border">
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding ElementName=Browser,Path=IsLoading}" Value="True">
+ <DataTrigger.EnterActions>
+ <BeginStoryboard Name="loadingStory">
+ <Storyboard>
+ <DoubleAnimation Storyboard.TargetProperty="Background.GradientStops[1].Offset" From="0" To="1" AutoReverse="True" RepeatBehavior="Forever" />
+ </Storyboard>
+ </BeginStoryboard>
+ </DataTrigger.EnterActions>
+ <DataTrigger.ExitActions>
+ <RemoveStoryboard BeginStoryboardName="loadingStory" />
+ </DataTrigger.ExitActions>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
+ </Border>
+ </Grid>
+ </DockPanel>
+ </Border>
+
+ <Grid>
+ <wpf:ChromiumWebBrowser x:Name="Browser" />
+ <Grid Background="White" IsHitTestVisible="False" Visibility="Hidden" x:Name="gridError">
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <touch:TouchIcon Icon="Alert" Foreground="{StaticResource TangoGrayTextBrush}" Width="100" Height="100" />
+ <TextBlock HorizontalAlignment="Center" Foreground="{StaticResource TangoGrayTextBrush}" FontSize="40" Margin="0 20 0 0">Page Not Found</TextBlock>
+ <TextBlock Margin="0 10 0 0" Foreground="{StaticResource TangoGrayTextBrush}" HorizontalAlignment="Center" Width="600" TextAlignment="Center" TextWrapping="Wrap">
+ <Run>The page at '</Run><Run Text="{Binding ElementName=txtAddress,Path=Text,Mode=OneWay}"></Run><Run>'</Run>
+ <Run>could not be reached.</Run>
+ <LineBreak/>
+ <Run>Please check your internet connection.</Run>
+ <LineBreak/>
+ <LineBreak/>
+ <Run x:Name="runError" Text="Unspecified"></Run>
+ </TextBlock>
+ </StackPanel>
+ </Grid>
+ </Grid>
+ </DockPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml.cs
new file mode 100644
index 000000000..cdba301ed
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/BrowserView.xaml.cs
@@ -0,0 +1,207 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+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 System.Windows.Threading;
+using CefSharp;
+using CefSharp.Wpf;
+using Tango.Core.DI;
+using Tango.Core.Helpers;
+using Tango.Logging;
+using Tango.PPC.Browser.BoundsObjects;
+using Tango.PPC.Browser.ViewContracts;
+using Tango.PPC.Common.Helpers;
+using Tango.Touch.Keyboard;
+
+namespace Tango.PPC.Browser.Views
+{
+ /// <summary>
+ /// Interaction logic for MainView.xaml
+ /// </summary>
+ public partial class BrowserView : UserControl, IBrowserView
+ {
+ public event EventHandler<string> AddressChanged;
+
+ public BrowserView()
+ {
+ try
+ {
+ var settings = new CefSettings();
+ settings.BrowserSubprocessPath = @"x86\CefSharp.BrowserSubprocess.exe";
+ settings.UserAgent = "Mozilla/5.0 (iPad; CPU OS 12_2 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148";
+
+ Cef.Initialize(settings, performDependencyCheck: false, browserProcessHandler: null);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Default.Log(ex, "Error loading cef.");
+ }
+
+ InitializeComponent();
+
+ TangoIOC.Default.Register<IBrowserView>(this);
+
+ Helpers.BoundObjectsHelper.RegisterAllBoundObjects(Browser, Dispatcher);
+
+ KeyboardView.Default.KeyboardOpened += Default_KeyboardOpened;
+ KeyboardView.Default.KeyboardClosed += Default_KeyboardClosed;
+
+ var handler = new RequestHandlers.ChromiumRequestHandler();
+ handler.AddressChanged += Handler_AddressChanged;
+ Browser.RequestHandler = handler;
+ Browser.LoadError += Browser_LoadError;
+ Browser.LoadingStateChanged += Browser_LoadingStateChanged;
+ }
+
+ private void Browser_LoadError(object sender, LoadErrorEventArgs e)
+ {
+ //if (e.ErrorCode == CefErrorCode.ConnectionTimedOut || e.ErrorCode == CefErrorCode.NameNotResolved)
+ //{
+ InvokeUI(() =>
+ {
+ runError.Text = e.ErrorText;
+ gridError.Visibility = Visibility.Visible;
+ });
+ //}
+ }
+
+ private void Browser_LoadingStateChanged(object sender, LoadingStateChangedEventArgs e)
+ {
+ if (!e.IsLoading)
+ {
+ InvokeUI(() =>
+ {
+ KeyboardHelper.CloseKeyboard();
+ });
+ }
+ else
+ {
+ InvokeUI(() =>
+ {
+ gridError.Visibility = Visibility.Hidden;
+ });
+ }
+ }
+
+ private void Handler_AddressChanged(object sender, string address)
+ {
+ InvokeUI(() =>
+ {
+ AddressChanged?.Invoke(this, address);
+ });
+ }
+
+ private void Default_KeyboardClosed(object sender, EventArgs e)
+ {
+ Browser.VerticalAlignment = VerticalAlignment.Stretch;
+ Browser.Height = double.NaN;
+ }
+
+ private void Default_KeyboardOpened(object sender, EventArgs e)
+ {
+ Browser.VerticalAlignment = VerticalAlignment.Top;
+ Browser.Height = 780;
+ }
+
+ public bool CanGoBack()
+ {
+ return Browser.CanGoBack;
+ }
+
+ public void NavigateTo(string address)
+ {
+ if (Browser.Address != address)
+ {
+ String uri;
+
+ if (ValidHttpURL(address, out uri))
+ {
+ Browser.Address = uri;
+ }
+ else
+ {
+ Browser.Address = $"google.com/search?q={address.Replace(" ", "+")}";
+ }
+ }
+ else
+ {
+ Browser.Reload();
+ }
+ }
+
+ public static bool ValidHttpURL(string s, out string result)
+ {
+ if (Uri.IsWellFormedUriString(s, UriKind.Absolute))
+ {
+ result = s;
+ return true;
+ }
+ else if (s.StartsWith("www."))
+ {
+ result = "http://" + s;
+ return true;
+ }
+
+ result = s;
+ return false;
+ }
+
+ public void GoBack()
+ {
+ if (Browser.CanGoBack)
+ {
+ Browser.Back();
+ }
+ }
+
+ private async void TxtAddress_GotFocus(object sender, RoutedEventArgs e)
+ {
+ KeyboardHelper.OpenKeyboard(KeyboardActionKeyMode.Go);
+ await Task.Delay(100);
+ txtAddress.SelectAll();
+ }
+
+ private void TxtAddress_LostFocus(object sender, RoutedEventArgs e)
+ {
+ KeyboardHelper.CloseKeyboard();
+ }
+
+ private void TxtAddress_KeyDown(object sender, KeyEventArgs e)
+ {
+ if (e.Key == Key.Return)
+ {
+ KeyboardHelper.CloseKeyboard();
+ NavigateTo(txtAddress.Text);
+ }
+ }
+
+ private void TxtAddress_MouseUp(object sender, MouseButtonEventArgs e)
+ {
+ KeyboardHelper.OpenKeyboard(KeyboardActionKeyMode.Go);
+ }
+
+ private async void TxtAddress_PreviewMouseDoubleClick(object sender, MouseButtonEventArgs e)
+ {
+ KeyboardHelper.OpenKeyboard(KeyboardActionKeyMode.Go);
+ await Task.Delay(100);
+ txtAddress.SelectAll();
+ }
+
+ private void InvokeUI(Action action)
+ {
+ Dispatcher.BeginInvoke(action);
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml
new file mode 100644
index 000000000..25e3381ba
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml
@@ -0,0 +1,23 @@
+<UserControl x:Class="Tango.PPC.Browser.Views.ErrorView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:vm="clr-namespace:Tango.PPC.Browser.ViewModels"
+ xmlns:global="clr-namespace:Tango.PPC.Browser"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.PPC.Browser.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="1280" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:BrowserViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.BrowserViewVM}" Background="{StaticResource TangoPrimaryBackgroundBrush}">
+ <Grid>
+ <Grid Background="White" IsHitTestVisible="False">
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <touch:TouchIcon Icon="Alert" Foreground="{StaticResource TangoGrayTextBrush}" Width="100" Height="100" />
+ <TextBlock HorizontalAlignment="Center" Foreground="{StaticResource TangoGrayTextBrush}" FontSize="40" Margin="0 20 0 0">Browser Not Loaded</TextBlock>
+ <TextBlock Margin="0 10 0 0" Foreground="{StaticResource TangoGrayTextBrush}" HorizontalAlignment="Center" Width="600" TextAlignment="Center" TextWrapping="Wrap">
+ The browser module was not loaded properly or has caused some error.
+ </TextBlock>
+ </StackPanel>
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml.cs
new file mode 100644
index 000000000..0d59b80f0
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/Views/ErrorView.xaml.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Tango.PPC.Browser.ViewContracts;
+
+namespace Tango.PPC.Browser.Views
+{
+ /// <summary>
+ /// Interaction logic for ErrorView.xaml
+ /// </summary>
+ public partial class ErrorView : UserControl
+ {
+ public ErrorView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/app.config b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/app.config
new file mode 100644
index 000000000..cf33970a7
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/app.config
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <configSections>
+ <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
+ <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
+ </configSections>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <!--Required for cefCharp-->
+ <probing privatePath="x86"/>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.2.2.0" newVersion="1.2.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Reflection.Metadata" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.4.2.0" newVersion="1.4.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.FileSystem" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.IO.FileSystem.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Security.Cryptography.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Xml.XPath.XDocument" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Console" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="System.Diagnostics.StackTrace" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.0.5.0" newVersion="5.0.5.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Data.Edm" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Data.Services.Client" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Microsoft.Data.OData" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-5.6.4.0" newVersion="5.6.4.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
+ </dependentAssembly>
+ <dependentAssembly>
+ <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-1.5.2.14234" newVersion="1.5.2.14234" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+ <entityFramework>
+ <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
+ <providers>
+ <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
+ </providers>
+ </entityFramework>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+ </startup>
+</configuration>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/packages.config b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/packages.config
new file mode 100644
index 000000000..f7fe1b9a2
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Browser/packages.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+ <package id="cef.redist.x64" version="75.1.14" targetFramework="net461" />
+ <package id="cef.redist.x86" version="75.1.14" targetFramework="net461" />
+ <package id="CefSharp.Common" version="75.1.143" targetFramework="net461" />
+ <package id="CefSharp.Wpf" version="75.1.143" targetFramework="net461" />
+ <package id="EntityFramework" version="6.0.0" targetFramework="net46" />
+ <package id="Expression.Blend.Sdk" version="1.0.2" targetFramework="net46" />
+ <package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net46" />
+ <package id="Google.Protobuf" version="3.4.1" targetFramework="net46" />
+</packages> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml
index ba6c13e91..afe331145 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/JobSummeryViewer.xaml
@@ -66,6 +66,9 @@
</RectangleGeometry.Rect>
</RectangleGeometry>
</Border.Clip>
+ <Border.Background>
+ <ImageBrush ImageSource="../Images/JobView/transparent_small.jpg" Stretch="None" TileMode="Tile" AlignmentX="Left" ViewportUnits="Absolute" Viewport="0,0,94,30" />
+ </Border.Background>
<Grid>
<ItemsControl ClipToBounds="False" ItemsSource="{Binding EffectiveSegments,IsAsync=True}">
<ItemsControl.ItemsPanel>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/RunningJobViewer.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/RunningJobViewer.xaml
index 97aedcf89..5d3f3f1fc 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/RunningJobViewer.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Controls/RunningJobViewer.xaml
@@ -57,6 +57,9 @@
</ItemsControl>
<Border Grid.Row="1" x:Name="brush_border" ClipToBounds="False" CornerRadius="10" Margin="0 5 0 0">
+ <Border.Background>
+ <ImageBrush ImageSource="../Images/JobView/transparent_small.jpg" Stretch="None" TileMode="Tile" AlignmentX="Left" ViewportUnits="Absolute" Viewport="0,0,94,30" />
+ </Border.Background>
<Border.Clip>
<RectangleGeometry RadiusX="10" RadiusY="10">
<RectangleGeometry.Rect>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent.jpg b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent.jpg
new file mode 100644
index 000000000..cf1d94d12
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent.jpg
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent_small.jpg b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent_small.jpg
new file mode 100644
index 000000000..c682a4c7e
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/JobView/transparent_small.jpg
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png
new file mode 100644
index 000000000..4e46ee447
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync-job.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.png
new file mode 100644
index 000000000..46059c5c0
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Images/sync.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs
new file mode 100644
index 000000000..4e3137e1c
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItem.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PPC.Common.Notifications;
+
+namespace Tango.PPC.Jobs.NotificationItems
+{
+ /// <summary>
+ /// Represents a simple text message notification item which can be inserted into the application notifications panel.
+ /// </summary>
+ /// <seealso cref="Tango.PPC.Common.Notifications.NotificationItem" />
+ public class NewSynchronizardJobsNotificationItem : NotificationItem
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="UpdateAvailableNotificationItem"/> class.
+ /// </summary>
+ public NewSynchronizardJobsNotificationItem()
+ {
+ CanClose = true;
+ }
+
+ /// <summary>
+ /// Gets or sets the view type.
+ /// </summary>
+ public override Type ViewType
+ {
+ get { return typeof(NewSynchronizardJobsNotificationItemView); }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml
new file mode 100644
index 000000000..23a64676b
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml
@@ -0,0 +1,26 @@
+<UserControl x:Class="Tango.PPC.Jobs.NotificationItems.NewSynchronizardJobsNotificationItemView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:local="clr-namespace:Tango.PPC.Jobs.NotificationItems"
+ xmlns:common="clr-namespace:Tango.PPC.Common.Converters"
+ mc:Ignorable="d"
+ x:Name="MessageNotificationItemControl"
+ d:DesignHeight="60" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=local:NewSynchronizardJobsNotificationItem, IsDesignTimeCreatable=False}" MinHeight="90" Height="90" MaxHeight="150" Background="White">
+
+ <Grid>
+ <Border BorderThickness="0 0 0 2" BorderBrush="{StaticResource TangoPrimaryAccentBrush}" Padding="15">
+ <DockPanel>
+ <Image Source="../Images/sync-job.png" MaxHeight="50" />
+
+ <Grid>
+ <TextBlock Margin="20 0 0 0" VerticalAlignment="Center">
+ New job definitions were synchronized with your machine. Tap to refresh your job list.
+ </TextBlock>
+ </Grid>
+ </DockPanel>
+ </Border>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs
new file mode 100644
index 000000000..33db09386
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/NotificationItems/NewSynchronizardJobsNotificationItemView.xaml.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.PPC.Jobs.NotificationItems
+{
+ /// <summary>
+ /// Represents the <see cref="UpdateAvailableNotificationItemView"/> view.
+ /// </summary>
+ /// <seealso cref="System.Windows.Controls.UserControl" />
+ /// <seealso cref="System.Windows.Markup.IComponentConnector" />
+ public partial class NewSynchronizardJobsNotificationItemView : UserControl
+ {
+ public NewSynchronizardJobsNotificationItemView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj
index 609a15de4..5e1fd39bd 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Tango.PPC.Jobs.csproj
@@ -124,6 +124,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="NotificationItems\NewSynchronizardJobsNotificationItemView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
<Page Include="Resources\Styles.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -228,6 +232,10 @@
<Compile Include="NavigationObjects\JobNavigationObject.cs" />
<Compile Include="NavigationObjects\JobSummeryNavigationObject.cs" />
<Compile Include="NavigationObjects\TwineCatalogNavigationObject.cs" />
+ <Compile Include="NotificationItems\NewSynchronizardJobsNotificationItem.cs" />
+ <Compile Include="NotificationItems\NewSynchronizardJobsNotificationItemView.xaml.cs">
+ <DependentUpon>NewSynchronizardJobsNotificationItemView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
@@ -486,6 +494,15 @@
<ItemGroup>
<Resource Include="Images\color-picker.png" />
</ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\sync.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\JobView\transparent.jpg" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\JobView\transparent_small.jpg" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs
index a097084f7..5ec1c34ec 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs
@@ -412,7 +412,7 @@ namespace Tango.PPC.Jobs.ViewModels
RepeatSampleDyeCommand = new RelayCommand(RepeatSampleDye);
AnotherSampleCommand = new RelayCommand(DyeAnotherSample);
InvokeFineTuningPaletteCommand = new RelayCommand<FineTuneItem>(InvokeFineTuningPalette);
- ResetFineTuningCommand = new RelayCommand(ResetFineTuning);
+ ResetFineTuningCommand = new RelayCommand(() => ResetFineTuning(true));
StartFineTuningCommand = new RelayCommand(StartFineTuning, () => FineTuneItems.Any(x => x.IsSelected) && CanStartJob());
RepeatFineTuningCommand = new RelayCommand(RepeatFineTuning);
ApproveFineTuningCommand = new RelayCommand(ApproveFineTuning);
@@ -468,7 +468,7 @@ namespace Tango.PPC.Jobs.ViewModels
Job.ValidateOnPropertyChanged = true;
LogManager.Log("Loading RMLS...");
- Rmls = (await new RmlsCollectionBuilder(_db).SetAll().WithActiveParametersGroup().WithCAT(Job.MachineGuid).WithCCT().WithLiquidFactors().BuildAsync()).ToList();
+ Rmls = (await new RmlsCollectionBuilder(_db).SetAll().WithActiveParametersGroup().WithCAT(Job.MachineGuid).WithCCT().WithLiquidFactors().WithSite(MachineProvider.Machine.SiteGuid).BuildAsync()).ToList();
LogManager.Log("Loading Color Spaces...");
ColorSpaces = await _db.ColorSpaces.ToListAsync();
LogManager.Log("Loading Spool Types...");
@@ -478,7 +478,7 @@ namespace Tango.PPC.Jobs.ViewModels
if (Job.ColorSpace.Space == BL.Enumerations.ColorSpaces.Catalog)
{
- SelectedCatalog = await new ColorCatalogBuilder(_db).Set(Job.ColorCatalogGuid).WithGroups().WithItems().BuildAsync();
+ SelectedCatalog = await new CatalogBuilder(_db).Set(Job.ColorCatalogGuid).WithGroups().WithItems().BuildAsync();
if (SelectedCatalog != null)
{
@@ -593,6 +593,7 @@ namespace Tango.PPC.Jobs.ViewModels
}
Job.LastUpdated = DateTime.UtcNow;
+ Job.IsSynchronized = false;
Job.JobStatus = BL.Enumerations.JobStatuses.Draft;
await _db.SaveChangesAsync();
_current_job_string = Job.ToJobFileWhenLoaded().ToString();
@@ -669,7 +670,7 @@ namespace Tango.PPC.Jobs.ViewModels
{
return
Job != null && Job.Validate(_db) &&
- !Job.Segments.SelectMany(x => x.BrushStops).ToList().Exists(x => x.IsOutOfGamut);
+ !Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.IsTransparent).ToList().Exists(x => x.IsOutOfGamut);
}
#endregion
@@ -901,22 +902,28 @@ namespace Tango.PPC.Jobs.ViewModels
if (vm == null || vm.Result == BasicColorCorrectionViewVM.ColorCorrectionDialogResult.MoreOptions)
{
- conversionOutput = _converter.Convert(brushStop, true);
+ NotificationProvider.SetGlobalBusyMessage("Generating color hive...");
- suggestions = conversionOutput.CreateHiveSuggestions();
-
- if (vm == null)
+ await Task.Factory.StartNew(() =>
{
- var center = suggestions.GetCenterSuggestion();
- center.Coordinates.Red = brushStop.Red;
- center.Coordinates.Green = brushStop.Green;
- center.Coordinates.Blue = brushStop.Blue;
+ conversionOutput = _converter.Convert(brushStop, true);
- center.Coordinates.L = brushStop.L;
- center.Coordinates.A = brushStop.A;
- center.Coordinates.B = brushStop.B;
- }
+ suggestions = conversionOutput.CreateHiveSuggestions();
+ if (vm == null)
+ {
+ var center = suggestions.GetCenterSuggestion();
+ center.Coordinates.Red = brushStop.Red;
+ center.Coordinates.Green = brushStop.Green;
+ center.Coordinates.Blue = brushStop.Blue;
+
+ center.Coordinates.L = brushStop.L;
+ center.Coordinates.A = brushStop.A;
+ center.Coordinates.B = brushStop.B;
+ }
+ });
+
+ NotificationProvider.ReleaseGlobalBusyMessage();
LogManager.Log("Invoking hive color conversion dialog...");
vm = await NotificationProvider.ShowDialog<AdvancedColorCorrectionViewVM>(new AdvancedColorCorrectionViewVM()
{
@@ -962,6 +969,7 @@ namespace Tango.PPC.Jobs.ViewModels
}
finally
{
+ NotificationProvider.ReleaseGlobalBusyMessage();
DyeCommand.RaiseCanExecuteChanged();
}
}
@@ -1111,7 +1119,7 @@ namespace Tango.PPC.Jobs.ViewModels
/// <summary>
/// Synchronizes the fine tune items to brush stops.
/// </summary>
- private void SyncFineTuneItemsToBrushStops()
+ private async void SyncFineTuneItemsToBrushStops(bool displayBusy = false)
{
try
{
@@ -1123,18 +1131,27 @@ namespace Tango.PPC.Jobs.ViewModels
}
else
{
+ if (displayBusy)
+ {
+ NotificationProvider.SetGlobalBusyMessage("Generating suggestions...");
+ }
+
FineTuneItems.Clear();
- foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).Where(x => x.ColorSpace.Space == BL.Enumerations.ColorSpaces.RGB || x.ColorSpace.Space == BL.Enumerations.ColorSpaces.LAB).DistinctBy(x => x.Color))
+ foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.IsTransparent).Where(x => x.ColorSpace.Space == BL.Enumerations.ColorSpaces.RGB || x.ColorSpace.Space == BL.Enumerations.ColorSpaces.LAB).DistinctBy(x => x.Color))
{
- FineTuneItem item = new FineTuneItem(_converter.Convert(stop, true));
+ var conversionoutput = await _converter.ConvertAsync(stop, true);
+ FineTuneItem item = new FineTuneItem(conversionoutput);
+ item.BrushStop = stop;
item.BrushStops = Job.Segments.SelectMany(x => x.BrushStops).Where(x => x.Color == stop.Color).ToList();
- item.SelectedSuggestion = item.Suggestions[item.Suggestions.Count / 2];
+ item.SelectedSuggestion = item.Suggestions.GetCenterSuggestion();
item.SelectedChanged += () => StartFineTuningCommand.RaiseCanExecuteChanged();
FineTuneItems.Add(item);
}
_jobs_fine_tune_items[Job.Guid] = FineTuneItems.ToList();
+
+ NotificationProvider.ReleaseGlobalBusyMessage();
}
ApprovalFineTuneItems = FineTuneItems.Where(x => x.IsSelected).ToObservableCollection();
@@ -1146,6 +1163,10 @@ namespace Tango.PPC.Jobs.ViewModels
{
LogManager.Log(ex, "Error while trying to synchronize fine tuning items with brush stops.");
}
+ finally
+ {
+ NotificationProvider.ReleaseGlobalBusyMessage();
+ }
}
/// <summary>
@@ -1172,19 +1193,23 @@ namespace Tango.PPC.Jobs.ViewModels
LogManager.Log(ex, "Error invoking the fine tunning palette");
await NotificationProvider.ShowError("An error occurred while trying to display the fine tunning palette.");
}
+ finally
+ {
+ NotificationProvider.ReleaseGlobalBusyMessage();
+ }
}
/// <summary>
/// Resets the fine tuning.
/// </summary>
- private void ResetFineTuning()
+ private void ResetFineTuning(bool displayBusy = false)
{
if (Job != null && _jobs_fine_tune_items.ContainsKey(Job.Guid))
{
_jobs_fine_tune_items.Remove(Job.Guid);
}
- SyncFineTuneItemsToBrushStops();
+ SyncFineTuneItemsToBrushStops(displayBusy);
}
/// <summary>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs
index 34d7e32cd..785472d0d 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs
@@ -36,6 +36,8 @@ using System.Windows.Media.Imaging;
using Tango.Touch.Components;
using Tango.PPC.Jobs.ViewContracts;
using Tango.Core.ExtensionMethods;
+using Tango.PPC.Common.Synchronization;
+using Tango.PPC.Jobs.NotificationItems;
namespace Tango.PPC.Jobs.ViewModels
{
@@ -46,7 +48,8 @@ namespace Tango.PPC.Jobs.ViewModels
public class JobsViewVM : PPCViewModel<IJobsView>
{
private ObservablesContext _db; //Holds the db context for the job list.
- private ObservableCollection<ColorCatalog> _catalogs; //Holds the available color catalogs.
+ private ObservableCollection<ColorCatalog> _catalogs; //Holds the available color catalogs for the site.
+ private ObservableCollection<Rml> _rmls; //Holds the available RML for the site.
public enum JobsCategory
{
@@ -411,6 +414,11 @@ namespace Tango.PPC.Jobs.ViewModels
Settings.SupportedColorSpaces.Count > 0 ? Settings.SupportedColorSpaces : Enum.GetValues(typeof(ColorSpaces)).Cast<ColorSpaces>().Where(x => x.IsUserSpace() || (ApplicationManager.IsInTechnicianMode && x == ColorSpaces.Volume)).ToList()
);
+ if (_catalogs.Count == 0)
+ {
+ vm.SupportedColorSpaces.Remove(ColorSpaces.Catalog);
+ }
+
CatalogSelectionViewVM catalogVM = new CatalogSelectionViewVM(_catalogs.ToList(), _catalogs.ToList().SingleOrDefault(x => x.Guid == settings.LastSelectedCatalogGuid));
if (settings.LastJobType != null)
@@ -483,7 +491,7 @@ namespace Tango.PPC.Jobs.ViewModels
settings.LastJobType = vm.SelectedJobType;
settings.LastJobColorSpace = vm.SelectedColorSpace;
-
+
if (vm.SelectedColorSpace == ColorSpaces.Catalog)
{
settings.LastSelectedCatalogGuid = catalogVM.SelectedCatalog.Guid;
@@ -503,7 +511,7 @@ namespace Tango.PPC.Jobs.ViewModels
job.ColorSpaceGuid = Adapter.ColorSpaces.FirstOrDefault(x => x.Code == vm.SelectedColorSpace.ToInt32()).Guid;
job.MachineGuid = MachineProvider.Machine.Guid;
job.UserGuid = AuthenticationProvider.CurrentUser.Guid;
- job.RmlGuid = Settings.DefaultRmlGuid != null ? Settings.DefaultRmlGuid : Adapter.Rmls.FirstOrDefault().Guid;
+ job.RmlGuid = Settings.DefaultRmlGuid != null ? Settings.DefaultRmlGuid : _rmls.FirstOrDefault().Guid;
job.WindingMethodGuid = Adapter.WindingMethods.FirstOrDefault().Guid;
job.SpoolTypeGuid = Settings.DefaultSpoolTypeGuid != null ? Settings.DefaultSpoolTypeGuid : Adapter.SpoolTypes.FirstOrDefault().Guid;
@@ -724,10 +732,13 @@ namespace Tango.PPC.Jobs.ViewModels
StorageProvider.RegisterFileHandler(ExplorerFileDefinition.Pulse.Extension, HandlePulseFileLoaded);
//Load catalogs.
- using (ObservablesContext c = ObservablesContext.CreateDefault())
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
{
- _catalogs = (await c.ColorCatalogs.ToListAsync()).ToObservableCollection();
+ _catalogs = await new CatalogsCollectionBuilder(db).SetAll().WithSite(MachineProvider.Machine.SiteGuid).BuildAsync();
+ _rmls = await new RmlsCollectionBuilder(db).SetAll().WithSite(MachineProvider.Machine.SiteGuid).BuildAsync();
}
+
+ MachineDataSynchronizer.SynchronizationEnded += MachineDataSynchronizer_SynchronizationEnded;
}
public override void OnNavigatedTo()
@@ -871,6 +882,25 @@ namespace Tango.PPC.Jobs.ViewModels
#endregion
+ #region Handle New Synchronized Jobs
+
+ private void MachineDataSynchronizer_SynchronizationEnded(object sender, SynchronizationEndedEventArgs e)
+ {
+ if (e.NewChangedJobs > 0)
+ {
+ var item = NotificationProvider.PushNotification<NewSynchronizardJobsNotificationItem>();
+ item.Pressed += (_, __) =>
+ {
+ LoadJobs(() =>
+ {
+ NotificationProvider.ShowSuccess("Your job list is now synchronized.");
+ });
+ };
+ }
+ }
+
+ #endregion
+
#region Color Profile Request
private void ExternalBridgeService_ColorProfileRequest(object sender, ColorProfileRequestEventArgs e)
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml
index 5f59549dd..97756ffd5 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobView.xaml
@@ -26,6 +26,8 @@
<BitmapImage x:Key="Image_Out_Of_Gamut" UriSource="../Images/JobView/error.png" />
<BitmapImage x:Key="Image_Replace_Color" UriSource="../Images/JobView/replace-color.png" />
<BitmapImage x:Key="Image_Color_Picker" UriSource="../Images/JobView/color-picker.png" />
+ <BitmapImage x:Key="Image_Transparent" UriSource="../Images/JobView/transparent.jpg" />
+ <BitmapImage x:Key="Image_TransparentSmall" UriSource="../Images/JobView/transparent_small.jpg" />
<Style TargetType="FrameworkElement" x:Key="Level1Container">
@@ -111,9 +113,24 @@
<StackPanel>
<StackPanel Orientation="Horizontal">
<Border Width="48" Height="48" CornerRadius="5" BorderThickness="1" BorderBrush="{StaticResource TangoGrayBrush}">
- <Border.Background>
- <SolidColorBrush Color="{Binding Color,IsAsync=True}"></SolidColorBrush>
- </Border.Background>
+ <Border.Style>
+ <Style TargetType="Border">
+ <Setter Property="Background">
+ <Setter.Value>
+ <SolidColorBrush Color="{Binding Color,IsAsync=True}" />
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding IsTransparent,IsAsync=True}" Value="True" >
+ <Setter Property="Background">
+ <Setter.Value>
+ <ImageBrush ImageSource="{StaticResource Image_TransparentSmall}" Stretch="None" />
+ </Setter.Value>
+ </Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
</Border>
<TextBlock Margin="30 0 0 0" FontSize="{StaticResource TangoTitleFontSize}">
@@ -147,6 +164,17 @@
<DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="Volume">
<Setter Property="ContentTemplate" Value="{StaticResource Volume_Template}" />
</DataTrigger>
+ <DataTrigger Binding="{Binding IsTransparent,IsAsync=True}" Value="True">
+ <Setter Property="ContentTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <Grid Height="40">
+ <TextBlock VerticalAlignment="Bottom" Foreground="{StaticResource TangoWarningBrush}">Transparent</TextBlock>
+ </Grid>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Style>
@@ -172,7 +200,10 @@
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0 0 -130 0" HorizontalAlignment="Right" VerticalAlignment="Top">
- <touch:TouchImageButton Command="{Binding ElementName=view,Path=DataContext.ReplaceBrushStopCommand,IsAsync=True}" CommandParameter="{Binding}" Visibility="{Binding ColorSpace,Converter={StaticResource ColorSpaceToVisibilityConverter},IsAsync=True}" Width="50" Height="50" Padding="10" Image="{StaticResource Image_Replace_Color}" CornerRadius="30"></touch:TouchImageButton>
+ <StackPanel Orientation="Horizontal" Visibility="{Binding ElementName=toggleEdit,Path=IsChecked,IsAsync=True,Converter={StaticResource BooleanToVisibilityInverseConverter}}">
+ <touch:TouchToggleIconButton Padding="15" Width="60" Height="60" CornerRadius="30" Icon="EyeOutline" CheckedIcon="EyeOffOutline" Foreground="{StaticResource TangoGrayBrush}" CheckedForeground="{StaticResource TangoWarningBrush}" IsChecked="{Binding IsTransparent,IsAsync=True}"></touch:TouchToggleIconButton>
+ <touch:TouchImageButton Command="{Binding ElementName=view,Path=DataContext.ReplaceBrushStopCommand,IsAsync=True}" CommandParameter="{Binding}" Visibility="{Binding ColorSpace,Converter={StaticResource ColorSpaceToVisibilityConverter},IsAsync=True}" Width="50" Height="50" Padding="10" Image="{StaticResource Image_Replace_Color}" CornerRadius="30"></touch:TouchImageButton>
+ </StackPanel>
<touch:TouchIconButton Margin="0 0 50 0" Visibility="{Binding ElementName=toggleEdit,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter}}" Command="{Binding ElementName=view,Path=DataContext.RemoveBrushStopCommand,IsAsync=True}" CommandParameter="{Binding}" EnableDropShadow="False" Icon="TrashAltRegular" Padding="12" Foreground="{StaticResource TangoPrimaryAccentBrush}" Width="50" Height="50" RippleBrush="{StaticResource TangoRippleDarkBrush}" CornerRadius="30" />
</StackPanel>
</Grid>
@@ -214,7 +245,11 @@
</Style.Triggers>
</Style>
</DockPanel.Style>
- <Border DockPanel.Dock="Left" Background="{Binding SegmentBrush}" BorderThickness="0 0 1 0" BorderBrush="{StaticResource TangoLightBorderBrush}">
+
+ <Border DockPanel.Dock="Left" BorderThickness="0 0 1 0" BorderBrush="{StaticResource TangoLightBorderBrush}">
+ <Border.Background>
+ <ImageBrush ImageSource="{StaticResource Image_Transparent}" Stretch="None" />
+ </Border.Background>
<Border.Style>
<Style TargetType="Border">
<Setter Property="CornerRadius" Value="8 0 0 8"></Setter>
@@ -233,6 +268,26 @@
</Style.Triggers>
</Style>
</Border.Style>
+ <Border Background="{Binding SegmentBrush}">
+ <Border.Style>
+ <Style TargetType="Border">
+ <Setter Property="CornerRadius" Value="8 0 0 8"></Setter>
+ <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight,IsAsync=True}"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding ElementName=toggle_small_list,Path=IsChecked,IsAsync=True}" Value="True">
+ <Setter Property="Width" Value="{Binding RelativeSource={RelativeSource Self},Path=ActualHeight,Converter={StaticResource MathOperatorConverter},ConverterParameter='*2',IsAsync=True}"></Setter>
+ </DataTrigger>
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding Converter={StaticResource IsSegmentGradientConverter},IsAsync=True}" Value="True"></Condition>
+ <Condition Binding="{Binding ElementName=toggle_large_list,Path=IsChecked,IsAsync=True}" Value="True"></Condition>
+ </MultiDataTrigger.Conditions>
+ <Setter Property="CornerRadius" Value="8 0 0 0"></Setter>
+ </MultiDataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Border.Style>
+ </Border>
</Border>
<Grid>
@@ -247,77 +302,90 @@
</TextBlock>
</StackPanel>
- <StackPanel Margin="0 30 0 0" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="300" Visibility="{Binding ElementName=toggle_large_list,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter},IsAsync=True}">
- <DockPanel LastChildFill="False">
- <DockPanel.Style>
- <Style TargetType="DockPanel">
- <Setter Property="Visibility" Value="Visible"></Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding Converter={StaticResource IsSegmentGradientConverter},IsAsync=True}" Value="True">
- <Setter Property="Visibility" Value="Collapsed"></Setter>
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </DockPanel.Style>
- <TextBlock VerticalAlignment="Bottom" DockPanel.Dock="Left" Text="Color code:"></TextBlock>
+ <Grid>
+ <StackPanel Margin="0 30 0 0" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="300" Visibility="{Binding ElementName=toggle_large_list,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter},IsAsync=True}">
+ <DockPanel LastChildFill="False">
+ <DockPanel.Style>
+ <Style TargetType="DockPanel">
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding Converter={StaticResource IsSegmentGradientConverter},IsAsync=True}" Value="True">
+ <Setter Property="Visibility" Value="Collapsed"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </DockPanel.Style>
+ <TextBlock VerticalAlignment="Bottom" DockPanel.Dock="Left" Text="Color code:"></TextBlock>
- <Grid DockPanel.Dock="Right" DataContext="{Binding BrushStops[0],IsAsync=True}">
- <StackPanel>
- <ContentControl Focusable="False" FocusVisualStyle="{x:Null}" d:DataContext="{d:DesignInstance Type=entities:BrushStop, IsDesignTimeCreatable=False}" Content="{Binding}" Width="180">
- <ContentControl.Style>
- <Style TargetType="ContentControl">
- <Setter Property="ContentTemplate">
- <Setter.Value>
- <DataTemplate>
+ <Grid DockPanel.Dock="Right" DataContext="{Binding BrushStops[0],IsAsync=True}">
+ <StackPanel>
+ <ContentControl Focusable="False" FocusVisualStyle="{x:Null}" d:DataContext="{d:DesignInstance Type=entities:BrushStop, IsDesignTimeCreatable=False}" Content="{Binding}" Width="180">
+ <ContentControl.Style>
+ <Style TargetType="ContentControl">
+ <Setter Property="ContentTemplate">
+ <Setter.Value>
+ <DataTemplate>
- </DataTemplate>
- </Setter.Value>
- </Setter>
- <Style.Triggers>
- <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="RGB">
- <Setter Property="ContentTemplate" Value="{StaticResource RGB_Template}" />
- </DataTrigger>
- <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="CMYK">
- <Setter Property="ContentTemplate" Value="{StaticResource CMYK_Template}" />
- </DataTrigger>
- <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="LAB">
- <Setter Property="ContentTemplate" Value="{StaticResource LAB_Template}" />
- </DataTrigger>
- <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="Catalog">
- <Setter Property="ContentTemplate" Value="{StaticResource CATALOG_Template}" />
- </DataTrigger>
- <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="Volume">
- <Setter Property="ContentTemplate" Value="{StaticResource Volume_Template}" />
- </DataTrigger>
- </Style.Triggers>
- </Style>
- </ContentControl.Style>
- </ContentControl>
- </StackPanel>
- </Grid>
- </DockPanel>
- <Canvas>
- <Canvas.Style>
- <Style TargetType="Canvas">
- <Setter Property="Visibility" Value="Collapsed"></Setter>
- <Style.Triggers>
- <MultiDataTrigger>
- <MultiDataTrigger.Conditions>
- <Condition Binding="{Binding Converter={StaticResource IsSegmentGradientConverter},IsAsync=True}" Value="False" />
- <Condition Binding="{Binding BrushStops[0].IsOutOfGamut,IsAsync=True}" Value="True" />
- </MultiDataTrigger.Conditions>
- <Setter Property="Visibility" Value="Visible"></Setter>
- </MultiDataTrigger>
- </Style.Triggers>
- </Style>
- </Canvas.Style>
- <TextBlock Canvas.Top="2" Foreground="{StaticResource TangoErrorBrush}" FontSize="{StaticResource TangoSmallFontSize}" Text="Color is out of gamut. Modify color or select an alternative."></TextBlock>
- </Canvas>
- <DockPanel LastChildFill="False" Margin="0 20 0 0">
- <TextBlock VerticalAlignment="Bottom" DockPanel.Dock="Left" Text="Length (m):"></TextBlock>
- <touch:TouchNumericTextBox Width="180" DockPanel.Dock="Right" Value="{Binding Length}" StringFormat="0.0" AutoCalculateJogStep="False" HasDecimalPoint="True" Minimum="1" Maximum="100000" KeyboardContainer="{Binding ElementName=Container}" />
- </DockPanel>
- </StackPanel>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="RGB">
+ <Setter Property="ContentTemplate" Value="{StaticResource RGB_Template}" />
+ </DataTrigger>
+ <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="CMYK">
+ <Setter Property="ContentTemplate" Value="{StaticResource CMYK_Template}" />
+ </DataTrigger>
+ <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="LAB">
+ <Setter Property="ContentTemplate" Value="{StaticResource LAB_Template}" />
+ </DataTrigger>
+ <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="Catalog">
+ <Setter Property="ContentTemplate" Value="{StaticResource CATALOG_Template}" />
+ </DataTrigger>
+ <DataTrigger Binding="{Binding ElementName=view,Path=DataContext.Job.ColorSpace.Name,IsAsync=True}" Value="Volume">
+ <Setter Property="ContentTemplate" Value="{StaticResource Volume_Template}" />
+ </DataTrigger>
+ <DataTrigger Binding="{Binding IsTransparent,IsAsync=True}" Value="True">
+ <Setter Property="ContentTemplate">
+ <Setter.Value>
+ <DataTemplate>
+ <Grid Height="40">
+ <TextBlock VerticalAlignment="Bottom" Foreground="{StaticResource TangoWarningBrush}">Transparent</TextBlock>
+ </Grid>
+ </DataTemplate>
+ </Setter.Value>
+ </Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </ContentControl.Style>
+ </ContentControl>
+ </StackPanel>
+ </Grid>
+ </DockPanel>
+ <Canvas>
+ <Canvas.Style>
+ <Style TargetType="Canvas">
+ <Setter Property="Visibility" Value="Collapsed"></Setter>
+ <Style.Triggers>
+ <MultiDataTrigger>
+ <MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding Converter={StaticResource IsSegmentGradientConverter},IsAsync=True}" Value="False" />
+ <Condition Binding="{Binding BrushStops[0].IsOutOfGamut,IsAsync=True}" Value="True" />
+ </MultiDataTrigger.Conditions>
+ <Setter Property="Visibility" Value="Visible"></Setter>
+ </MultiDataTrigger>
+ </Style.Triggers>
+ </Style>
+ </Canvas.Style>
+ <TextBlock Canvas.Top="2" Foreground="{StaticResource TangoErrorBrush}" FontSize="{StaticResource TangoSmallFontSize}" Text="Color is out of gamut. Modify color or select an alternative."></TextBlock>
+ </Canvas>
+ <DockPanel LastChildFill="False" Margin="0 20 0 0">
+ <TextBlock VerticalAlignment="Bottom" DockPanel.Dock="Left" Text="Length (m):"></TextBlock>
+ <touch:TouchNumericTextBox Width="180" DockPanel.Dock="Right" Value="{Binding Length}" StringFormat="0.0" AutoCalculateJogStep="False" HasDecimalPoint="True" Minimum="1" Maximum="100000" KeyboardContainer="{Binding ElementName=Container}" />
+ </DockPanel>
+ </StackPanel>
+ </Grid>
</DockPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 10 10 0">
@@ -334,23 +402,27 @@
</TextBlock.Style>
</TextBlock>
- <touch:TouchImageButton Command="{Binding ElementName=view,Path=DataContext.ReplaceBrushStopCommand}" CommandParameter="{Binding BrushStops[0]}" Width="50" Height="50" Padding="10" Image="{StaticResource Image_Replace_Color}" CornerRadius="30">
- <touch:TouchImageButton.Style>
- <Style TargetType="{x:Type touch:TouchImageButton}" BasedOn="{StaticResource {x:Type touch:TouchImageButton}}">
+ <StackPanel Orientation="Horizontal">
+ <StackPanel.Style>
+ <Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Collapsed"></Setter>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
+ <Condition Binding="{Binding ElementName=toggleEdit,Path=IsChecked,IsAsync=True}" Value="False" />
<Condition Binding="{Binding ElementName=toggle_large_list,Path=IsChecked,IsAsync=True}" Value="True" />
<Condition Binding="{Binding Converter={StaticResource IsSegmentGradientConverter},IsAsync=True}" Value="False" />
- <Condition Binding="{Binding BrushStops[0].ColorSpace,Converter={StaticResource ColorSpaceToVisibilityConverter},IsAsync=True}" Value="Visible" />
</MultiDataTrigger.Conditions>
<Setter Property="Visibility" Value="Visible"></Setter>
</MultiDataTrigger>
</Style.Triggers>
</Style>
- </touch:TouchImageButton.Style>
- </touch:TouchImageButton>
+ </StackPanel.Style>
+
+ <touch:TouchToggleIconButton Padding="15" Width="60" Height="60" CornerRadius="30" Icon="EyeOutline" CheckedIcon="EyeOffOutline" Foreground="{StaticResource TangoGrayBrush}" CheckedForeground="{StaticResource TangoWarningBrush}" IsChecked="{Binding BrushStops[0].IsTransparent,IsAsync=True}"></touch:TouchToggleIconButton>
+
+ <touch:TouchImageButton Visibility="{Binding BrushStops[0].ColorSpace,Converter={StaticResource ColorSpaceToVisibilityConverter},IsAsync=True}" Command="{Binding ElementName=view,Path=DataContext.ReplaceBrushStopCommand}" CommandParameter="{Binding BrushStops[0]}" Width="50" Height="50" Padding="10" Image="{StaticResource Image_Replace_Color}" CornerRadius="30"></touch:TouchImageButton>
+ </StackPanel>
<StackPanel Visibility="{Binding ElementName=toggleEdit,Path=IsChecked,Converter={StaticResource BooleanToVisibilityConverter},IsAsync=True}" Orientation="Horizontal">
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs
index 598b1a194..5077fd884 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/ViewModels/MainViewVM.cs
@@ -9,6 +9,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Data;
using Tango.BL;
+using Tango.BL.Builders;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.Core.Commands;
@@ -52,6 +53,13 @@ namespace Tango.PPC.MachineSettings.ViewModels
set { _selectedColorSpaces = value; RaisePropertyChangedAuto(); }
}
+ private ObservableCollection<Rml> _rmls;
+ public ObservableCollection<Rml> Rmls
+ {
+ get { return _rmls; }
+ set { _rmls = value; RaisePropertyChangedAuto(); }
+ }
+
private bool _enableHotSpot;
public bool EnableHotSpot
{
@@ -122,6 +130,27 @@ namespace Tango.PPC.MachineSettings.ViewModels
set { _defaultSpoolType = value; RaisePropertyChangedAuto(); }
}
+ private bool _synchronizeJobs;
+ public bool SynchronizeJobs
+ {
+ get { return _synchronizeJobs; }
+ set { _synchronizeJobs = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+ private bool _synchronizeDiagnostics;
+ public bool SynchronizeDiagnostics
+ {
+ get { return _synchronizeDiagnostics; }
+ set { _synchronizeDiagnostics = value; RaisePropertyChangedAuto(); InvalidateRelayCommands(); }
+ }
+
+ private bool _autoCheckForUpdates;
+ public bool AutoCheckForUpdates
+ {
+ get { return _autoCheckForUpdates; }
+ set { _autoCheckForUpdates = value; RaisePropertyChangedAuto(); }
+ }
+
#endregion
#region Commands
@@ -136,12 +165,18 @@ namespace Tango.PPC.MachineSettings.ViewModels
/// </summary>
public RelayCommand DiscardCommand { get; set; }
+ /// <summary>
+ /// Gets or sets the synchronize command.
+ /// </summary>
+ public RelayCommand SynchronizeCommand { get; set; }
+
#endregion
public MainViewVM()
{
SaveCommand = new RelayCommand(Save);
DiscardCommand = new RelayCommand(Discard);
+ SynchronizeCommand = new RelayCommand(Synchronize, () => !MachineDataSynchronizer.IsSynchronizing && IsFree && (SynchronizeJobs || SynchronizeDiagnostics));
}
private void Discard()
@@ -155,7 +190,7 @@ namespace Tango.PPC.MachineSettings.ViewModels
{
Settings.SupportedJobTypes = SelectedJobTypes.SynchedSource.ToList();
Settings.SupportedColorSpaces = SelectedColorSpaces.SynchedSource.ToList();
- Machine.MapPrimitivesWithStrings(MachineProvider.Machine);
+ Machine.MapPropertiesTo(MachineProvider.Machine, MappingFlags.NoReferenceTypes);
Settings.EnableHotSpot = EnableHotSpot;
Settings.HotSpotPassword = HotSpotPassword;
@@ -166,6 +201,12 @@ namespace Tango.PPC.MachineSettings.ViewModels
Settings.LockScreenPassword = LockScreenPassword;
Settings.DefaultRmlGuid = DefaultRML?.Guid;
Settings.DefaultSpoolTypeGuid = DefaultSpoolType?.Guid;
+ Settings.SynchronizeJobs = SynchronizeJobs;
+ Settings.SynchronizeDiagnostics = SynchronizeDiagnostics;
+ Settings.AutoCheckForUpdates = AutoCheckForUpdates;
+
+ MachineDataSynchronizer.IsEnabled = SynchronizeJobs || SynchronizeDiagnostics;
+
Settings.Save();
await MachineProvider.SaveMachine();
@@ -186,6 +227,18 @@ namespace Tango.PPC.MachineSettings.ViewModels
}
+ public async override void OnApplicationReady()
+ {
+ base.OnApplicationReady();
+ MachineDataSynchronizer.SynchronizationStarted += (_, __) => InvalidateRelayCommands();
+ MachineDataSynchronizer.SynchronizationEnded += (_, __) => InvalidateRelayCommands();
+
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ Rmls = await new RmlsCollectionBuilder(db).SetAll().WithSite(MachineProvider.Machine.SiteGuid).BuildAsync();
+ }
+ }
+
public override void OnNavigatedTo()
{
base.OnNavigatedTo();
@@ -216,6 +269,11 @@ namespace Tango.PPC.MachineSettings.ViewModels
DefaultRML = Adapter.Rmls.SingleOrDefault(x => x.Guid == Settings.DefaultRmlGuid);
DefaultSpoolType = Adapter.SpoolTypes.SingleOrDefault(x => x.Guid == Settings.DefaultSpoolTypeGuid);
+
+ SynchronizeJobs = Settings.SynchronizeJobs;
+ SynchronizeDiagnostics = Settings.SynchronizeDiagnostics;
+
+ AutoCheckForUpdates = Settings.AutoCheckForUpdates;
}
private async void OnEnableRemoteAssistanceChanged()
@@ -290,5 +348,29 @@ namespace Tango.PPC.MachineSettings.ViewModels
{
ExternalBridgeService.Enabled = EnableExternalBridge;
}
+
+ private async void Synchronize()
+ {
+ try
+ {
+ IsFree = false;
+ NotificationProvider.SetGlobalBusyMessage("Synchronizing...");
+
+ await MachineDataSynchronizer.Synchronize();
+
+ NotificationProvider.ReleaseGlobalBusyMessage();
+ await NotificationProvider.ShowSuccess("Synchronization completed successfully.");
+ }
+ catch (Exception ex)
+ {
+ NotificationProvider.ReleaseGlobalBusyMessage();
+ await NotificationProvider.ShowError($"Error occurred while trying to synchronize.\n{ex.FlattenMessage()}");
+ }
+ finally
+ {
+ NotificationProvider.ReleaseGlobalBusyMessage();
+ IsFree = true;
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml
index 0d9a3cea1..4a2f1e253 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.MachineSettings/Views/MainView.xaml
@@ -11,9 +11,9 @@
xmlns:global="clr-namespace:Tango.PPC.MachineSettings"
xmlns:local="clr-namespace:Tango.PPC.MachineSettings.Views"
mc:Ignorable="d"
- d:DesignHeight="2500" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
+ d:DesignHeight="3000" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:MainViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.MainViewVM}">
- <Grid Background="{StaticResource TangoMidBackgroundBrush}">
+ <Grid Background="{StaticResource TangoMidBackgroundBrush}" IsEnabled="{Binding IsFree}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="1*"/>
@@ -137,7 +137,7 @@
</ItemsControl>
<TextBlock VerticalAlignment="Bottom">Default Thread</TextBlock>
- <touch:TouchComboBox HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="200" ItemsSource="{Binding Adapter.Rmls}" SelectedItem="{Binding DefaultRML}" DisplayMemberPath="Name"></touch:TouchComboBox>
+ <touch:TouchComboBox HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="200" ItemsSource="{Binding Rmls}" SelectedItem="{Binding DefaultRML}" DisplayMemberPath="Name"></touch:TouchComboBox>
<TextBlock VerticalAlignment="Bottom">Default Spool</TextBlock>
<touch:TouchComboBox HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="200" ItemsSource="{Binding Adapter.SpoolTypes}" SelectedItem="{Binding DefaultSpoolType}" DisplayMemberPath="Name"></touch:TouchComboBox>
@@ -195,6 +195,59 @@
</DockPanel>
</StackPanel>
</touch:TouchExpander>
+
+ <!--SYNCHRONIZATION-->
+ <touch:TouchExpander Margin="0 20 0 0" Header="Cloud Synchronization" IsExpanded="True" FontSize="{StaticResource TangoExpanderHeaderFontSize}">
+ <StackPanel Margin="10 30 10 10">
+
+ <DockPanel TextElement.FontSize="{StaticResource TangoDefaultFontSize}">
+ <StackPanel>
+ <TextBlock VerticalAlignment="Center">Auto Update Check</TextBlock>
+ <DockPanel Margin="0 5 0 0">
+ <touch:TouchIcon VerticalAlignment="Top" Icon="InformationOutline" Foreground="{StaticResource TangoGrayTextBrush}"></touch:TouchIcon>
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Top" TextWrapping="Wrap" FontSize="{StaticResource TangoSmallFontSize}" Foreground="{StaticResource TangoGrayTextBrush}">
+ Automatically check for software and database updates.
+ </TextBlock>
+ </DockPanel>
+ </StackPanel>
+ <touch:TouchToggleSlider Margin="0 0 100 0" DockPanel.Dock="Right" Style="{StaticResource TangoToggleButtonGrayAccent}" HorizontalAlignment="Right" Width="90" IsChecked="{Binding AutoCheckForUpdates}"></touch:TouchToggleSlider>
+ </DockPanel>
+
+ <DockPanel Margin="0 40 0 0" TextElement.FontSize="{StaticResource TangoDefaultFontSize}">
+ <StackPanel>
+ <TextBlock VerticalAlignment="Center">Synchronize Jobs</TextBlock>
+ <DockPanel Margin="0 5 0 0">
+ <touch:TouchIcon VerticalAlignment="Top" Icon="InformationOutline" Foreground="{StaticResource TangoGrayTextBrush}"></touch:TouchIcon>
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Top" TextWrapping="Wrap" FontSize="{StaticResource TangoSmallFontSize}" Foreground="{StaticResource TangoGrayTextBrush}">
+ Synchronize your jobs with twine's cloud services.
+ </TextBlock>
+ </DockPanel>
+ </StackPanel>
+ <touch:TouchToggleSlider Margin="0 0 100 0" DockPanel.Dock="Right" Style="{StaticResource TangoToggleButtonGrayAccent}" HorizontalAlignment="Right" Width="90" IsChecked="{Binding SynchronizeJobs}"></touch:TouchToggleSlider>
+ </DockPanel>
+
+ <DockPanel Margin="0 40 0 0" TextElement.FontSize="{StaticResource TangoDefaultFontSize}">
+ <StackPanel>
+ <TextBlock VerticalAlignment="Center">Synchronize Diagnostics Data</TextBlock>
+ <DockPanel Margin="0 5 0 0">
+ <touch:TouchIcon VerticalAlignment="Top" Icon="InformationOutline" Foreground="{StaticResource TangoGrayTextBrush}"></touch:TouchIcon>
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Top" TextWrapping="Wrap" FontSize="{StaticResource TangoSmallFontSize}" Foreground="{StaticResource TangoGrayTextBrush}">
+ Help us improve your experience using this system.
+ </TextBlock>
+ </DockPanel>
+ </StackPanel>
+ <touch:TouchToggleSlider Margin="0 0 100 0" DockPanel.Dock="Right" Style="{StaticResource TangoToggleButtonGrayAccent}" HorizontalAlignment="Right" Width="90" IsChecked="{Binding SynchronizeDiagnostics}"></touch:TouchToggleSlider>
+ </DockPanel>
+
+ <DockPanel Margin="0 40 0 0">
+ <touch:TouchIcon VerticalAlignment="Top" Icon="InformationOutline" Foreground="{StaticResource TangoGrayTextBrush}"></touch:TouchIcon>
+ <TextBlock Margin="10 0 0 0" VerticalAlignment="Top" TextWrapping="Wrap" FontSize="{StaticResource TangoSmallFontSize}" Foreground="{StaticResource TangoGrayTextBrush}">
+ Once enabled, synchronization occurres automatically in the background. you can choose to synchronize right now.
+ </TextBlock>
+ </DockPanel>
+ <touch:TouchButton Command="{Binding SynchronizeCommand}" IsEnabled="{Binding MachineDataSynchronizer.IsEnabled}" HorizontalAlignment="Left" Margin="25 10 0 0" Style="{StaticResource TangoHollowButton}" FontSize="{StaticResource TangoDefaultFontSize}" Padding="15 10" CornerRadius="22">Synchronize Now</touch:TouchButton>
+ </StackPanel>
+ </touch:TouchExpander>
</StackPanel>
</touch:LightTouchScrollViewer>
</Grid>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/browser.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/browser.png
new file mode 100644
index 000000000..ebb975b6f
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/browser.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.png b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.png
new file mode 100644
index 000000000..46059c5c0
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Images/sync.png
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj
index 192b9ae11..e11e34298 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Tango.PPC.Technician.csproj
@@ -98,10 +98,14 @@
<Compile Include="ViewModels\LoggingViewVM.cs" />
<Compile Include="ViewModels\MainViewVM.cs" />
<Compile Include="ViewModels\PackagesViewVM.cs" />
+ <Compile Include="ViewModels\SynchronizationViewVM.cs" />
<Compile Include="ViewModels\SystemViewVM.cs" />
<Compile Include="Views\CatalogView.xaml.cs">
<DependentUpon>CatalogView.xaml</DependentUpon>
</Compile>
+ <Compile Include="Views\SynchronizationView.xaml.cs">
+ <DependentUpon>SynchronizationView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\PackagesView.xaml.cs">
<DependentUpon>PackagesView.xaml</DependentUpon>
</Compile>
@@ -169,6 +173,10 @@
<Project>{0BE74EEE-22CB-4DBA-B896-793B9E1A3AC0}</Project>
<Name>Tango.PPC.Common</Name>
</ProjectReference>
+ <ProjectReference Include="..\Tango.PPC.Browser\Tango.PPC.Browser.csproj">
+ <Project>{f02eaa84-ad59-465b-99a2-4422c13bfb72}</Project>
+ <Name>Tango.PPC.Browser</Name>
+ </ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="App.xaml">
@@ -191,6 +199,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\SynchronizationView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
<Page Include="Views\PackagesView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -234,5 +246,11 @@
<ItemGroup>
<Resource Include="Images\packages.png" />
</ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\sync.png" />
+ </ItemGroup>
+ <ItemGroup>
+ <Resource Include="Images\browser.png" />
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs
index c79a10e79..05a04e2a6 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModelLocator.cs
@@ -21,6 +21,7 @@ namespace Tango.PPC.Technician
TangoIOC.Default.Register<DispensersViewVM>();
TangoIOC.Default.Register<SystemViewVM>();
TangoIOC.Default.Register<PackagesViewVM>();
+ TangoIOC.Default.Register<SynchronizationViewVM>();
}
/// <summary>
@@ -88,5 +89,16 @@ namespace Tango.PPC.Technician
return TangoIOC.Default.GetInstance<PackagesViewVM>();
}
}
+
+ /// <summary>
+ /// Gets the synchronization view vm.
+ /// </summary>
+ public static SynchronizationViewVM SynchronizationViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<SynchronizationViewVM>();
+ }
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/CatalogViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/CatalogViewVM.cs
index 97bae6f5b..ecd2c7b93 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/CatalogViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/CatalogViewVM.cs
@@ -4,6 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.Core.Commands;
+using Tango.PPC.Browser;
+using Tango.PPC.Browser.Navigation;
+using Tango.PPC.Browser.Views;
using Tango.PPC.Common;
namespace Tango.PPC.Technician.ViewModels
@@ -16,16 +19,22 @@ namespace Tango.PPC.Technician.ViewModels
public RelayCommand<String> NavigationCommand { get; set; }
/// <summary>
+ /// Gets or sets the browser command.
+ /// </summary>
+ public RelayCommand BrowserCommand { get; set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="CatalogViewVM"/> class.
/// </summary>
public CatalogViewVM()
{
NavigationCommand = new RelayCommand<string>(NavigateToView);
+ BrowserCommand = new RelayCommand(OpenBrowserModule);
}
public override void OnApplicationStarted()
{
-
+
}
/// <summary>
@@ -36,5 +45,17 @@ namespace Tango.PPC.Technician.ViewModels
{
NavigationManager.NavigateTo<TechnicianModule>(view);
}
+
+ /// <summary>
+ /// Opens the browser module.
+ /// </summary>
+ private void OpenBrowserModule()
+ {
+ NavigationManager.NavigateWithObject<BrowserModule, BrowserView, BrowserNavigationRequest>(new BrowserNavigationRequest()
+ {
+ Address = "https://twine-s.com/",
+ DisplayAddressBar = true,
+ }, true);
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs
new file mode 100644
index 000000000..8036b99a4
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SynchronizationViewVM.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.PPC.Common;
+
+namespace Tango.PPC.Technician.ViewModels
+{
+ public class SynchronizationViewVM : PPCViewModel
+ {
+ public RelayCommand SynchronizeCommand { get; set; }
+
+ public SynchronizationViewVM()
+ {
+ SynchronizeCommand = new RelayCommand(Synchronize, () => !MachineDataSynchronizer.IsSynchronizing);
+ }
+
+ public override void OnApplicationStarted()
+ {
+
+ }
+
+ public override void OnApplicationReady()
+ {
+ base.OnApplicationReady();
+ MachineDataSynchronizer.SynchronizationStarted += (_, __) => InvalidateRelayCommands();
+ MachineDataSynchronizer.SynchronizationEnded += (_, __) => InvalidateRelayCommands();
+ }
+
+ private async void Synchronize()
+ {
+ try
+ {
+ await MachineDataSynchronizer.Synchronize();
+ }
+ catch { }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs
index b46e566d1..13aeeb671 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/ViewModels/SystemViewVM.cs
@@ -265,11 +265,11 @@ namespace Tango.PPC.Technician.ViewModels
{
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
- var jobs = await db.Jobs.Include(x => x.JobRuns).Where(x => x.MachineGuid == MachineProvider.Machine.Guid).ToListAsync();
+ var jobRuns = await db.JobRuns.Where(x => x.MachineGuid == MachineProvider.Machine.Guid).ToListAsync();
- TotalDyeTime = TimeSpan.FromHours(jobs.SelectMany(x => x.JobRuns).Select(x => x.EndDate - x.StartDate).Sum(x => x.TotalHours)).ToString(@"hh\:mm\:ss");
+ TotalDyeTime = TimeSpan.FromHours(jobRuns.Select(x => x.EndDate - x.StartDate).Sum(x => x.TotalHours)).ToString(@"hh\:mm\:ss");
- int meters = (int)jobs.SelectMany(x => x.JobRuns).Select(x => x.EndPosition).Sum();
+ int meters = (int)jobRuns.Select(x => x.EndPosition).Sum();
TotalDyeMeters = $"{meters.ToString("N0")} meters";
}
}
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml
index c13c3e3eb..b8c74c374 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/CatalogView.xaml
@@ -50,7 +50,7 @@
<Image Source="../Images/logging.png" Width="80" Height="80" />
<StackPanel Margin="10 0 0 0">
<TextBlock FontSize="{StaticResource TangoButtonFontSize}">Logging</TextBlock>
- <TextBlock Foreground="{StaticResource TangoGrayTextBrush}">
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" TextWrapping="Wrap" Width="580">
Display and investigate issues using application and embedded device logs.
</TextBlock>
</StackPanel>
@@ -62,7 +62,7 @@
<Image Source="../Images/system.png" Width="80" Height="80" />
<StackPanel Margin="10 0 0 0">
<TextBlock FontSize="{StaticResource TangoTitleFontSize}">System</TextBlock>
- <TextBlock Foreground="{StaticResource TangoGrayTextBrush}">
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" TextWrapping="Wrap" Width="580">
Display system properties, perform system actions, reset, shutdown etc...
</TextBlock>
</StackPanel>
@@ -74,7 +74,7 @@
<Image Source="../Images/dispensers.png" Width="80" Height="80" />
<StackPanel Margin="10 0 0 0">
<TextBlock FontSize="{StaticResource TangoButtonFontSize}">Dispensers</TextBlock>
- <TextBlock Foreground="{StaticResource TangoGrayTextBrush}">
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" TextWrapping="Wrap" Width="580">
Perform manual dispensers homing priming.
</TextBlock>
</StackPanel>
@@ -86,12 +86,36 @@
<Image Source="../Images/packages.png" Width="80" Height="80" />
<StackPanel Margin="10 0 0 0">
<TextBlock FontSize="{StaticResource TangoButtonFontSize}">Installed Packages</TextBlock>
- <TextBlock Foreground="{StaticResource TangoGrayTextBrush}">
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" TextWrapping="Wrap" Width="580">
View the history of update packages installation.
</TextBlock>
</StackPanel>
</StackPanel>
</touch:TouchButton>
+
+ <touch:TouchButton Command="{Binding NavigationCommand}" CommandParameter="SynchronizationView" Style="{StaticResource ButtonMenu}">
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
+ <Image Source="../Images/sync.png" Width="80" Height="80" />
+ <StackPanel Margin="10 0 0 0">
+ <TextBlock FontSize="{StaticResource TangoButtonFontSize}">Synchronization</TextBlock>
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" TextWrapping="Wrap" Width="580">
+ View the current status and history of synchronization operations to the machine service.
+ </TextBlock>
+ </StackPanel>
+ </StackPanel>
+ </touch:TouchButton>
+
+ <touch:TouchButton Command="{Binding BrowserCommand}" Style="{StaticResource ButtonMenu}">
+ <StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
+ <Image Source="../Images/browser.png" RenderOptions.BitmapScalingMode="Fant" Width="80" Height="80" />
+ <StackPanel Margin="10 0 0 0">
+ <TextBlock FontSize="{StaticResource TangoButtonFontSize}">Browser</TextBlock>
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" TextWrapping="Wrap" Width="580">
+ Open the browser module and navigate the web.
+ </TextBlock>
+ </StackPanel>
+ </StackPanel>
+ </touch:TouchButton>
</StackPanel>
</Grid>
</Grid>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml
index 733a2d713..2acadb32d 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/MainView.xaml
@@ -18,6 +18,7 @@
<local:DispensersView/>
<local:SystemView/>
<local:PackagesView/>
+ <local:SynchronizationView/>
</controls:NavigationControl>
</Grid>
</UserControl>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/PackagesView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/PackagesView.xaml
index f4708448c..a7944497b 100644
--- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/PackagesView.xaml
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/PackagesView.xaml
@@ -26,7 +26,7 @@
<Grid Grid.Row="1">
<Grid Margin="20">
- <touch:TouchSimpleDataGrid AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="FullRow" BorderThickness="1" BorderBrush="{StaticResource TangoDarkForegroundBrush}" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserResizeColumns="False" CanUserSortColumns="False" IsReadOnly="True" ItemsSource="{Binding Packages}" VerticalGridLinesBrush="{x:Null}" HorizontalGridLinesBrush="{StaticResource TangoGrayBrush}" RowHeight="50" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
+ <touch:TouchSimpleDataGrid Background="{StaticResource TangoPrimaryBackgroundBrush}" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="FullRow" BorderThickness="1" BorderBrush="{StaticResource TangoDarkForegroundBrush}" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserResizeColumns="False" CanUserSortColumns="False" IsReadOnly="True" ItemsSource="{Binding Packages}" VerticalGridLinesBrush="{x:Null}" HorizontalGridLinesBrush="{StaticResource TangoGrayBrush}" RowHeight="50" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
<DataGrid.Resources>
<Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="Background" Value="{StaticResource TangoDarkForegroundBrush}" />
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml
new file mode 100644
index 000000000..a0021d40e
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml
@@ -0,0 +1,133 @@
+<UserControl x:Class="Tango.PPC.Technician.Views.SynchronizationView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.PPC.Technician.Views"
+ xmlns:sys="clr-namespace:System;assembly=mscorlib"
+ xmlns:vm="clr-namespace:Tango.PPC.Technician.ViewModels"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:converters="clr-namespace:Tango.PPC.Technician.Converters"
+ xmlns:global="clr-namespace:Tango.PPC.Technician"
+ mc:Ignorable="d"
+ d:DesignHeight="1280" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:SynchronizationViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.SynchronizationViewVM}">
+
+ <UserControl.Resources>
+ <converters:LogItemMessageToOneLineConverter x:Key="LogItemMessageToOneLineConverter" />
+ </UserControl.Resources>
+
+ <Grid Background="{StaticResource TangoMidBackgroundBrush}">
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto"/>
+ <RowDefinition Height="1*"/>
+ </Grid.RowDefinitions>
+
+ <Border Padding="20" Background="{StaticResource TangoPrimaryBackgroundBrush}" BorderThickness="0 0 0 1" BorderBrush="{StaticResource TangoDividerBrush}">
+ <Border.Effect>
+ <DropShadowEffect Color="Silver" ShadowDepth="0" BlurRadius="20" Opacity="1" />
+ </Border.Effect>
+ <TextBlock VerticalAlignment="Center" FontSize="{StaticResource TangoHeaderFontSize}" FontWeight="SemiBold">Synchronization</TextBlock>
+ </Border>
+
+ <Grid Grid.Row="1">
+
+ <DockPanel>
+ <DockPanel DockPanel.Dock="Bottom">
+ <DockPanel Margin="20 0 20 20">
+ <touch:TouchButton IsEnabled="{Binding MachineDataSynchronizer.IsEnabled}" DockPanel.Dock="Right" Padding="50 20" CornerRadius="30" Command="{Binding SynchronizeCommand}">Synchronize Now</touch:TouchButton>
+ <TextBlock Foreground="{StaticResource TangoGrayTextBrush}" VerticalAlignment="Center" TextWrapping="Wrap" Margin="0 0 20 0">Synchronization occurres automatically in the background. You can choose to synchronize now.</TextBlock>
+ </DockPanel>
+ </DockPanel>
+
+ <Grid Margin="20">
+ <touch:TouchSimpleDataGrid Background="{StaticResource TangoPrimaryBackgroundBrush}" AutoGenerateColumns="False" SelectionMode="Single" SelectionUnit="FullRow" BorderThickness="1" BorderBrush="{StaticResource TangoDarkForegroundBrush}" HeadersVisibility="Column" CanUserAddRows="False" CanUserDeleteRows="False" CanUserReorderColumns="False" CanUserResizeRows="False" CanUserResizeColumns="False" CanUserSortColumns="False" IsReadOnly="True" ItemsSource="{Binding MachineDataSynchronizer.StatusHistory}" SelectedItem="{Binding SelectedStatus}" VerticalGridLinesBrush="{x:Null}" HorizontalGridLinesBrush="{StaticResource TangoGrayBrush}" RowHeight="50" VerticalScrollBarVisibility="Visible" HorizontalScrollBarVisibility="Disabled">
+ <DataGrid.Resources>
+ <Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}">
+ <Setter Property="Background" Value="{StaticResource TangoDarkForegroundBrush}" />
+ <Setter Property="Foreground" Value="{StaticResource TangoLightForegroundBrush}" />
+ <Setter Property="Padding" Value="5"></Setter>
+ </Style>
+ </DataGrid.Resources>
+ <DataGrid.RowStyle>
+ <Style TargetType="DataGridRow" BasedOn="{StaticResource {x:Type DataGridRow}}">
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoPrimaryAccentBrush}" />
+ </Trigger>
+ <Trigger Property="IsFocused" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoPrimaryAccentBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.RowStyle>
+ <DataGrid.CellStyle>
+ <Style TargetType="{x:Type DataGridCell}">
+ <Setter Property="Template">
+ <Setter.Value>
+ <ControlTemplate TargetType="{x:Type DataGridCell}">
+ <Grid Background="{TemplateBinding Background}">
+ <ContentPresenter VerticalAlignment="Center" />
+ </Grid>
+ </ControlTemplate>
+ </Setter.Value>
+ </Setter>
+ <Style.Triggers>
+ <Trigger Property="IsSelected" Value="True">
+ <Setter Property="Background" Value="Transparent"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoPrimaryAccentBrush}" />
+ </Trigger>
+ </Style.Triggers>
+ </Style>
+ </DataGrid.CellStyle>
+ <DataGrid.Columns>
+ <DataGridTemplateColumn Header="" Width="50">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <touch:TouchIcon Width="16">
+ <touch:TouchIcon.Style>
+ <Style TargetType="touch:TouchIcon">
+ <Setter Property="Icon" Value="Pause"></Setter>
+ <Style.Triggers>
+ <DataTrigger Binding="{Binding State}" Value="Pending">
+ <Setter Property="Icon" Value="Pause"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoGrayBrush}"></Setter>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding State}" Value="Synchronizing">
+ <Setter Property="Icon" Value="CloudSync"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoWarningBrush}"></Setter>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding State}" Value="Failed">
+ <Setter Property="Icon" Value="Alert"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoErrorBrush}"></Setter>
+ </DataTrigger>
+ <DataTrigger Binding="{Binding State}" Value="Completed">
+ <Setter Property="Icon" Value="Check"></Setter>
+ <Setter Property="Foreground" Value="{StaticResource TangoGreenBrush}"></Setter>
+ </DataTrigger>
+ </Style.Triggers>
+ </Style>
+ </touch:TouchIcon.Style>
+ </touch:TouchIcon>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ <DataGridTextColumn Header="Start Time" Width="120" Binding="{Binding StartDateTime,StringFormat=t}" />
+ <DataGridTextColumn Header="Status" Width="120" Binding="{Binding State,Converter={StaticResource EnumToDescriptionConverter}}" />
+ <DataGridTextColumn Header="Duration" Width="120" Binding="{Binding Duration,StringFormat='hh\\:mm\\:ss'}" />
+ <DataGridTemplateColumn Header="Message" Width="1*">
+ <DataGridTemplateColumn.CellTemplate>
+ <DataTemplate>
+ <TextBlock Text="{Binding Message,Converter={StaticResource StringEllipsisConverter},ConverterParameter='70',Mode=OneWay}"/>
+ </DataTemplate>
+ </DataGridTemplateColumn.CellTemplate>
+ </DataGridTemplateColumn>
+ </DataGrid.Columns>
+ </touch:TouchSimpleDataGrid>
+ </Grid>
+ </DockPanel>
+
+ </Grid>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs
new file mode 100644
index 000000000..7193d66ff
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Technician/Views/SynchronizationView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.PPC.Technician.Views
+{
+ /// <summary>
+ /// Interaction logic for SynchronizationView.xaml
+ /// </summary>
+ public partial class SynchronizationView : UserControl
+ {
+ public SynchronizationView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/CefInstaller.cs b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/CefInstaller.cs
new file mode 100644
index 000000000..61a4077fe
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/CefInstaller.cs
@@ -0,0 +1,59 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tango.Core;
+using Tango.Core.Helpers;
+using Tango.PPC.Common.UpdatePackages;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Packages.CefInstaller
+{
+ [PPCPackage(PackageType.Post, "Installing Web Browser", true)]
+ public class CefInstaller : ExtendedObject, IPPCPackage
+ {
+ public Task Run(PackageContext context)
+ {
+ return Task.Factory.StartNew(() =>
+ {
+ LogManager.Log("Downloading cef binaries...");
+
+ var tempFolder = TemporaryManager.CreateFolder();
+ var zipFile = TemporaryManager.CreateImaginaryFile();
+
+ try
+ {
+ for (int i = 0; i < 100; i++)
+ {
+ context.ReportProgress("Downloading cef binaries...", false, i, 100);
+ Thread.Sleep(100);
+ }
+
+ //using (AutoFileDownloader downloader = new AutoFileDownloader("", "", zipFile))
+ //{
+ // downloader.Progress += (x, e) =>
+ // {
+ // context.ReportProgress("Downloading cef binaries...", false, e.Current, e.Total);
+ // };
+
+ // downloader.Download().GetAwaiter().GetResult();
+ //}
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error downloading cef.");
+ throw;
+ }
+ finally
+ {
+ tempFolder.Delete();
+ zipFile.Delete();
+ }
+
+ });
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Properties/AssemblyInfo.cs b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..9ddf67db3
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/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.PPC.Packages.CefInstaller")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Tango.PPC.Packages.CefInstaller")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[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("df64460a-6617-4338-872a-dc43fd994c48")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj
new file mode 100644
index 000000000..42f996079
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Packages/Tango.PPC.Packages.CefInstaller/Tango.PPC.Packages.CefInstaller.csproj
@@ -0,0 +1,69 @@
+<?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>{DF64460A-6617-4338-872A-DC43FD994C48}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Tango.PPC.Packages.CefInstaller</RootNamespace>
+ <AssemblyName>Tango.PPC.Packages.CefInstaller</AssemblyName>
+ <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <Deterministic>true</Deterministic>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <DebugSymbols>true</DebugSymbols>
+ <DebugType>full</DebugType>
+ <Optimize>false</Optimize>
+ <OutputPath>..\..\..\Build\PPC\Debug\Packages\</OutputPath>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <DebugType>pdbonly</DebugType>
+ <Optimize>true</Optimize>
+ <OutputPath>..\..\..\Build\PPC\Release\Packages\</OutputPath>
+ <DefineConstants>TRACE</DefineConstants>
+ <ErrorReport>prompt</ErrorReport>
+ <WarningLevel>4</WarningLevel>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ <Reference Include="System.Core" />
+ <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="CefInstaller.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\..\Tango.Core\Tango.Core.csproj">
+ <Project>{A34EE0F0-649D-41C8-8489-B6F1CC6924EE}</Project>
+ <Name>Tango.Core</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Logging\Tango.Logging.csproj">
+ <Project>{bc932dbd-7cdb-488c-99e4-f02cf441f55e}</Project>
+ <Name>Tango.Logging</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ <ProjectReference Include="..\..\..\Tango.Transport\Tango.Transport.csproj">
+ <Project>{74e700b0-1156-4126-be40-ee450d3c3026}</Project>
+ <Name>Tango.Transport</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.PPC.Common\Tango.PPC.Common.csproj">
+ <Project>{0be74eee-22cb-4dba-b896-793b9e1a3ac0}</Project>
+ <Name>Tango.PPC.Common</Name>
+ <Private>False</Private>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs
index 1474eaa04..8f108eaf6 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Application/IPPCApplicationManager.cs
@@ -96,6 +96,11 @@ namespace Tango.PPC.Common.Application
Version Version { get; }
/// <summary>
+ /// Gets the firmware version.
+ /// </summary>
+ Version FirmwareVersion { get; }
+
+ /// <summary>
/// Gets the application build date.
/// </summary>
String BuildDate { get; }
@@ -106,6 +111,11 @@ namespace Tango.PPC.Common.Application
DateTime StartUpDate { get; }
/// <summary>
+ /// Gets or sets the application folder.
+ /// </summary>
+ String StartPath { get; }
+
+ /// <summary>
/// Gets or sets a value indicating whether the screen is currently locked.
/// </summary>
bool IsScreenLocked { get; set; }
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs
index 8cccc43a7..eae09a7e7 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Connection/DefaultMachineProvider.cs
@@ -134,6 +134,12 @@ namespace Tango.PPC.Common.Connection
try
{
await MachineOperator.Connect();
+
+ if (MachineOperator.DeviceInformation != null)
+ {
+ settings.FirmwareVersion = MachineOperator.DeviceInformation.Version;
+ settings.Save();
+ }
}
catch (Exception)
{
@@ -156,6 +162,12 @@ namespace Tango.PPC.Common.Connection
try
{
await MachineOperator.Connect();
+
+ if (MachineOperator.DeviceInformation != null)
+ {
+ settings.FirmwareVersion = MachineOperator.DeviceInformation.Version;
+ settings.Save();
+ }
}
catch (Exception)
{
@@ -186,6 +198,12 @@ namespace Tango.PPC.Common.Connection
LogManager.Log("Connecting machine operator...");
await MachineOperator.Connect();
+ if (MachineOperator.DeviceInformation != null)
+ {
+ settings.FirmwareVersion = MachineOperator.DeviceInformation.Version;
+ settings.Save();
+ }
+
await Task.Delay(1000);
await MachineOperator.UploadHardwareConfiguration(Machine.Configuration.HardwareVersion, Machine.Configuration);
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/KeyboardHelper.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/KeyboardHelper.cs
new file mode 100644
index 000000000..202f0378e
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Helpers/KeyboardHelper.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Touch.Keyboard;
+
+namespace Tango.PPC.Common.Helpers
+{
+ public static class KeyboardHelper
+ {
+ public static void OpenKeyboard(KeyboardActionKeyMode action, TouchKeyboardMode mode = TouchKeyboardMode.AlphaNumeric)
+ {
+ KeyboardView.Keyboard.ActionKeyMode = action;
+ KeyboardView.Keyboard.Mode = mode;
+ KeyboardView.Default.IsOpened = true;
+ }
+
+ public static void CloseKeyboard()
+ {
+ KeyboardView.Default.IsOpened = false;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs
index f1c722d96..dfa9b833b 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs
@@ -44,6 +44,7 @@ namespace Tango.PPC.Common.MachineSetup
private IOperationSystemManager _windows_manager;
private PPCWebClient _client;
private List<LogItemBase> _logs;
+ private bool _isUpdating;
#region Events
@@ -93,7 +94,10 @@ namespace Tango.PPC.Common.MachineSetup
private void LogManager_NewLog(object sender, LogItemBase e)
{
- _logs.Add(e);
+ if (_isUpdating)
+ {
+ _logs.Add(e);
+ }
}
#endregion
@@ -136,6 +140,8 @@ namespace Tango.PPC.Common.MachineSetup
LogManager.Log(xx, "Error notifying setup completed.");
}
}
+
+ _isUpdating = false;
}
private async void OnCompleted(MachineSetupResult result, TaskCompletionSource<MachineSetupResult> completionSource, MachineSetupResponse response)
@@ -157,6 +163,8 @@ namespace Tango.PPC.Common.MachineSetup
LogManager.Log(xx, "Error notifying setup completed.");
}
}
+
+ _isUpdating = false;
}
private String GetLogsStringAndClear()
@@ -186,6 +194,8 @@ namespace Tango.PPC.Common.MachineSetup
try
{
+ _isUpdating = true;
+
LogManager.Log($"Starting machine setup for serial number {serialNumber}...");
var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs
index 3655aa462..421b4ee54 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/IMachineUpdateManager.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.PMR.Synchronization;
+using Tango.PPC.Common.Publish;
using Tango.PPC.Common.UpdatePackages;
using Tango.PPC.Common.Web;
@@ -19,7 +20,7 @@ namespace Tango.PPC.Common.MachineUpdate
/// <summary>
/// Gets or sets a value indicating whether to automatically check for new application updates.
/// </summary>
- bool AutoCheckForUpdates { get; set; }
+ bool EnableAutoCheckForUpdates { get; set; }
/// <summary>
/// Gets the current machine update progress status.
@@ -43,14 +44,14 @@ namespace Tango.PPC.Common.MachineUpdate
/// <param name="setupFirmware">if set to <c>true</c> updates the embedded device firmware.</param>
/// <param name="setupFPGA">if set to <c>true</c> updates the embedded device FPGA version and other parameters.</param>
/// <returns></returns>
- Task<MachineUpdateResult> Update(String serialNumber, bool setupFirmware, bool setupFPGA);
+ Task<MachineUpdateResult> Update(bool setupFirmware, bool setupFPGA);
/// <summary>
/// Performs a machine update using the specified software update package path.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <returns></returns>
- Task<MachineUpdateResult> UpdateFromTUP(String fileName);
+ Task<MachineUpdateResult> UpdateFromTUP(String fileName, bool setupFirmware, bool setupFPGA);
/// <summary>
/// Checks if any update are available for the specified machine serial number.
@@ -77,7 +78,7 @@ namespace Tango.PPC.Common.MachineUpdate
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns></returns>
- Task<UpdatePackageFile> GetUpdatePackageFileInfo(String filePath);
+ Task<PublishInfo> GetUpdatePackageFileInfo(String filePath);
/// <summary>
/// Checks whether any post update packages needs to be installed.
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
index 5296a9f34..088e80f61 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs
@@ -22,6 +22,7 @@ using Tango.PMR.Synchronization;
using Tango.PPC.Common.Application;
using Tango.PPC.Common.Connection;
using Tango.PPC.Common.Navigation;
+using Tango.PPC.Common.Publish;
using Tango.PPC.Common.UpdatePackages;
using Tango.PPC.Common.Web;
using Tango.Settings;
@@ -40,6 +41,7 @@ namespace Tango.PPC.Common.MachineUpdate
private List<LogItemBase> _logs;
private System.Timers.Timer _checkForUpdateTimer;
private bool _isUpdating;
+ private PPCSettings _settings;
#region Events
@@ -76,7 +78,7 @@ namespace Tango.PPC.Common.MachineUpdate
/// <summary>
/// Gets or sets a value indicating whether to automatically check for new application updates.
/// </summary>
- public bool AutoCheckForUpdates
+ public bool EnableAutoCheckForUpdates
{
get { return _autoCheckForUpdates; }
set { _autoCheckForUpdates = value; RaisePropertyChangedAuto(); }
@@ -96,7 +98,7 @@ namespace Tango.PPC.Common.MachineUpdate
_machineProvider = machineProvider;
_app_manager = applicationManager;
_packageRunner = packageRunner;
- _packageRunner.PackageStateChanged += _packageRunner_PackageStateChanged;
+ _packageRunner.PackageProgress += _packageRunner_PackageProgress;
_logs = new List<LogItemBase>();
LogManager.NewLog += LogManager_NewLog;
@@ -104,20 +106,25 @@ namespace Tango.PPC.Common.MachineUpdate
_checkForUpdateTimer = new System.Timers.Timer(TimeSpan.FromMinutes(1).TotalMilliseconds);
_checkForUpdateTimer.Elapsed += _checkForUpdateTimer_Elapsed;
_checkForUpdateTimer.Start();
+
+ _settings = SettingsManager.Default.GetOrCreate<PPCSettings>();
}
#endregion
#region Event Handlers
- private void _packageRunner_PackageStateChanged(object sender, PackageStateChangedEventArgs e)
+ private void _packageRunner_PackageProgress(object sender, PackageProgressEventArgs e)
{
- UpdateProgress(e.PackageType == PackageType.Pre ? "Preparing" : "Finalizing", e.PackageName);
+ UpdateProgress(e.PackageName, e.Message, e.IsIntermediate, e.Progress, e.Total);
}
private void LogManager_NewLog(object sender, LogItemBase e)
{
- _logs.Add(e);
+ if (_isUpdating)
+ {
+ _logs.Add(e);
+ }
}
#endregion
@@ -133,37 +140,80 @@ namespace Tango.PPC.Common.MachineUpdate
});
}
- private async void OnFailed(Exception ex, TaskCompletionSource<MachineUpdateResult> completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, Tango.Core.DataSource localDataSource)
+ private async void OnFailed(Exception ex, TaskCompletionSource<MachineUpdateResult> completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, String backupsFolder, String tempDbName, Tango.Core.DataSource localDataSource, String tempUpdatePackageFolder = null)
{
LogManager.Log(ex, "An error occurred in machine update.");
- if (performDatabaseRollback)
+ await Task.Factory.StartNew(() =>
{
- LogManager.Log("Rolling back database changes...");
- using (DbManager db = DbManager.FromDataSource(localDataSource))
+ if (performDatabaseRollback)
+ {
+ LogManager.Log("Rolling back database changes...");
+
+ using (DbManager db = DbManager.FromDataSource(localDataSource))
+ {
+ try
+ {
+ UpdateProgress("Rollback", "Rolling back database changes...");
+ db.Restore(localDataSource.Catalog, dbBackupFile);
+ LogManager.Log("Database restored successfully.");
+ }
+ catch (Exception e)
+ {
+ LogManager.Log(e, "Could not rollback the database.");
+ }
+ finally
+ {
+ try
+ {
+ File.Delete(dbBackupFile);
+ }
+ catch { }
+ }
+ }
+ }
+
+ if (tempDbName != null)
{
try
{
- UpdateProgress("Rollback", "Rolling back database changes...");
- await Task.Factory.StartNew(() => db.Restore(localDataSource.Catalog, dbBackupFile));
- LogManager.Log("Database restored successfully.");
+ LogManager.Log($"Removing temporary database '{tempDbName}'...");
+ using (DbManager dbManager = DbManager.FromDataSource(localDataSource))
+ {
+ dbManager.SetOffline(tempDbName);
+ dbManager.SetOnline(tempDbName);
+ dbManager.Delete(tempDbName);
+ }
}
- catch (Exception e)
+ catch (Exception exx)
{
- LogManager.Log(e, "Could not rollback the database.");
- throw ex;
+ LogManager.Log(exx, "Error removing temporary database.");
}
- finally
+ }
+
+ try
+ {
+ Directory.Delete(backupsFolder, true);
+ }
+ catch (Exception ee)
+ {
+ LogManager.Log(ee, $"Error deleting backups folder '{backupsFolder}'.");
+ }
+
+ if (tempUpdatePackageFolder != null)
+ {
+ try
{
- try
- {
- File.Delete(dbBackupFile);
- }
- catch { }
+ Directory.Delete(tempUpdatePackageFolder, true);
+ }
+ catch (Exception eee)
+ {
+ LogManager.Log(eee, "Error removing temporary package folder.");
}
}
- }
+
+ });
completionSource.SetException(ex);
@@ -188,13 +238,50 @@ namespace Tango.PPC.Common.MachineUpdate
_isUpdating = false;
}
- private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource<MachineUpdateResult> completionSource, DownloadUpdateResponse response, String dbBackupFile)
+ private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource<MachineUpdateResult> completionSource, DownloadUpdateResponse response, String tempDbName, String backupsFolder, Core.DataSource localDataSource)
{
- try
+ await Task.Factory.StartNew(() =>
{
- File.Delete(dbBackupFile);
- }
- catch { }
+ if (tempDbName != null)
+ {
+ try
+ {
+ LogManager.Log($"Removing temporary database '{tempDbName}'...");
+ using (DbManager dbManager = DbManager.FromDataSource(localDataSource))
+ {
+ dbManager.SetOffline(tempDbName);
+ dbManager.SetOnline(tempDbName);
+ dbManager.Delete(tempDbName);
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error removing temporary database.");
+ }
+ }
+
+ try
+ {
+ Directory.Delete(backupsFolder, true);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error deleting backups folder '{backupsFolder}'.");
+ }
+
+ if (!result.RequiresBinariesUpdate)
+ {
+ try
+ {
+ Directory.Delete(result.UpdatePackagePath, true);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error removing temporary package folder.");
+ }
+ }
+
+ });
completionSource.SetResult(result);
@@ -315,7 +402,7 @@ namespace Tango.PPC.Common.MachineUpdate
/// or
/// </exception>
/// <exception cref="System.InvalidProgramException">Database tango does not exists.</exception>
- public async Task<MachineUpdateResult> Update(String serialNumber, bool setupFirmware, bool setupFPGA)
+ public async Task<MachineUpdateResult> Update(bool setupFirmware, bool setupFPGA)
{
_logs.Clear();
@@ -325,12 +412,19 @@ namespace Tango.PPC.Common.MachineUpdate
bool performDatabaseRollback = false;
String dbBackupFile = null;
DownloadUpdateResponse update_response = null;
+ String backupsFolder = "C:\\Backups";
+
+ //Create temporary folders for packages.
+ var _newPackageTempFolder = TemporaryManager.CreateFolder();
+ _newPackageTempFolder.Persist = true;
+
+ String serialNumber = _machineProvider.Machine.SerialNumber;
try
{
_isUpdating = true;
- var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
+ var machineServiceAddress = _settings.GetMachineServiceAddress();
LogManager.Log($"Starting machine update for serial number {serialNumber}...");
@@ -371,10 +465,6 @@ namespace Tango.PPC.Common.MachineUpdate
LogManager.Log($"Machine update response received: {Environment.NewLine}{update_response.ToJsonString()}");
- //Create temporary folders for packages.
- var _newPackageTempFolder = TemporaryManager.CreateFolder();
- _newPackageTempFolder.Persist = true;
-
LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}.");
//Download software package.
@@ -413,8 +503,12 @@ namespace Tango.PPC.Common.MachineUpdate
UpdateProgress("Downloading software package", "Extracting package...");
LogManager.Log("Extracting downloaded zip file...");
- //Extract software package.
- ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder);
+
+ await Task.Factory.StartNew(() =>
+ {
+ //Extract software package.
+ ZipFile.ExtractToDirectory(tempFile, _newPackageTempFolder);
+ });
LogManager.Log("Copying latest updater utility to application path...");
//Copy new updater utility to app path.
@@ -464,8 +558,8 @@ namespace Tango.PPC.Common.MachineUpdate
//Create Database Backup
try
{
- Directory.CreateDirectory("C:\\Backups");
- dbBackupFile = $"C:\\Backups\\{Path.GetRandomFileName()}.bak";
+ Directory.CreateDirectory(backupsFolder);
+ dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak";
LogManager.Log($"Creating database backup to '{dbBackupFile}'...");
await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile));
performDatabaseRollback = true;
@@ -548,7 +642,7 @@ namespace Tango.PPC.Common.MachineUpdate
handler.Failed += (_, ex) =>
{
stream.Dispose();
- OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, localDataSource);
+ OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder);
};
handler.Completed += (_, __) =>
{
@@ -557,12 +651,12 @@ namespace Tango.PPC.Common.MachineUpdate
OnCompleted(new MachineUpdateResult()
{
UpdatePackagePath = _newPackageTempFolder,
- }, result, update_response, dbBackupFile);
+ }, result, update_response, null, backupsFolder, localDataSource);
};
handler.Canceled += (_, __) =>
{
stream.Dispose();
- OnFailed(new Exception("The operation has been canceled."), result, update_response, performDatabaseRollback, dbBackupFile, localDataSource);
+ OnFailed(new Exception("The operation has been canceled."), result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder);
};
handler.Progress += (_, e) =>
{
@@ -574,12 +668,12 @@ namespace Tango.PPC.Common.MachineUpdate
OnCompleted(new MachineUpdateResult()
{
UpdatePackagePath = _newPackageTempFolder,
- }, result, update_response, dbBackupFile);
+ }, result, update_response, null, backupsFolder, localDataSource);
}
}
catch (Exception ex)
{
- OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, localDataSource);
+ OnFailed(ex, result, update_response, performDatabaseRollback, dbBackupFile, backupsFolder, null, localDataSource, _newPackageTempFolder);
}
return await result.Task;
@@ -597,7 +691,7 @@ namespace Tango.PPC.Common.MachineUpdate
{
_isUpdating = true;
- var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
+ var machineServiceAddress = _settings.GetMachineServiceAddress();
LogManager.Log($"Connecting to machine service on {machineServiceAddress}...");
@@ -611,6 +705,8 @@ namespace Tango.PPC.Common.MachineUpdate
try
{
+ request.MachineLastUpdated = _machineProvider.Machine.LastUpdated;
+
using (ObservablesContext db = ObservablesContext.CreateDefault())
{
request.Rmls = db.Rmls.ToList().Select(x => new UpdatedEntity(x)).ToList();
@@ -770,7 +866,7 @@ namespace Tango.PPC.Common.MachineUpdate
{
return Task.Factory.StartNew<DbCompareResult>(() =>
{
- var machineServiceAddress = SettingsManager.Default.GetOrCreate<PPCSettings>().GetMachineServiceAddress();
+ var machineServiceAddress = _settings.GetMachineServiceAddress();
LogManager.Log($"Checking if database update is required for serial number {serialNumber}...");
@@ -789,6 +885,8 @@ namespace Tango.PPC.Common.MachineUpdate
UpdateDBRequest request = new UpdateDBRequest();
request.SerialNumber = serialNumber;
+ request.ApplicationVersion = _app_manager.Version.ToString();
+ request.FirmwareVersion = _app_manager.FirmwareVersion.ToString();
UpdateDBResponse update_response = null;
@@ -875,31 +973,284 @@ namespace Tango.PPC.Common.MachineUpdate
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <returns></returns>
- public Task<MachineUpdateResult> UpdateFromTUP(string fileName)
+ public async Task<MachineUpdateResult> UpdateFromTUP(string fileName, bool setupFirmware, bool setupFPGA)
{
- return Task.Factory.StartNew<MachineUpdateResult>(() =>
+ _logs.Clear();
+
+ TaskCompletionSource<MachineUpdateResult> result = new TaskCompletionSource<MachineUpdateResult>();
+
+ var localDataSource = SettingsManager.Default.GetOrCreate<CoreSettings>().DataSource;
+ bool performDatabaseRollback = false;
+ String dbBackupFile = null;
+ String tempDbName = "Tango_TUP";
+ String tempDbFileName = tempDbName + ".bak";
+ String backupsFolder = "C:\\Backups";
+ bool replaceBinaries = false;
+
+ String serialNumber = _machineProvider.Machine.SerialNumber;
+
+ //Create temporary folders for packages.
+ var _newPackageTempFolder = TemporaryManager.CreateFolder();
+ _newPackageTempFolder.Persist = true;
+
+ try
{
- LogManager.Log($"Starting machine update from update package '{fileName}'...");
+ _isUpdating = true;
- //Create temporary folders for packages.
- var _newPackageTempFolder = TemporaryManager.CreateFolder();
- _newPackageTempFolder.Persist = true;
+ LogManager.Log($"Starting machine update for serial number {serialNumber}...");
- LogManager.Log("Extracting downloaded zip file...");
- //Extract software package.
- ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder);
+ //Connecting to machine...
+ LogManager.Log("Verifying machine connection and state...");
+
+ UpdateProgress("Verifying machine state", "Initializing...");
+
+ await Task.Delay(1000);
+
+ IMachineOperator op = _machineProvider.MachineOperator;
+
+ if (setupFirmware)
+ {
+ LogManager.Log("Machine is configured to update firmware...");
+
+ if (op.State != Transport.TransportComponentState.Connected)
+ {
+ throw LogManager.Log(new InvalidOperationException("Could not perform an update while the machine is not connected."));
+ }
+ if (op.Status != MachineStatuses.ReadyToDye)
+ {
+ throw LogManager.Log(new InvalidOperationException($"Could not perform an update while the machine is in {op.Status} status."));
+ }
+ }
+
+ UpdateProgress("Exploring package", "Extracting...");
+ LogManager.Log("Extracting package...");
+
+ LogManager.Log($"Temporary package folder created: {_newPackageTempFolder}.");
+
+ await Task.Factory.StartNew(() =>
+ {
+ //Extract software package.
+ ZipFile.ExtractToDirectory(fileName, _newPackageTempFolder);
+ });
+
+ //Extracting publish info
+ UpdateProgress("Exploring package", "Verifying...");
+ PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(_newPackageTempFolder, "version.json")));
+
+ if (!publishInfo.IsMachineTupPackage)
+ {
+ throw new InvalidOperationException("The specified tup file is invalid. Updating a machine from a tup file requires a custom generated package.");
+ }
+
+ if (publishInfo.MachineSerialNumber != serialNumber)
+ {
+ throw new InvalidOperationException("The specified tup file is invalid. The package was generated for a different machine.");
+ }
+
+ if (publishInfo.MachineDeploymentSlot != _settings.DeploymentSlot)
+ {
+ throw new InvalidOperationException("The specified tup file is invalid. The package was generated on a different environment.");
+ }
+
+ replaceBinaries = _app_manager.Version.ToString() != publishInfo.ApplicationVersion;
LogManager.Log("Copying latest updater utility to application path...");
+
//Copy new updater utility to app path.
File.Copy(Path.Combine(_newPackageTempFolder, "Tango.PPC.Updater.exe"), Path.Combine(PathHelper.GetStartupPath(), "Tango.PPC.Updater.exe"), true);
- LogManager.Log("Update operation completed!");
+ //Run pre-update packages.
+ try
+ {
+ UpdateProgress("Preparing", "Running update packages...");
+ LogManager.Log("Running pre-update packages...");
+ var packagesFolder = Path.Combine(_newPackageTempFolder, "Packages");
- return new MachineUpdateResult()
+ Version updateVersion = new Version(1, 0, 0, 0);
+ try
+ {
+ updateVersion = Version.Parse(publishInfo.ApplicationVersion);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error parsing new version string for package runner.");
+ }
+
+ await _packageRunner.Run(PackageType.Pre, updateVersion, packagesFolder);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error running pre-update packages...");
+ }
+
+ //Synchronize database
+ UpdateProgress("Updating Database", "Initializing...");
+
+ UpdateProgress("Updating Database", "Connecting to local database...");
+ LogManager.Log("Initializing database manager...");
+ DbManager db = DbManager.FromDataSource(localDataSource);
+
+ LogManager.Log("Checking Tango database exists on the local machine...");
+ if (!db.Exists(localDataSource.Catalog))
{
- UpdatePackagePath = _newPackageTempFolder,
+ throw new InvalidProgramException("Database tango does not exists.");
+ }
+
+ UpdateProgress("Updating Database", "Creating database backup...");
+
+ //Create Database Backup
+ try
+ {
+ Directory.CreateDirectory(backupsFolder);
+ dbBackupFile = $"{backupsFolder}\\{Path.GetRandomFileName()}.bak";
+ LogManager.Log($"Creating database backup to '{dbBackupFile}'...");
+ await Task.Factory.StartNew(() => db.Backup(localDataSource.Catalog, dbBackupFile));
+ performDatabaseRollback = true;
+ LogManager.Log("Database backup created successfully.");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Update manager error while trying to create a database backup.");
+ }
+
+ LogManager.Log("Extracting database file from package...");
+ File.Copy(Path.Combine(_newPackageTempFolder, tempDbFileName), Path.Combine(backupsFolder, tempDbFileName));
+
+ LogManager.Log("Restoring package database as a new database...");
+ db.RestoreAsNew(tempDbName, Path.Combine(backupsFolder, tempDbFileName), backupsFolder);
+
+ Core.DataSource tempDbDataSource = new Core.DataSource();
+ tempDbDataSource.Address = localDataSource.Address;
+ tempDbDataSource.IntegratedSecurity = localDataSource.IntegratedSecurity;
+ tempDbDataSource.Type = localDataSource.Type;
+ tempDbDataSource.Catalog = tempDbName;
+
+ LogManager.Log("Disposing database manager.");
+ db.Dispose();
+
+ LogManager.Log($"Initializing {nameof(ExaminerSequenceConfigurationRunner)}...");
+
+ UpdateProgress("Updating Database", "Initializing update sequence...");
+
+ ExaminerSequenceConfigurationRunner runner = new ExaminerSequenceConfigurationRunner(
+ Path.Combine(_newPackageTempFolder, "Update Scripts", "config.xml"),
+ Path.Combine(_newPackageTempFolder, "Update Scripts"),
+ tempDbDataSource,
+ localDataSource,
+ serialNumber);
+
+ runner.Log += (x, msg) =>
+ {
+ LogManager.Log(msg);
+ ProgressLog?.Invoke(this, msg);
};
- });
+
+ runner.ScriptExecuting += (x, item) =>
+ {
+ LogManager.Log($"Executing script {item.ToString()}...");
+ UpdateProgress("Updating Database", item.Name + "...");
+ };
+
+ LogManager.Log("Starting synchronization process...");
+
+ try
+ {
+ await runner.Run();
+ LogManager.Log("Synchronization completed successfully!");
+ UpdateProgress("Updating Database", "Database synchronization completed successfully.");
+ }
+ catch (Exception ex)
+ {
+ throw LogManager.Log(ex, "Update manager error while trying to synchronize database.");
+ }
+
+ LogManager.Log("Getting setup firmware/fpga directly from db..");
+
+ using (var dbManager = DbManager.FromDataSource(localDataSource))
+ {
+ try
+ {
+ String firmware = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FIRMWARE");
+ String fpga = dbManager.GetValue($"SELECT TOP 1 * FROM MACHINES WHERE SERIAL_NUMBER = '{serialNumber}'", "SETUP_FPGA");
+
+ setupFirmware = bool.Parse(firmware);
+ setupFPGA = bool.Parse(fpga);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error getting new values of SETUP_FIRMWARE and SETUP_FPGA.");
+ }
+ }
+
+ //Updating firmware
+ if (setupFirmware)
+ {
+ UpdateProgress("Updating Firmware", "Connecting to firmware device...");
+ LogManager.Log("");
+ LogManager.Log("-------------------------------------------------------------------------");
+ LogManager.Log("Updating Firmware...");
+
+ UpdateProgress("Updating Firmware", "Loading firmware package...");
+ var tfpPath = Path.Combine(_newPackageTempFolder, "firmware_package.tfp");
+ var stream = new FileStream(tfpPath, FileMode.Open);
+
+ if (!_machineProvider.Machine.IsDemo)
+ {
+ if (setupFPGA)
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU | FirmwareUpgradeModes.TFP_PACKAGE;
+ }
+ else
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.DFU;
+ }
+ }
+ else
+ {
+ op.FirmwareUpgradeMode = FirmwareUpgradeModes.TFP_PACKAGE;
+ }
+
+ var handler = await op.UpgradeFirmware(stream);
+ handler.Failed += (_, ex) =>
+ {
+ stream.Dispose();
+ OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder);
+ };
+ handler.Completed += (_, __) =>
+ {
+ UpdateProgress("Updating Firmware", "Firmware update completed successfully.");
+ stream.Dispose();
+ OnCompleted(new MachineUpdateResult()
+ {
+ UpdatePackagePath = _newPackageTempFolder,
+ RequiresBinariesUpdate = replaceBinaries,
+ }, result, null, tempDbName, backupsFolder, localDataSource);
+ };
+ handler.Canceled += (_, __) =>
+ {
+ stream.Dispose();
+ OnFailed(new Exception("The operation has been canceled."), result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder);
+ };
+ handler.Progress += (_, e) =>
+ {
+ UpdateProgress("Updating Firmware", e.Message, false, e.Current, e.Total);
+ };
+ }
+ else
+ {
+ OnCompleted(new MachineUpdateResult()
+ {
+ UpdatePackagePath = _newPackageTempFolder,
+ RequiresBinariesUpdate = replaceBinaries,
+ }, result, null, tempDbName, backupsFolder, localDataSource);
+ }
+ }
+ catch (Exception ex)
+ {
+ OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder);
+ }
+
+ return await result.Task;
}
/// <summary>
@@ -907,25 +1258,23 @@ namespace Tango.PPC.Common.MachineUpdate
/// </summary>
/// <param name="filePath">The file path.</param>
/// <returns></returns>
- public Task<UpdatePackageFile> GetUpdatePackageFileInfo(string filePath)
+ public Task<PublishInfo> GetUpdatePackageFileInfo(string filePath)
{
- return Task.Factory.StartNew<UpdatePackageFile>(() =>
+ return Task.Factory.StartNew<PublishInfo>(() =>
{
- UpdatePackageFile file = new UpdatePackageFile();
- var tempFolder = TemporaryManager.CreateFolder();
-
using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile(filePath))
{
- var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "Tango.PPC.UI.exe");
- appEntry.Extract(tempFolder);
- }
+ var appEntry = zip.Entries.SingleOrDefault(x => x.FileName == "version.json");
+ var reader = appEntry.OpenReader();
- FileVersionInfo info = FileVersionInfo.GetVersionInfo(Path.Combine(tempFolder, "Tango.PPC.UI.exe"));
- file.Version = Version.Parse(info.ProductVersion);
-
- tempFolder.Delete();
+ using (StreamReader stReader = new StreamReader(reader))
+ {
+ String json = stReader.ReadToEnd();
+ reader.Dispose();
- return file;
+ return PublishInfo.FromJson(json);
+ }
+ }
});
}
@@ -948,7 +1297,7 @@ namespace Tango.PPC.Common.MachineUpdate
String packagesFolder = Path.Combine(AssemblyHelper.GetCurrentAssemblyFolder(), "packages");
Version previousVersion = null;
- String str = SettingsManager.Default.GetOrCreate<PPCSettings>().PreviousApplicationVersion;
+ String str = _settings.PreviousApplicationVersion;
if (Version.TryParse(str, out previousVersion))
{
@@ -989,7 +1338,7 @@ namespace Tango.PPC.Common.MachineUpdate
private async void _checkForUpdateTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
- if (AutoCheckForUpdates && !_isUpdating)
+ if (EnableAutoCheckForUpdates && _settings.AutoCheckForUpdates && !_isUpdating)
{
_checkForUpdateTimer.Stop();
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs
index 17ae394ee..85dd5b7d2 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateResult.cs
@@ -12,5 +12,18 @@ namespace Tango.PPC.Common.MachineUpdate
/// Gets or sets the temporary update package path from which to get the last downloaded software version.
/// </summary>
public String UpdatePackagePath { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether the application should replace it's binaries.
+ /// </summary>
+ public bool RequiresBinariesUpdate { get; set; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="MachineUpdateResult"/> class.
+ /// </summary>
+ public MachineUpdateResult()
+ {
+ RequiresBinariesUpdate = true;
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs
deleted file mode 100644
index df496c3be..000000000
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/UpdatePackageFile.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Tango.PPC.Common.MachineUpdate
-{
- public class UpdatePackageFile
- {
- public Version Version { get; set; }
- }
-}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Models/FineTuneItem.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Models/FineTuneItem.cs
index 2eea5c3ce..c03be1ae9 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Models/FineTuneItem.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Models/FineTuneItem.cs
@@ -18,6 +18,8 @@ namespace Tango.PPC.Common.Models
{
public event Action SelectedChanged;
+ public BrushStop BrushStop { get; set; }
+
/// <summary>
/// Gets or sets the brush stops.
/// </summary>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs
index d791d10d3..cb17f5be3 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCSettings.cs
@@ -180,6 +180,46 @@ namespace Tango.PPC.Common
public String PreviousApplicationVersion { get; set; }
/// <summary>
+ /// Gets or sets a value indicating whether synchronize jobs with twine server.
+ /// </summary>
+ public bool SynchronizeJobs { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether synchronize diagnostics data.
+ /// </summary>
+ public bool SynchronizeDiagnostics { get; set; }
+
+ /// <summary>
+ /// Gets or sets the synchronization interval.
+ /// </summary>
+ public TimeSpan SynchronizationInterval { get; set; }
+
+ /// <summary>
+ /// Gets or sets the known firmware version.
+ /// </summary>
+ public String FirmwareVersion { get; set; }
+
+ /// <summary>
+ /// Gets or sets the last power up selected RML.
+ /// </summary>
+ public String LastPowerUpSelectedRmlGuid { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether to display the power up screen.
+ /// </summary>
+ public bool DisplayPowerUpScreen { get; set; }
+
+ /// <summary>
+ /// Gets or sets the power up screen timeout.
+ /// </summary>
+ public TimeSpan PowerUpScreenTimeout { get; set; }
+
+ /// <summary>
+ /// Gets or sets a value indicating whether to automatically check for software and database (quick) updates.
+ /// </summary>
+ public bool AutoCheckForUpdates { get; set; }
+
+ /// <summary>
/// Gets the machine service address.
/// </summary>
/// <returns></returns>
@@ -214,6 +254,13 @@ namespace Tango.PPC.Common
SupportedColorSpaces = new List<ColorSpaces>();
SupportedJobTypes = new List<JobTypes>();
PreviousApplicationVersion = "1.0.0.0";
+ SynchronizeJobs = true;
+ SynchronizeDiagnostics = true;
+ SynchronizationInterval = TimeSpan.FromMinutes(60);
+ FirmwareVersion = "1.0.0.0";
+ DisplayPowerUpScreen = true;
+ PowerUpScreenTimeout = TimeSpan.FromSeconds(20);
+ AutoCheckForUpdates = true;
}
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
index 19bc6cd67..7992e6672 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/PPCViewModel.cs
@@ -17,6 +17,7 @@ using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.Printing;
using Tango.PPC.Common.RemoteAssistance;
using Tango.PPC.Common.Storage;
+using Tango.PPC.Common.Synchronization;
using Tango.Settings;
using Tango.SharedUI;
using static Tango.SharedUI.Controls.NavigationControl;
@@ -109,6 +110,12 @@ namespace Tango.PPC.Common
[TangoInject]
public IEventLogger EventLogger { get; set; }
+ /// <summary>
+ /// Gets or sets the machine data synchronizer.
+ /// </summary>
+ [TangoInject]
+ public IMachineDataSynchronizer MachineDataSynchronizer { get; set; }
+
private PPCSettings _settings;
/// <summary>
/// Gets the main PPC settings.
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs
index 77717254e..df5690a05 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Tango.PMR.FirmwareUpgrade;
+using Tango.Web;
namespace Tango.PPC.Common.Publish
{
@@ -13,6 +14,9 @@ namespace Tango.PPC.Common.Publish
public String ApplicationVersion { get; set; }
public VersionPackageDescriptor Firmware { get; set; }
public String Comments { get; set; }
+ public bool IsMachineTupPackage { get; set; }
+ public String MachineSerialNumber { get; set; }
+ public DeploymentSlot MachineDeploymentSlot { get; set; }
public PublishInfo()
{
@@ -24,7 +28,7 @@ namespace Tango.PPC.Common.Publish
return JsonConvert.SerializeObject(this);
}
- public PublishInfo FromJson(String json)
+ public static PublishInfo FromJson(String json)
{
return JsonConvert.DeserializeObject<PublishInfo>(json);
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs
new file mode 100644
index 000000000..8260eb4b3
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs
@@ -0,0 +1,554 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Timers;
+using Tango.BL;
+using Tango.PPC.Common.Web;
+using System.Data.Entity;
+using Tango.BL.DTO;
+using Tango.PPC.Common.Connection;
+using Tango.BL.Builders;
+using Tango.Settings;
+using Tango.Core;
+using Tango.PPC.Common.Authentication;
+using Tango.Logging;
+using System.Diagnostics;
+using Tango.BL.Enumerations;
+using Tango.PPC.Common.Application;
+using Tango.Core.DI;
+
+namespace Tango.PPC.Common.Synchronization
+{
+ public class DefaultMachineDataSynchronizer : ExtendedObject, IMachineDataSynchronizer
+ {
+ private Timer _synchTimer;
+ private PPCWebClient client;
+ private IMachineProvider _machineProvider;
+ private IAuthenticationProvider _authenticationProvider;
+ private List<LogItemBase> _logs;
+ private bool _synchronizedOnce;
+
+ [TangoInject(TangoInjectMode.WhenAvailable)]
+ private IPPCApplicationManager _appManager;
+
+ public event EventHandler<SynchronizationStatusChangedEventArgs> CurrentStatusChanged;
+ public event EventHandler SynchronizationStarted;
+ public event EventHandler<SynchronizationEndedEventArgs> SynchronizationEnded;
+
+ public int MaxJobs { get; set; }
+ public int MaxJobRuns { get; set; }
+ public int MaxMachinesEvents { get; set; }
+
+ private SynchronizationStatus _currentStatus;
+ public SynchronizationStatus CurrentStatus
+ {
+ get { return _currentStatus; }
+ private set { _currentStatus = value; RaisePropertyChangedAuto(); }
+ }
+
+ private SynchronizationStatus _lastStatus;
+ public SynchronizationStatus LastStatus
+ {
+ get { return _lastStatus; }
+ private set { _lastStatus = value; RaisePropertyChangedAuto(); }
+ }
+
+ public SynchronizedObservableCollection<SynchronizationStatus> StatusHistory { get; private set; }
+
+ public TimeSpan Interval { get; set; }
+
+ private bool _isEnabled;
+ public bool IsEnabled
+ {
+ get { return _isEnabled; }
+ set { _isEnabled = value; OnEnableChanged(); RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isSynchronizing;
+ public bool IsSynchronizing
+ {
+ get { return _isSynchronizing; }
+ set { _isSynchronizing = value; RaisePropertyChangedAuto(); }
+ }
+
+ public DefaultMachineDataSynchronizer()
+ {
+ StatusHistory = new SynchronizedObservableCollection<SynchronizationStatus>();
+
+ MaxJobs = 10;
+ MaxJobRuns = 100;
+ MaxMachinesEvents = 100;
+
+ var settings = SettingsManager.Default.GetOrCreate<PPCSettings>();
+ Interval = settings.SynchronizationInterval;
+
+ _synchTimer = new Timer(Interval.TotalMilliseconds);
+ _synchTimer.Elapsed += _synchTimer_Elapsed;
+ _synchTimer.Enabled = true;
+
+ ExecuteNewStatus(TimeSpan.FromMinutes(2));
+ LastStatus = CurrentStatus;
+ }
+
+ public DefaultMachineDataSynchronizer(PPCWebClient ppcWebClient, IMachineProvider machineProvider, IAuthenticationProvider authenticationProvider) : this()
+ {
+ _logs = new List<LogItemBase>();
+ _machineProvider = machineProvider;
+ client = new PPCWebClient(ppcWebClient, TimeSpan.FromMinutes(10));
+ _authenticationProvider = authenticationProvider;
+
+ LogManager.NewLog += LogManager_NewLog;
+ }
+
+ private void LogManager_NewLog(object sender, LogItemBase e)
+ {
+ if (IsSynchronizing)
+ {
+ _logs.Add(e);
+ }
+ }
+
+ private String GetLogsStringAndClear()
+ {
+ String logsString = String.Join(Environment.NewLine, _logs.ToList().Select(x => x.ToString()));
+ _logs.Clear();
+ return logsString;
+ }
+
+ private void OnEnableChanged()
+ {
+ _synchTimer.Interval = Interval.TotalMilliseconds;
+
+ if (IsEnabled)
+ {
+ CurrentStatus.State = SynchronizationState.Pending;
+ }
+ else
+ {
+ CurrentStatus.State = SynchronizationState.Disabled;
+ }
+ }
+
+ private void _synchTimer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ _synchTimer.Interval = Interval.TotalMilliseconds;
+
+ try
+ {
+ Synchronize().GetAwaiter().GetResult();
+ }
+ catch { }
+ }
+
+ private async Task<UploadMachineDataRequest> CreateUploadMachineDataRequest(bool syncJobs, bool syncDiagnostics)
+ {
+ UploadMachineDataRequest request = new UploadMachineDataRequest();
+
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ if (syncJobs)
+ {
+ LogManager.Log("Checking Jobs...");
+
+ var jobs = await new JobsCollectionBuilder(db).Set(x => !x.IsSynchronized).WithSegments().WithBrushStops().Query(x => x.Take(MaxJobs).OrderByDescending(z => z.LastUpdated)).BuildListAsync();
+ List<JobDTO> dtos = new List<JobDTO>();
+
+ foreach (var job in jobs)
+ {
+ var dto = JobDTO.FromObservable(job);
+ request.Jobs.Add(dto);
+ }
+ }
+
+ if (syncDiagnostics)
+ {
+ LogManager.Log("Checking Job Runs...");
+
+ var jobRuns = await db.JobRuns.Where(x => !x.IsSynchronized).Take(MaxJobRuns).OrderByDescending(x => x.LastUpdated).ToListAsync();
+ List<JobRunDTO> dtos = new List<JobRunDTO>();
+
+ foreach (var jobRun in jobRuns)
+ {
+ var dto = JobRunDTO.FromObservable(jobRun);
+ request.JobRuns.Add(dto);
+ }
+ }
+
+ if (syncDiagnostics)
+ {
+ LogManager.Log("Checking Events...");
+
+ var machineEvents = await db.MachinesEvents.Where(x => !x.IsSynchronized).Take(MaxMachinesEvents).OrderByDescending(x => x.LastUpdated).ToListAsync();
+ List<MachinesEventDTO> dtos = new List<MachinesEventDTO>();
+
+ foreach (var machineEvent in machineEvents)
+ {
+ machineEvent.IsSynchronized = true;
+ var dto = MachinesEventDTO.FromObservable(machineEvent);
+ request.MachineEvents.Add(dto);
+ }
+ }
+ }
+
+ return request;
+ }
+
+ private async Task FinalizeMachineDataUpload(UploadMachineDataRequest request, UploadMachineDataResponse response)
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ //Finalize jobs
+ foreach (var job in request.Jobs)
+ {
+ var failedJob = response.FailedJobs.SingleOrDefault(x => x.Guid == job.Guid);
+
+ if (failedJob == null)
+ {
+ var dbJob = await db.Jobs.SingleOrDefaultAsync(x => x.Guid == job.Guid);
+ dbJob.IsSynchronized = true;
+ }
+ else
+ {
+ LogManager.Log($"Synchronization Error - Job '{job.Name}' cannot be stored on the server due to the following reason:\n{failedJob.Reason}", LogCategory.Error);
+ }
+ }
+
+ //Finalize job runs
+ foreach (var jobRun in request.JobRuns)
+ {
+ var failedJobRun = response.FailedJobRuns.SingleOrDefault(x => x.Guid == jobRun.Guid);
+
+ if (failedJobRun == null)
+ {
+ var dbJobRun = await db.JobRuns.SingleOrDefaultAsync(x => x.Guid == jobRun.Guid);
+ dbJobRun.IsSynchronized = true;
+ }
+ else
+ {
+ LogManager.Log($"Synchronization Error - JobRun '{jobRun.ID}' cannot be stored on the server due to the following reason:\n{failedJobRun.Reason}", LogCategory.Error);
+ }
+ }
+
+ //Finalize machine events
+ foreach (var machineEvent in request.MachineEvents)
+ {
+ var failedMachineEvent = response.FailedMachineEvents.SingleOrDefault(x => x.Guid == machineEvent.Guid);
+
+ if (failedMachineEvent == null)
+ {
+ var dbMachineEvent = await db.MachinesEvents.SingleOrDefaultAsync(x => x.Guid == machineEvent.Guid);
+ dbMachineEvent.IsSynchronized = true;
+ }
+ else
+ {
+ LogManager.Log($"Synchronization Error - Event '{machineEvent.ID}' cannot be stored on the server due to the following reason:\n{failedMachineEvent.Reason}", LogCategory.Error);
+ }
+ }
+
+ await db.SaveChangesAsync();
+ }
+ }
+
+ private async Task<DownloadMachineDataResponse> DownloadMachineData(bool syncJobs, bool syncDiagnostics)
+ {
+ return await client.DownloadMachineData(new DownloadMachineDataRequest()
+ {
+ RequestJobs = syncJobs,
+ RequestJobRuns = syncDiagnostics,
+ RequestMachineEvents = syncDiagnostics,
+ MaxJobs = MaxJobs,
+ MaxJobRuns = MaxJobRuns,
+ MaxMachinesEvents = MaxMachinesEvents,
+ });
+ }
+
+ private async Task<NotifyMachineDataDownloadCompletedRequest> InsertReplaceMachineData(DownloadMachineDataResponse response)
+ {
+ NotifyMachineDataDownloadCompletedRequest request = new NotifyMachineDataDownloadCompletedRequest();
+
+ //Insert/Replace Jobs.
+ if (response.Jobs.Count > 0)
+ {
+ LogManager.Log("Inserting/Replacing Jobs...");
+ }
+ foreach (var dto in response.Jobs)
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ try
+ {
+ var job = dto.ToObservable();
+
+ job.ID = 0;
+ job.UserGuid = _authenticationProvider.CurrentUser.Guid;
+ job.CustomerGuid = null;
+ job.IsSynchronized = true;
+
+ var existingJob = await db.Jobs.SingleOrDefaultAsync(x => x.Guid == job.Guid);
+
+ if (existingJob == null)
+ {
+ db.Jobs.Add(job);
+ await db.SaveChangesAsync();
+ }
+ else if (job.LastUpdated > existingJob.LastUpdated)
+ {
+ existingJob.Delete(db);
+ db.Jobs.Add(job);
+ await db.SaveChangesAsync();
+ }
+
+ request.SynchronizedJobs.Add(job.Guid);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log($"Synchronization Error - Job '{dto.Name}' cannot be stored locally due to the following reason:\n{ex.FlattenMessage()}", LogCategory.Error);
+ }
+ }
+ }
+
+ //Insert JobRuns.
+ if (response.JobRuns.Count > 0)
+ {
+ LogManager.Log("Inserting/Replacing Job Runs...");
+ }
+ foreach (var dto in response.JobRuns)
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ try
+ {
+ var run = dto.ToObservable();
+ run.ID = 0;
+ run.IsSynchronized = true;
+
+ if (await db.JobRuns.SingleOrDefaultAsync(x => x.Guid == run.Guid) == null)
+ {
+ db.JobRuns.Add(run);
+ await db.SaveChangesAsync();
+ }
+
+ request.SynchronizedJobRuns.Add(run.Guid);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log($"Synchronization Error - JobRun '{dto.ID}' cannot be stored locally due to the following reason:\n{ex.FlattenMessage()}", LogCategory.Error);
+ }
+ }
+ }
+
+ //Insert MachineEvents.
+ if (response.MachineEvents.Count > 0)
+ {
+ LogManager.Log("Inserting/Replacing Events...");
+ }
+ foreach (var dto in response.MachineEvents)
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ try
+ {
+ var ev = dto.ToObservable();
+ ev.ID = 0;
+ ev.UserGuid = _authenticationProvider.CurrentUser.Guid;
+ ev.IsSynchronized = true;
+
+ if (await db.MachinesEvents.SingleOrDefaultAsync(x => x.Guid == ev.Guid) == null)
+ {
+ db.MachinesEvents.Add(ev);
+ await db.SaveChangesAsync();
+ }
+
+ request.SynchronizedMachineEvents.Add(ev.Guid);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log($"Synchronization Error - Event '{dto.ID}' cannot be stored locally due to the following reason:\n{ex.FlattenMessage()}", LogCategory.Error);
+ }
+ }
+ }
+
+ return request;
+ }
+
+ public async Task Synchronize()
+ {
+ _synchronizedOnce = true;
+
+ if (!IsEnabled || IsSynchronizing) return;
+
+ var settings = SettingsManager.Default.GetOrCreate<PPCSettings>();
+
+ var syncJobs = settings.SynchronizeJobs;
+ var syncDiagnostics = settings.SynchronizeDiagnostics;
+
+ if (!syncJobs && !syncDiagnostics) return;
+
+ IsSynchronizing = true;
+ SynchronizationStarted?.Invoke(this, new EventArgs());
+
+ _logs.Clear();
+
+ _synchTimer.Stop();
+
+ LogManager.Log("Starting machine data synchronization...");
+ LogManager.Log($"Synchronization interval: {Interval}.");
+
+ CurrentStatus.StartDateTime = DateTime.Now;
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Starting synchronization...");
+
+ Stopwatch watch = new Stopwatch();
+ watch.Start();
+
+ String notifyToken = null;
+
+ int newChangedJobs = 0;
+ int newJobRuns = 0;
+ int newMachineEvents = 0;
+
+ try
+ {
+ LogManager.Log("Authenticating with machine service...");
+
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Authenticating with machine service...");
+
+ if (!this.client.IsAuthenticated)
+ {
+ await this.client.Login(new LoginRequest()
+ {
+ Mode = LoginMode.Machine,
+ SerialNumber = _machineProvider.Machine.SerialNumber,
+ });
+ }
+
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Preparing machine data for upload...");
+ LogManager.Log("Preparing machine data for upload...");
+ var request = await CreateUploadMachineDataRequest(syncJobs, syncDiagnostics);
+ request.ApplicationVersion = _appManager.Version.ToString();
+ request.FirmwareVersion = _appManager.FirmwareVersion.ToString();
+
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Uploading machine data...");
+ LogManager.Log($"Uploading machine data:\nJobs: {request.Jobs.Count}\nJob Runs: {request.JobRuns.Count}\nEvents: {request.MachineEvents.Count}");
+ var response = await this.client.UploadMachineData(request);
+ notifyToken = response.NotifyCompletedToken;
+ LogManager.Log($"Upload response received:\nFailed Jobs: {response.FailedJobs.Count}\nFailed Job Runs: {response.FailedJobRuns.Count}\nFailed Events: {response.FailedMachineEvents.Count}");
+ LogManager.Log("Finalizing upload...");
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Finalizing upload...");
+ await FinalizeMachineDataUpload(request, response);
+
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Downloading machine data from service...");
+ LogManager.Log("Downloading machine data from server...");
+ var downloadResponse = await DownloadMachineData(syncJobs, syncDiagnostics);
+
+ newChangedJobs = downloadResponse.Jobs.Count;
+ newJobRuns = downloadResponse.JobRuns.Count;
+ newMachineEvents = downloadResponse.MachineEvents.Count;
+
+ LogManager.Log($"Download response received:\nJobs: {downloadResponse.Jobs.Count}\nJob Runs: {downloadResponse.JobRuns.Count}\nEvents: {downloadResponse.MachineEvents.Count}");
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Updating local database...");
+ LogManager.Log("Updating local database...");
+ var notifyRequest = await InsertReplaceMachineData(downloadResponse);
+ LogManager.Log($"Finalizing download:\nSynchronized Jobs: {notifyRequest.SynchronizedJobs.Count}\nSynchronized Job Runs: {notifyRequest.SynchronizedJobRuns.Count}\nSynchronized Events: {notifyRequest.SynchronizedMachineEvents.Count}");
+ UpdateCurrentStatus(SynchronizationState.Synchronizing, "Finalizing download...");
+ var notifyResponse = await this.client.NotifyMachineDataDownloadCompleted(notifyRequest);
+
+ if (notifyToken != null)
+ {
+ try
+ {
+ await client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
+ {
+ Token = notifyToken,
+ Status = TangoUpdateStatuses.SynchronizationCompleted,
+ });
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Synchronization completed successfully but an error occurred when trying to notify about the completion.");
+ }
+ }
+
+ LogManager.Log("Machine data synchronization completed successfully.");
+ UpdateCurrentStatus(SynchronizationState.Completed, "Synchronization completed successfully.", null, watch.Elapsed);
+ }
+ catch (Exception ex)
+ {
+ if (notifyToken != null)
+ {
+ try
+ {
+ await client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest()
+ {
+ Token = notifyToken,
+ Status = TangoUpdateStatuses.SynchronizationFailed,
+ FailedReason = ex.FlattenMessage(),
+ FailedLog = GetLogsStringAndClear(),
+ });
+ }
+ catch (Exception ee)
+ {
+ LogManager.Log(ee, "Synchronization completed successfully but an error occurred when trying to notify about the completion.");
+ }
+ }
+
+ UpdateCurrentStatus(SynchronizationState.Failed, "Synchronization failed.", ex.FlattenMessage(), watch.Elapsed);
+ throw LogManager.Log(ex, "Error occurred while synchronizing machine data.");
+ }
+ finally
+ {
+ watch.Stop();
+ LogManager.Log($"Synchronization duration: {watch.Elapsed}.");
+ LastStatus = CurrentStatus;
+ CreateNewStatus();
+ IsSynchronizing = false;
+ SynchronizationEnded?.Invoke(this, new SynchronizationEndedEventArgs()
+ {
+ NewChangedJobs = newChangedJobs,
+ NewJobRuns = newJobRuns,
+ NewMachineEvents = newMachineEvents,
+ });
+ }
+
+ _synchTimer.Start();
+ }
+
+ private void CreateNewStatus()
+ {
+ CurrentStatus = new SynchronizationStatus();
+ CurrentStatus.State = SynchronizationState.Pending;
+ CurrentStatus.StartDateTime = DateTime.Now.Add(Interval);
+ StatusHistory.Insert(0, CurrentStatus);
+ }
+
+ private async void ExecuteNewStatus(TimeSpan delay)
+ {
+ CurrentStatus = new SynchronizationStatus();
+ CurrentStatus.State = SynchronizationState.Pending;
+ CurrentStatus.StartDateTime = DateTime.Now.Add(delay);
+ StatusHistory.Insert(0, CurrentStatus);
+ await Task.Delay(delay);
+ try
+ {
+ if (!_synchronizedOnce)
+ {
+ await Synchronize();
+ }
+ }
+ catch { }
+ }
+
+ private void UpdateCurrentStatus(SynchronizationState state, String message, String errorReason = null, TimeSpan? duration = null)
+ {
+ CurrentStatus.State = state;
+ CurrentStatus.Message = message;
+ CurrentStatus.ErrorReason = errorReason;
+ CurrentStatus.Duration = duration;
+ CurrentStatusChanged?.Invoke(this, new SynchronizationStatusChangedEventArgs()
+ {
+ Status = CurrentStatus,
+ });
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs
new file mode 100644
index 000000000..bfd527a05
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/IMachineDataSynchronizer.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+
+namespace Tango.PPC.Common.Synchronization
+{
+ public interface IMachineDataSynchronizer
+ {
+ event EventHandler SynchronizationStarted;
+ event EventHandler<SynchronizationEndedEventArgs> SynchronizationEnded;
+ event EventHandler<SynchronizationStatusChangedEventArgs> CurrentStatusChanged;
+ int MaxJobs { get; set; }
+ int MaxJobRuns { get; set; }
+ int MaxMachinesEvents { get; set; }
+ SynchronizationStatus CurrentStatus { get; }
+ SynchronizationStatus LastStatus { get; }
+ SynchronizedObservableCollection<SynchronizationStatus> StatusHistory { get; }
+ TimeSpan Interval { get; set; }
+ bool IsEnabled { get; set; }
+ bool IsSynchronizing { get; }
+ Task Synchronize();
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs
new file mode 100644
index 000000000..4b8040e95
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationEndedEventArgs.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.Synchronization
+{
+ public class SynchronizationEndedEventArgs : EventArgs
+ {
+ public int NewChangedJobs { get; set; }
+ public int NewJobRuns { get; set; }
+ public int NewMachineEvents { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs
new file mode 100644
index 000000000..5797f449f
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationState.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.Synchronization
+{
+ public enum SynchronizationState
+ {
+ [Description("Pending...")]
+ Pending,
+ [Description("Synchronizing...")]
+ Synchronizing,
+ [Description("Failed")]
+ Failed,
+ [Description("Completed")]
+ Completed,
+ [Description("Disabled")]
+ Disabled
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs
new file mode 100644
index 000000000..5b1d5d1d2
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatus.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core;
+
+namespace Tango.PPC.Common.Synchronization
+{
+ public class SynchronizationStatus : ExtendedObject
+ {
+ private SynchronizationState _state;
+ public SynchronizationState State
+ {
+ get { return _state; }
+ set { _state = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _message;
+ public String Message
+ {
+ get { return _message; }
+ set { _message = value; RaisePropertyChangedAuto(); }
+ }
+
+ private String _errorReason;
+ public String ErrorReason
+ {
+ get { return _errorReason; }
+ set { _errorReason = value; RaisePropertyChangedAuto(); }
+ }
+
+ private TimeSpan? _duration;
+ public TimeSpan? Duration
+ {
+ get { return _duration; }
+ set { _duration = value; RaisePropertyChangedAuto(); }
+ }
+
+ private DateTime _startDateTime;
+ public DateTime StartDateTime
+ {
+ get { return _startDateTime; }
+ set { _startDateTime = value; RaisePropertyChangedAuto(); }
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs
new file mode 100644
index 000000000..1f0a9a27f
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/SynchronizationStatusChangedEventArgs.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.Synchronization
+{
+ public class SynchronizationStatusChangedEventArgs : EventArgs
+ {
+ public SynchronizationStatus Status { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
index e3a23903e..7142f461b 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Tango.PPC.Common.csproj
@@ -149,6 +149,7 @@
<Compile Include="ExtensionMethods\ObservableCollectionExtensions.cs" />
<Compile Include="ExternalBridge\IPPCExternalBridgeService.cs" />
<Compile Include="ExternalBridge\PPCExternalBridgeService.cs" />
+ <Compile Include="Helpers\KeyboardHelper.cs" />
<Compile Include="HotSpot\DefaultHotSpotProvider.cs" />
<Compile Include="HotSpot\IHotSpotProvider.cs" />
<Compile Include="IPPCView.cs" />
@@ -156,12 +157,19 @@
<Compile Include="MachineSetup\MachineSetupManager.cs" />
<Compile Include="MachineSetup\MachineSetupProgress.cs" />
<Compile Include="MachineSetup\MachineSetupResult.cs" />
+ <Compile Include="Synchronization\DefaultMachineDataSynchronizer.cs" />
+ <Compile Include="Synchronization\IMachineDataSynchronizer.cs" />
+ <Compile Include="Synchronization\SynchronizationEndedEventArgs.cs" />
+ <Compile Include="Synchronization\SynchronizationState.cs" />
+ <Compile Include="Synchronization\SynchronizationStatus.cs" />
+ <Compile Include="Synchronization\SynchronizationStatusChangedEventArgs.cs" />
<Compile Include="UpdatePackages\DefaultPackageRunner.cs" />
<Compile Include="UpdatePackages\IPackageRunner.cs" />
<Compile Include="UpdatePackages\IPPCPackage.cs" />
<Compile Include="UpdatePackages\PackageContext.cs" />
<Compile Include="UpdatePackages\PackageInstallation.cs" />
<Compile Include="UpdatePackages\PackageInstallationState.cs" />
+ <Compile Include="UpdatePackages\PackageProgressEventArgs.cs" />
<Compile Include="UpdatePackages\PackageRunnerResult.cs" />
<Compile Include="UpdatePackages\PackageStateChangedEventArgs.cs" />
<Compile Include="UpdatePackages\PackagesFile.cs" />
@@ -177,6 +185,8 @@
<Compile Include="Web\CheckForUpdateRequest.cs" />
<Compile Include="Web\CheckForUpdateResponse.cs" />
<Compile Include="MachineUpdate\DbCompareResult.cs" />
+ <Compile Include="Web\NotifyMachineDataDownloadCompletedResponse.cs" />
+ <Compile Include="Web\NotifyMachineDataDownloadCompletedRequest.cs" />
<Compile Include="Web\DownloadUpdateRequest.cs" />
<Compile Include="Web\MachineUpdateCompletedResponse.cs" />
<Compile Include="Web\DownloadUpdateResponse.cs" />
@@ -192,9 +202,9 @@
<Compile Include="MachineUpdate\MachineUpdateResult.cs" />
<Compile Include="Web\PPCWebClient.cs" />
<Compile Include="Web\PPCWebClientBase.cs" />
+ <Compile Include="Web\SynchronizationFailedEntity.cs" />
<Compile Include="Web\UpdateDBRequest.cs" />
<Compile Include="Web\UpdateDBResponse.cs" />
- <Compile Include="MachineUpdate\UpdatePackageFile.cs" />
<Compile Include="Messages\JobRemovedMessage.cs" />
<Compile Include="Messages\JobSavedMessage.cs" />
<Compile Include="Messages\MachineSettingsSavedMessage.cs" />
@@ -227,8 +237,12 @@
<Compile Include="Web\LatestVersionRequest.cs" />
<Compile Include="Web\LatestVersionResponse.cs" />
<Compile Include="Web\UpdatedEntity.cs" />
+ <Compile Include="Web\DownloadMachineDataRequest.cs" />
+ <Compile Include="Web\DownloadMachineDataResponse.cs" />
+ <Compile Include="Web\UploadMachineDataResponse.cs" />
<Compile Include="Web\UploadCompletedResponse.cs" />
<Compile Include="Web\UploadCompletedRequest.cs" />
+ <Compile Include="Web\UploadMachineDataRequest.cs" />
<Compile Include="Web\UploadVersionRequest.cs" />
<Compile Include="Web\UploadVersionResponse.cs" />
<Compile Include="UWF\DefaultUnifiedWriteFilterManager.cs" />
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/DefaultPackageRunner.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/DefaultPackageRunner.cs
index 74ba59bad..c94aedeb0 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/DefaultPackageRunner.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/DefaultPackageRunner.cs
@@ -25,6 +25,7 @@ namespace Tango.PPC.Common.UpdatePackages
private PackagesFile _packagesFile;
public event EventHandler<PackageStateChangedEventArgs> PackageStateChanged;
+ public event EventHandler<PackageProgressEventArgs> PackageProgress;
public DefaultPackageRunner()
{
@@ -189,6 +190,27 @@ namespace Tango.PPC.Common.UpdatePackages
{
OnPackageRuns(att.Name, installedPackage.State, installedPackage.Type);
installedPackage.InstallationDate = DateTime.Now;
+ context.ProgressAction = (message, isIntermediate, progress, total) =>
+ {
+ PackageProgress?.Invoke(this, new PackageProgressEventArgs()
+ {
+ PackageName = att.Name,
+ Message = message,
+ IsIntermediate = isIntermediate,
+ Progress = progress,
+ Total = total
+ });
+ };
+
+ PackageProgress?.Invoke(this, new PackageProgressEventArgs()
+ {
+ PackageName = type == PackageType.Pre ? "Preparing" : "Finalizing",
+ Message = att.Name,
+ IsIntermediate = true,
+ Progress = 0,
+ Total = 100
+ });
+
packageInstance.Run(context).GetAwaiter().GetResult();
installedPackage.State = PackageInstallationState.Installed;
installedPackage.FailedReason = null;
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/IPackageRunner.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/IPackageRunner.cs
index dcdfa8b60..b864100aa 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/IPackageRunner.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/IPackageRunner.cs
@@ -9,6 +9,7 @@ namespace Tango.PPC.Common.UpdatePackages
public interface IPackageRunner
{
event EventHandler<PackageStateChangedEventArgs> PackageStateChanged;
+ event EventHandler<PackageProgressEventArgs> PackageProgress;
Task<PackagesFile> GetPackagesFile();
Task<PackageRunnerResult> Run(PackageType type, Version deltaVersion, String packagesFolder);
Task<bool> IsPackageInstallationRequired(PackageType type, String packagesFolder);
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageContext.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageContext.cs
index 24044e567..7c8736112 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageContext.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageContext.cs
@@ -11,10 +11,18 @@ namespace Tango.PPC.Common.UpdatePackages
{
public class PackageContext
{
+ public delegate void PackageProgressDelegate(String message, bool isIntermediate = true, double progress = 0, double maximum = 100);
+
public IPPCApplicationManager ApplicationManager { get; set; }
public IMachineProvider MachineProvider { get; set; }
public INotificationProvider NotificationProvider { get; set; }
public Version InstalledVersion { get; set; }
public Version DeltaVersion { get; set; }
+ internal PackageProgressDelegate ProgressAction { get; set; }
+
+ public void ReportProgress(String message, bool isIntermediate = true, double progress = 0, double maximum = 100)
+ {
+ ProgressAction?.Invoke(message, isIntermediate, progress, maximum);
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageProgressEventArgs.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageProgressEventArgs.cs
new file mode 100644
index 000000000..ebf0b23a6
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/UpdatePackages/PackageProgressEventArgs.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.UpdatePackages
+{
+ public class PackageProgressEventArgs : EventArgs
+ {
+ public String PackageName { get; set; }
+ public String Message { get; set; }
+ public bool IsIntermediate { get; set; }
+ public double Progress { get; set; }
+ public double Total { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateRequest.cs
index 0feb32aaf..3d606b918 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateRequest.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateRequest.cs
@@ -15,6 +15,7 @@ namespace Tango.PPC.Common.Web
public List<UpdatedEntity> Rmls { get; set; }
public List<UpdatedEntity> HardwareVersions { get; set; }
public List<UpdatedEntity> Catalogs { get; set; }
+ public DateTime MachineLastUpdated { get; set; }
public CheckForUpdateRequest()
{
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs
new file mode 100644
index 000000000..66fca8e36
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataRequest.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.DTO;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.Web
+{
+ public class DownloadMachineDataRequest : WebRequestMessage
+ {
+ public bool RequestJobs { get; set; }
+ public bool RequestJobRuns { get; set; }
+ public bool RequestMachineEvents { get; set; }
+
+ public int MaxJobs { get; set; }
+ public int MaxJobRuns { get; set; }
+ public int MaxMachinesEvents { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs
new file mode 100644
index 000000000..5c3f7ba78
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadMachineDataResponse.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.DTO;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.Web
+{
+ public class DownloadMachineDataResponse : WebResponseMessage
+ {
+ public List<JobDTO> Jobs { get; set; }
+ public List<JobRunDTO> JobRuns { get; set; }
+ public List<MachinesEventDTO> MachineEvents { get; set; }
+
+ public DownloadMachineDataResponse()
+ {
+ Jobs = new List<JobDTO>();
+ JobRuns = new List<JobRunDTO>();
+ MachineEvents = new List<MachinesEventDTO>();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs
new file mode 100644
index 000000000..fc135c234
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedRequest.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.DTO;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.Web
+{
+ public class NotifyMachineDataDownloadCompletedRequest : WebRequestMessage
+ {
+ public List<String> SynchronizedJobs { get; set; }
+ public List<String> SynchronizedJobRuns { get; set; }
+ public List<String> SynchronizedMachineEvents { get; set; }
+
+ public NotifyMachineDataDownloadCompletedRequest()
+ {
+ SynchronizedJobs = new List<string>();
+ SynchronizedJobRuns = new List<string>();
+ SynchronizedMachineEvents = new List<string>();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs
new file mode 100644
index 000000000..6d5769885
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/NotifyMachineDataDownloadCompletedResponse.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.DTO;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.Web
+{
+ public class NotifyMachineDataDownloadCompletedResponse : WebResponseMessage
+ {
+
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs
index 52c9fdef3..318512fbb 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClient.cs
@@ -30,5 +30,10 @@ namespace Tango.PPC.Common.Web
public PPCWebClient(string address, string token) : base(address, token)
{
}
+
+ public PPCWebClient(PPCWebClient other, TimeSpan requestTimeout) : base(other)
+ {
+ RequestTimeout = requestTimeout;
+ }
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs
index 5520f8b5a..ff972acb2 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/PPCWebClientBase.cs
@@ -41,6 +41,15 @@ namespace Tango.PPC.Common.Web
}
/// <summary>
+ /// Initializes a new instance of the <see cref="PPCWebClientBase"/> class.
+ /// </summary>
+ /// <param name="cloned">Other instance.</param>
+ public PPCWebClientBase(PPCWebClientBase cloned) : base(cloned)
+ {
+
+ }
+
+ /// <summary>
/// Executes the MachineSetup action and returns Tango.PPC.Common.Web.MachineSetupResponse.
/// </summary>
/// <returns></returns>
@@ -86,6 +95,33 @@ namespace Tango.PPC.Common.Web
}
/// <summary>
+ /// Executes the UploadMachineData action and returns Tango.PPC.Common.Web.UploadMachineDataResponse.
+ /// </summary>
+ /// <returns></returns>
+ public Task<Tango.PPC.Common.Web.UploadMachineDataResponse> UploadMachineData(Tango.PPC.Common.Web.UploadMachineDataRequest request)
+ {
+ return Post<Tango.PPC.Common.Web.UploadMachineDataRequest, Tango.PPC.Common.Web.UploadMachineDataResponse>("UploadMachineData", request);
+ }
+
+ /// <summary>
+ /// Executes the DownloadMachineData action and returns Tango.PPC.Common.Web.DownloadMachineDataResponse.
+ /// </summary>
+ /// <returns></returns>
+ public Task<Tango.PPC.Common.Web.DownloadMachineDataResponse> DownloadMachineData(Tango.PPC.Common.Web.DownloadMachineDataRequest request)
+ {
+ return Post<Tango.PPC.Common.Web.DownloadMachineDataRequest, Tango.PPC.Common.Web.DownloadMachineDataResponse>("DownloadMachineData", request);
+ }
+
+ /// <summary>
+ /// Executes the NotifyMachineDataDownloadCompleted action and returns Tango.PPC.Common.Web.NotifyMachineDataDownloadCompletedResponse.
+ /// </summary>
+ /// <returns></returns>
+ public Task<Tango.PPC.Common.Web.NotifyMachineDataDownloadCompletedResponse> NotifyMachineDataDownloadCompleted(Tango.PPC.Common.Web.NotifyMachineDataDownloadCompletedRequest request)
+ {
+ return Post<Tango.PPC.Common.Web.NotifyMachineDataDownloadCompletedRequest, Tango.PPC.Common.Web.NotifyMachineDataDownloadCompletedResponse>("NotifyMachineDataDownloadCompleted", request);
+ }
+
+ /// <summary>
/// Executes the GetLatestVersion action and returns Tango.PPC.Common.Web.LatestVersionResponse.
/// </summary>
/// <returns></returns>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs
new file mode 100644
index 000000000..c50044cbe
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/SynchronizationFailedEntity.cs
@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Tango.PPC.Common.Web
+{
+ public class SynchronizationFailedEntity
+ {
+ public String Guid { get; set; }
+ public String Reason { get; set; }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs
index f3b4ccb34..c78f6199e 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UpdateDBRequest.cs
@@ -10,5 +10,7 @@ namespace Tango.PPC.Common.Web
public class UpdateDBRequest : WebRequestMessage
{
public String SerialNumber { get; set; }
+ public String ApplicationVersion { get; set; }
+ public String FirmwareVersion { get; set; }
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs
new file mode 100644
index 000000000..dc0b05988
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.DTO;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.Web
+{
+ public class UploadMachineDataRequest : WebRequestMessage
+ {
+ public List<JobDTO> Jobs { get; set; }
+ public List<JobRunDTO> JobRuns { get; set; }
+ public List<MachinesEventDTO> MachineEvents { get; set; }
+ public String ApplicationVersion { get; set; }
+ public String FirmwareVersion { get; set; }
+
+ public UploadMachineDataRequest()
+ {
+ Jobs = new List<JobDTO>();
+ JobRuns = new List<JobRunDTO>();
+ MachineEvents = new List<MachinesEventDTO>();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs
new file mode 100644
index 000000000..e4dda4013
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.BL.DTO;
+using Tango.Transport.Web;
+
+namespace Tango.PPC.Common.Web
+{
+ public class UploadMachineDataResponse : WebResponseMessage
+ {
+ public List<SynchronizationFailedEntity> FailedJobs { get; set; }
+ public List<SynchronizationFailedEntity> FailedJobRuns { get; set; }
+ public List<SynchronizationFailedEntity> FailedMachineEvents { get; set; }
+ public String NotifyCompletedToken { get; set; }
+
+ public UploadMachineDataResponse()
+ {
+ FailedJobs = new List<SynchronizationFailedEntity>();
+ FailedJobRuns = new List<SynchronizationFailedEntity>();
+ FailedMachineEvents = new List<SynchronizationFailedEntity>();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config
new file mode 100644
index 000000000..731f6de6c
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/App.config
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+ <startup>
+ <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+ </startup>
+</configuration> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs
new file mode 100644
index 000000000..d77192de2
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Program.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Data.SqlClient;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.SQLExaminer;
+
+namespace Tango.PPC.SchemaSynchronizer.CLI
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Core.DataSource source = new Core.DataSource();
+ source.Address = "localhost\\SQLEXPRESS";
+ source.Catalog = "Tango";
+
+ Core.DataSource target = new Core.DataSource();
+ target.Address = "localhost\\SQLPPC";
+ target.Catalog = "Tango";
+
+ ExaminerConfigurationBuilder builder = new ExaminerConfigurationBuilder(ExaminerConfigurationType.Schema);
+
+ builder.
+ SetSource(source).
+ SetTarget(target).
+ Synchronize();
+
+ var config = builder.Build();
+
+ ExaminerProcess process = new ExaminerProcess(config, ExaminerProcessType.Schema);
+ process.Progress += (x, msg) =>
+ {
+ Console.WriteLine(msg);
+ };
+ var result = process.Execute().Result;
+
+ if (result.ExitCode == ExaminerProcessExitCode.Success)
+ {
+ Console.ForegroundColor = ConsoleColor.Green;
+ Console.WriteLine("Completed!");
+ }
+ else
+ {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine("Failed!");
+ }
+
+ Console.ReadLine();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Properties/AssemblyInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..61246489d
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/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.PPC.SchemaSynchronizer.CLI")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Tango.PPC.SchemaSynchronizer.CLI")]
+[assembly: AssemblyCopyright("Copyright © 2019")]
+[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("f3746f2b-e4ae-498b-9d42-74f95d992460")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj
new file mode 100644
index 000000000..529815ba2
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.SchemaSynchronizer.CLI/Tango.PPC.SchemaSynchronizer.CLI.csproj
@@ -0,0 +1,63 @@
+<?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>{F3746F2B-E4AE-498B-9D42-74F95D992460}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>Tango.PPC.SchemaSynchronizer.CLI</RootNamespace>
+ <AssemblyName>Tango.PPC.SchemaSynchronizer.CLI</AssemblyName>
+ <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+ <Deterministic>true</Deterministic>
+ </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="System" />
+ <Reference Include="System.Core" />
+ <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" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\..\Tango.Core\Tango.Core.csproj">
+ <Project>{a34ee0f0-649d-41c8-8489-b6f1cc6924ee}</Project>
+ <Name>Tango.Core</Name>
+ </ProjectReference>
+ <ProjectReference Include="..\..\Tango.SQLExaminer\Tango.SQLExaminer.csproj">
+ <Project>{e1e66ed9-597d-45fa-8048-de90a6930484}</Project>
+ <Name>Tango.SQLExaminer</Name>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
+</Project> \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config
index 77255b814..a55b50e5b 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.config
@@ -10,6 +10,9 @@
<runtime>
<legacyCorruptedStateExceptionsPolicy enabled="true|false"/>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <!--Required for cefCharp-->
+ <probing privatePath="x86"/>
+
<!--<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.2.2.0" newVersion="5.2.2.0" />
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
index f9261e754..ebe68a5d3 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/App.xaml.cs
@@ -105,6 +105,12 @@ namespace Tango.PPC.UI
{
e.TryRecover = true;
+ if (e.Exception.ToString().Contains("FocusVisualStyle"))
+ {
+ LogManager.Log("FocusVisualStyle Error occurred. Ignoring...");
+ return;
+ }
+
try
{
LogManager.Log(e.Exception, "Application Crashed!");
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml
new file mode 100644
index 000000000..776233955
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml
@@ -0,0 +1,32 @@
+<UserControl x:Class="Tango.PPC.UI.Dialogs.PowerUpView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:local="clr-namespace:Tango.PPC.UI.Dialogs"
+ mc:Ignorable="d"
+ Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DesignHeight="555" d:DesignWidth="560" Width="600" Height="800" d:DataContext="{d:DesignInstance Type=local:PowerUpViewVM, IsDesignTimeCreatable=False}">
+ <Grid>
+ <StackPanel Margin="0 100 0 0" HorizontalAlignment="Center">
+ <touch:TouchGifAnimation Source="../Images/powerup.gif" EnableAnimation="{Binding IsVisible}" />
+ <TextBlock HorizontalAlignment="Center" FontSize="{StaticResource TangoTitleFontSize}" Margin="0 30 0 0">Continue getting ready for:</TextBlock>
+ <DockPanel HorizontalAlignment="Center" Margin="0 40 0 0">
+ <touch:TouchRadioButton IsChecked="{Binding IsSelectedRml}" />
+ <touch:TouchComboBox Margin="20 0 0 0" Width="300" ItemsSource="{Binding Rmls}" SelectedItem="{Binding SelectedRml}" DisplayMemberPath="Name"></touch:TouchComboBox>
+ </DockPanel>
+ <DockPanel HorizontalAlignment="Left" Margin="0 40 0 0">
+ <touch:TouchRadioButton IsChecked="{Binding IsMinimalTemperature}" />
+ <TextBlock VerticalAlignment="Center" Margin="20 0 0 0">Minimal temperature</TextBlock>
+ </DockPanel>
+
+ <touch:TouchButton Command="{Binding OKCommand}" Margin="0 150 0 0" Style="{StaticResource TangoHollowButton}" HorizontalAlignment="Center" Padding="60 15">CONTINUE</touch:TouchButton>
+
+ <TextBlock HorizontalAlignment="Center" Margin="0 10 0 0" Visibility="{Binding IsTimeoutEnabled,Converter={StaticResource BooleanToVisibilityConverter}}">
+ <Run>auto select in</Run>
+ <Run Text="{Binding RemainingSeconds}"></Run>
+ <Run>sec</Run>
+ </TextBlock>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml.cs
new file mode 100644
index 000000000..a9767276a
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpView.xaml.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.PPC.UI.Dialogs
+{
+ /// <summary>
+ /// Interaction logic for PowerUpView.xaml
+ /// </summary>
+ public partial class PowerUpView : UserControl
+ {
+ public PowerUpView()
+ {
+ InitializeComponent();
+ }
+
+ protected override void OnPreviewMouseUp(MouseButtonEventArgs e)
+ {
+ base.OnPreviewMouseUp(e);
+ (DataContext as PowerUpViewVM).IsTimeoutEnabled = false;
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs
new file mode 100644
index 000000000..413b8453d
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/PowerUpViewVM.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Timers;
+using Tango.BL.Entities;
+using Tango.PPC.Common;
+using Tango.Settings;
+using Tango.SharedUI;
+
+namespace Tango.PPC.UI.Dialogs
+{
+ public class PowerUpViewVM : DialogViewVM
+ {
+ private Timer _timer;
+
+ private List<Rml> _rmls;
+ public List<Rml> Rmls
+ {
+ get { return _rmls; }
+ set { _rmls = value; RaisePropertyChangedAuto(); }
+ }
+
+ private Rml _selectedRml;
+ public Rml SelectedRml
+ {
+ get { return _selectedRml; }
+ set { _selectedRml = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isSelectedRml;
+ public bool IsSelectedRml
+ {
+ get { return _isSelectedRml; }
+ set
+ {
+ _isSelectedRml = value;
+ RaisePropertyChangedAuto();
+
+ if (_isSelectedRml)
+ {
+ IsMinimalTemperature = false;
+ }
+ }
+ }
+
+ private bool _isMinimalTemperature;
+ public bool IsMinimalTemperature
+ {
+ get { return _isMinimalTemperature; }
+ set
+ {
+ _isMinimalTemperature = value;
+ RaisePropertyChangedAuto();
+
+ if (_isMinimalTemperature)
+ {
+ IsSelectedRml = false;
+ }
+ }
+ }
+
+ private int _remainingSeconds;
+ public int RemainingSeconds
+ {
+ get { return _remainingSeconds; }
+ set { _remainingSeconds = value; RaisePropertyChangedAuto(); }
+ }
+
+ private bool _isTimeoutEnabled;
+ public bool IsTimeoutEnabled
+ {
+ get { return _isTimeoutEnabled; }
+ set
+ {
+ _isTimeoutEnabled = value; RaisePropertyChangedAuto();
+
+ if (!_isTimeoutEnabled)
+ {
+ _timer.Stop();
+ }
+ }
+ }
+
+ public PowerUpViewVM()
+ {
+ RemainingSeconds = (int)SettingsManager.Default.GetOrCreate<PPCSettings>().PowerUpScreenTimeout.TotalSeconds;
+ CanClose = false;
+ IsMinimalTemperature = true;
+ IsTimeoutEnabled = true;
+ _timer = new Timer();
+ _timer.Interval = TimeSpan.FromSeconds(1).TotalMilliseconds;
+ _timer.Elapsed += _timer_Elapsed;
+ }
+
+ private void _timer_Elapsed(object sender, ElapsedEventArgs e)
+ {
+ RemainingSeconds--;
+
+ if (RemainingSeconds == 0)
+ {
+ InvokeUI(() =>
+ {
+ Accept();
+ });
+ }
+ }
+
+ protected override void Cancel()
+ {
+ _timer.Stop();
+ base.Cancel();
+ }
+
+ protected override void Accept()
+ {
+ _timer.Stop();
+ base.Accept();
+ }
+
+ public override void OnShow()
+ {
+ base.OnShow();
+ _timer.Start();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml
index 231f5dabb..a175b655e 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Dialogs/UpdateFromFileView.xaml
@@ -6,16 +6,16 @@
xmlns:local="clr-namespace:Tango.PPC.UI.Dialogs"
xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
mc:Ignorable="d"
- Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DesignHeight="555" d:DesignWidth="560" Width="550" Height="450" d:DataContext="{d:DesignInstance Type=local:UpdateFromFileViewVM, IsDesignTimeCreatable=False}">
+ Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DesignHeight="555" d:DesignWidth="560" Width="570" Height="700" d:DataContext="{d:DesignInstance Type=local:UpdateFromFileViewVM, IsDesignTimeCreatable=False}">
<Grid Margin="20">
<DockPanel>
- <StackPanel DockPanel.Dock="Bottom" HorizontalAlignment="Right" Orientation="Horizontal">
- <touch:TouchButton Command="{Binding CloseCommand}" CornerRadius="25" Style="{StaticResource TangoMessageBoxButton}" HorizontalContentAlignment="Center" DockPanel.Dock="Right" Width="120" Height="50" VerticalAlignment="Bottom">CANCEL</touch:TouchButton>
- <touch:TouchButton Command="{Binding OKCommand}" CornerRadius="25" Style="{StaticResource TangoMessageBoxButton}" Foreground="{StaticResource TangoPrimaryAccentBrush}" HorizontalContentAlignment="Center" DockPanel.Dock="Right" Width="120" Height="50" VerticalAlignment="Bottom">UPDATE</touch:TouchButton>
- </StackPanel>
+ <Grid DockPanel.Dock="Bottom">
+ <touch:TouchButton HorizontalAlignment="Left" CornerRadius="25" Command="{Binding CloseCommand}" Style="{StaticResource TangoHollowButton}" Width="150" Height="50" VerticalAlignment="Bottom">CANCEL</touch:TouchButton>
+ <touch:TouchButton HorizontalAlignment="Right" CornerRadius="25" Command="{Binding OKCommand}" Style="{StaticResource TangoHollowButton}" Width="150" Height="50" VerticalAlignment="Bottom">UPDATE</touch:TouchButton>
+ </Grid>
<StackPanel>
<Image Source="../Images/update.png" Stretch="Uniform" Height="120"></Image>
- <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0" FontSize="{StaticResource TangoHeaderFontSize}">UPDATE PACKAGE</TextBlock>
+ <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0" FontSize="{StaticResource TangoHeaderFontSize}">Tango Update Package</TextBlock>
<TextBlock Margin="20 10" HorizontalAlignment="Center" TextWrapping="Wrap" TextAlignment="Center">The selected file contains a software update package. Press 'UPDATE' to start updating your system.</TextBlock>
<TextBlock HorizontalAlignment="Center" Margin="0 40 0 0" FontSize="{StaticResource TangoTitleFontSize}" Foreground="{StaticResource TangoGrayTextBrush}">
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/power_off.gif b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/power_off.gif
new file mode 100644
index 000000000..dd07593e2
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/power_off.gif
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/powerup.gif b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/powerup.gif
new file mode 100644
index 000000000..f435d38d1
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Images/powerup.gif
Binary files differ
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/InternalModule.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/InternalModule.cs
new file mode 100644
index 000000000..e960fa020
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/InternalModule.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media.Imaging;
+using Tango.BL.Enumerations;
+using Tango.PPC.Common;
+using Tango.PPC.UI.Views;
+
+namespace Tango.PPC.UI
+{
+ [PPCModule(100)]
+ public class InternalModule : PPCModuleBase
+ {
+ public InternalModule()
+ {
+ IsVisibleInMenu = false;
+ }
+
+ /// <summary>
+ /// Gets the module name.
+ /// </summary>
+ public override string Name
+ {
+ get
+ {
+ return "Internal";
+ }
+ }
+
+ /// <summary>
+ /// Gets the module description.
+ /// </summary>
+ public override string Description
+ {
+ get
+ {
+ return "Internal Module";
+ }
+ }
+
+ /// <summary>
+ /// Gets the module cover image.
+ /// </summary>
+ public override BitmapSource Image
+ {
+ get
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Gets the module entry point view type.
+ /// </summary>
+ public override Type MainViewType
+ {
+ get
+ {
+ return typeof(InternalModuleView);
+ }
+ }
+
+ /// <summary>
+ /// Gets the permission required to see and load this module.
+ /// </summary>
+ public override Permissions Permission
+ {
+ get
+ {
+ return Permissions.RunPPC;
+ }
+ }
+
+ /// <summary>
+ /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
+ /// </summary>
+ public override void Dispose()
+ {
+ //Dispose module here...
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Modules/DefaultStudioModuleLoader.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Modules/DefaultStudioModuleLoader.cs
index feb7e371f..375b648d0 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Modules/DefaultStudioModuleLoader.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Modules/DefaultStudioModuleLoader.cs
@@ -103,7 +103,7 @@ namespace Tango.PPC.UI.Modules
if (moduleAssembly != null)
{
- foreach (var moduleType in moduleAssembly.GetTypes().Where(x => !x.IsInterface && typeof(IPPCModule).IsAssignableFrom(x) && !x.IsAbstract))
+ foreach (var moduleType in moduleAssembly.GetLoadableTypes().Where(x => !x.IsInterface && typeof(IPPCModule).IsAssignableFrom(x) && !x.IsAbstract))
{
if (!AllModules.ToList().Exists(x => x.GetType() == moduleType))
{
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs
index 2a825cc19..3502648d4 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Navigation/DefaultNavigationManager.cs
@@ -12,6 +12,7 @@ using Tango.Core.Commands;
using Tango.PPC.Common;
using Tango.PPC.Common.Modules;
using Tango.PPC.Common.Navigation;
+using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.Threading;
using Tango.PPC.UI.Views;
using Tango.SharedUI.Controls;
@@ -36,6 +37,7 @@ namespace Tango.PPC.UI.Navigation
private List<AwaitingVMResult> _awaitingVMResults;
private IDispatcherProvider _dispatcherProvider;
private IPPCModuleLoader _moduleLoader;
+ private INotificationProvider _notificationProvider;
private Object _currentVM;
private String _lastFullPath;
private bool _preventHistory;
@@ -75,12 +77,13 @@ namespace Tango.PPC.UI.Navigation
/// Initializes a new instance of the <see cref="DefaultNavigationManager"/> class.
/// </summary>
/// <param name="moduleLoader">The module loader.</param>
- public DefaultNavigationManager(IPPCModuleLoader moduleLoader, IDispatcherProvider dispatcherProvider)
+ public DefaultNavigationManager(IPPCModuleLoader moduleLoader, IDispatcherProvider dispatcherProvider, INotificationProvider notificationProvider)
{
IsBackEnabled = true;
_awaitingVMResults = new List<AwaitingVMResult>();
_navigationHistory = new Stack<String>();
_moduleLoader = moduleLoader;
+ _notificationProvider = notificationProvider;
NavigateToCommand = new RelayCommand<string>(async (x) => await NavigateTo(x));
NavigateBackCommand = new RelayCommand(async () => await NavigateBack());
@@ -197,105 +200,127 @@ namespace Tango.PPC.UI.Navigation
/// <param name="fullPath">The full path.</param>
public async Task<bool> NavigateTo(String fullPath, bool pushToHistory = true, Action<PPCViewModel, PPCViewModel> onNavigating = null, Action<PPCViewModel, PPCViewModel> onNavigated = null)
{
- String[] path = fullPath.Split('.');
- var module = _moduleLoader.UserModules.SingleOrDefault(x => x.GetType().Name == path[0] || x.Name == path[0]);
+ try
+ {
+ String[] path = fullPath.Split('.');
+ var module = _moduleLoader.UserModules.SingleOrDefault(x => x.GetType().Name == path[0] || x.Name == path[0]);
+
+ if (module == null)
+ {
+ await _notificationProvider.ShowError("The specified module was not loaded.");
+ return false;
+ }
- if (path.Length == 1 && path[0] == CurrentModule.Name) return true;
+ if (path.Length == 1 && path[0] == CurrentModule.Name) return true;
- LogManager.Log($"Navigating to: {fullPath}...");
+ LogManager.Log($"Navigating to: {fullPath}...");
- var fromVM = _currentVM;
+ var fromVM = _currentVM;
- if (_currentVM != null && _currentVM is INavigationBlocker)
- {
- if (_navigating_back)
+ if (_currentVM != null && _currentVM is INavigationBlocker)
{
- if (!await (_currentVM as INavigationBlocker).OnNavigateBackRequest())
+ if (_navigating_back)
{
- return false;
+ if (!await (_currentVM as INavigationBlocker).OnNavigateBackRequest())
+ {
+ return false;
+ }
}
- }
- else
- {
- if (!await (_currentVM as INavigationBlocker).OnNavigateOutRequest())
+ else
{
- return false;
+ if (!await (_currentVM as INavigationBlocker).OnNavigateOutRequest())
+ {
+ return false;
+ }
}
}
- }
- if (pushToHistory && _lastFullPath != null && !_preventHistory)
- {
- _navigationHistory.Push(_lastFullPath);
- RaisePropertyChanged(nameof(CanNavigateBack));
- }
-
- _lastFullPath = fullPath;
+ if (pushToHistory && _lastFullPath != null && !_preventHistory)
+ {
+ _navigationHistory.Push(_lastFullPath);
+ RaisePropertyChanged(nameof(CanNavigateBack));
+ }
- MainView.Instance.NavigationControl.NavigateTo(NavigationView.LayoutView.ToString());
- var navigationControl = LayoutView.Instance.NavigationControl;
- CurrentModule = module;
- var moduleView = navigationControl.NavigateTo(module.Name);
+ _lastFullPath = fullPath;
- _currentVM = moduleView.DataContext;
+ MainView.Instance.NavigationControl.NavigateTo(NavigationView.LayoutView.ToString());
+ var navigationControl = LayoutView.Instance.NavigationControl;
+ CurrentModule = module;
+ var moduleView = navigationControl.NavigateTo(module.Name);
- if (path.Length > 1)
- {
- var moduleNavigation = moduleView.FindChildOffline<NavigationControl>();
+ _currentVM = moduleView.DataContext;
- if (moduleNavigation != null)
+ if (path.Length > 1)
{
- moduleNavigation.RegisterForLoadedOrNow(async (x, e) =>
- {
- var lastView = moduleNavigation.GetElement(path.Last());
-
- if (lastView != null)
- {
- onNavigating?.Invoke(fromVM as PPCViewModel, lastView.DataContext as PPCViewModel);
- }
+ var moduleNavigation = moduleView.FindChildOffline<NavigationControl>();
- foreach (var view in path.Skip(1))
+ if (moduleNavigation != null)
+ {
+ moduleNavigation.RegisterForLoadedOrNow(async (x, e) =>
{
- await Task.Delay(100);
+ var lastView = moduleNavigation.GetElement(path.Last());
- FrameworkElement v = null;
+ if (lastView != null)
+ {
+ onNavigating?.Invoke(fromVM as PPCViewModel, lastView.DataContext as PPCViewModel);
+ }
- v = moduleNavigation.NavigateTo(view, () =>
+ foreach (var view in path.Skip(1))
{
- if (v != null)
+ await Task.Delay(100);
+
+ FrameworkElement v = null;
+
+ v = moduleNavigation.NavigateTo(view, () =>
{
- NotifyOnNavigated(fromVM, v.DataContext);
- onNavigated?.Invoke(fromVM as PPCViewModel, v.DataContext as PPCViewModel);
- NotifyAwaitingVMResults(fromVM as PPCViewModel, v.DataContext as PPCViewModel);
- }
- });
+ if (v != null)
+ {
+ NotifyOnNavigated(fromVM, v.DataContext);
+ onNavigated?.Invoke(fromVM as PPCViewModel, v.DataContext as PPCViewModel);
+ NotifyAwaitingVMResults(fromVM as PPCViewModel, v.DataContext as PPCViewModel);
+ }
+ });
- NotifyOnBeforeNavigated(fromVM, v.DataContext);
+ NotifyOnBeforeNavigated(fromVM, v.DataContext);
- if (v != null)
- {
- _currentVM = v.DataContext;
+ if (v != null)
+ {
+ _currentVM = v.DataContext;
- if (view != path.Last())
+ if (view != path.Last())
+ {
+ moduleNavigation = v.FindChildOffline<NavigationControl>();
+ }
+ }
+ else
{
- moduleNavigation = v.FindChildOffline<NavigationControl>();
+ throw LogManager.Log(new ArgumentNullException("Could not navigate to " + fullPath));
}
}
- else
- {
- throw LogManager.Log(new ArgumentNullException("Could not navigate to " + fullPath));
- }
- }
- });
+ });
+ }
+ else
+ {
+ onNavigating?.Invoke(fromVM as PPCViewModel, _currentVM as PPCViewModel);
+
+ NotifyOnBeforeNavigated(fromVM, _currentVM);
+
+ await Task.Delay(navigationControl.TransitionDuration.TimeSpan);
+
+ NotifyOnNavigated(fromVM, _currentVM);
+
+ onNavigated?.Invoke(fromVM as PPCViewModel, _currentVM as PPCViewModel);
+ NotifyAwaitingVMResults(fromVM as PPCViewModel, _currentVM as PPCViewModel);
+ }
}
else
{
- onNavigating?.Invoke(fromVM as PPCViewModel, _currentVM as PPCViewModel);
-
NotifyOnBeforeNavigated(fromVM, _currentVM);
+ onNavigating?.Invoke(fromVM as PPCViewModel, _currentVM as PPCViewModel);
+
await Task.Delay(navigationControl.TransitionDuration.TimeSpan);
NotifyOnNavigated(fromVM, _currentVM);
@@ -303,22 +328,14 @@ namespace Tango.PPC.UI.Navigation
onNavigated?.Invoke(fromVM as PPCViewModel, _currentVM as PPCViewModel);
NotifyAwaitingVMResults(fromVM as PPCViewModel, _currentVM as PPCViewModel);
}
+
+ return true;
}
- else
+ catch (Exception ex)
{
- NotifyOnBeforeNavigated(fromVM, _currentVM);
-
- onNavigating?.Invoke(fromVM as PPCViewModel, _currentVM as PPCViewModel);
-
- await Task.Delay(navigationControl.TransitionDuration.TimeSpan);
-
- NotifyOnNavigated(fromVM, _currentVM);
-
- onNavigated?.Invoke(fromVM as PPCViewModel, _currentVM as PPCViewModel);
- NotifyAwaitingVMResults(fromVM as PPCViewModel, _currentVM as PPCViewModel);
+ await _notificationProvider.ShowError($"Error navigating to '{fullPath}'.");
+ return false;
}
-
- return true;
}
/// <summary>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
index 44b6ffded..149fb549f 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/PPCApplication/DefaultPPCApplicationManager.cs
@@ -33,6 +33,7 @@ using Tango.Core.Threading;
using Tango.PPC.Common.Messages;
using Tango.Core.ExtensionMethods;
using Tango.PPC.Common.Navigation;
+using Tango.PPC.Common.Synchronization;
namespace Tango.PPC.UI.PPCApplication
{
@@ -50,6 +51,7 @@ namespace Tango.PPC.UI.PPCApplication
private IEventLogger _eventLogger;
private IPPCModuleLoader _moduleLoader;
private INotificationProvider _notificationProvider;
+ private IMachineDataSynchronizer _machineDataSynchronizer;
private WatchDogServer _watchdogServer;
private ObservablesContext _machineContext;
private ActionTimer _screenLockTimer;
@@ -147,15 +149,34 @@ namespace Tango.PPC.UI.PPCApplication
}
/// <summary>
+ /// Gets the firmware version.
+ /// </summary>
+ public Version FirmwareVersion
+ {
+ get
+ {
+ return Version.Parse(SettingsManager.Default.GetOrCreate<PPCSettings>().FirmwareVersion);
+ }
+ }
+
+ /// <summary>
+ /// Gets or sets the application folder.
+ /// </summary>
+ public String StartPath { get; private set; }
+
+ /// <summary>
/// Initializes a new instance of the <see cref="DefaultPPCApplicationManager"/> class.
/// </summary>
- public DefaultPPCApplicationManager(IMachineProvider machineProvider, IDispatcherProvider dispatcherProvider, IEventLogger eventLogger, IPPCModuleLoader moduleLoader, INotificationProvider notificationProvider)
+ public DefaultPPCApplicationManager(IMachineProvider machineProvider, IDispatcherProvider dispatcherProvider, IEventLogger eventLogger, IPPCModuleLoader moduleLoader, INotificationProvider notificationProvider, IMachineDataSynchronizer machineDataSynchronizer)
{
+ StartPath = AssemblyHelper.GetCurrentAssemblyFolder();
+
_notificationProvider = notificationProvider;
_machineProvider = machineProvider;
_dispatcher = dispatcherProvider;
_eventLogger = eventLogger;
_moduleLoader = moduleLoader;
+ _machineDataSynchronizer = machineDataSynchronizer;
if (!DesignMode)
{
@@ -248,6 +269,8 @@ namespace Tango.PPC.UI.PPCApplication
LogManager.Log("Loading machine from database...");
_machineContext = ObservablesContext.CreateDefault();
_machine = new MachineBuilder(_machineContext).SetFirst().WithVersion().WithSettings().WithOrganization().WithConfiguration().WithSpools().WithCats().Build();
+
+
}
initialized = true;
@@ -305,6 +328,8 @@ namespace Tango.PPC.UI.PPCApplication
}
}
+ var internalModules = this.GetType().Assembly.GetTypes().Where(xx => typeof(PPCModuleBase).IsAssignableFrom(xx)).ToList();
+
LogManager.Log("Waiting for IPPCModuleLoader instance injection...");
TangoIOC.Default.GetInstanceWhenAvailable<IPPCModuleLoader>((loader) =>
{
@@ -319,12 +344,32 @@ namespace Tango.PPC.UI.PPCApplication
{
if (!Views.LayoutView.Instance.NavigationControl.Elements.ToList().Exists(m => m.GetType() == module.MainViewType))
{
- LogManager.Log("Loading module view " + module.Name + "...");
- FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement;
- SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name);
- Views.LayoutView.Instance.NavigationControl.Elements.Add(view);
+ try
+ {
+ LogManager.Log("Loading module view " + module.Name + "...");
+ FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement;
+ SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name);
+ Views.LayoutView.Instance.NavigationControl.Elements.Add(view);
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, $"Error loading module view for module {module.Name}.");
+ }
}
}
+
+ //Adding internal modules.
+ LogManager.Log("Loading internal modules...");
+ foreach (var type in internalModules)
+ {
+ var module = Activator.CreateInstance(type) as IPPCModule;
+ LogManager.Log("Loading module view " + module.Name + "...");
+ FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement;
+ SharedUI.Controls.NavigationControl.SetNavigationName(view, module.Name);
+ Views.LayoutView.Instance.NavigationControl.Elements.Add(view);
+ _moduleLoader.AllModules.Add(module);
+ _moduleLoader.UserModules.Add(module);
+ }
});
LogManager.Log($"{loader.UserModules.Count} modules loaded.");
@@ -349,6 +394,9 @@ namespace Tango.PPC.UI.PPCApplication
LogManager.Log("Initializing Machine Provider...");
_machineProvider.Init(_machine, _machineContext);
+ LogManager.Log("Starting Machine Data Synchronizer...");
+ _machineDataSynchronizer.IsEnabled = true;
+
LogManager.Log("Applications initialization completed!");
LogManager.Log("Checking for un-notified PPC view models...");
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs
index 56ec2fa7e..4c5a87ab4 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Printing/DefaultPrintingManager.cs
@@ -259,7 +259,7 @@ namespace Tango.PPC.UI.Printing
{
throw new InvalidOperationException("Error starting job. Color is out of range.");
}
- if (job.Segments.SelectMany(x => x.BrushStops).Any(x => x.BrushColorSpace == ColorSpaces.Catalog && x.ColorCatalogsItem == null))
+ if (job.Segments.SelectMany(x => x.BrushStops).Any(x => x.BrushColorSpace == ColorSpaces.Catalog && x.ColorCatalogsItem == null && !x.IsTransparent))
{
throw new InvalidOperationException("Error starting job. Please select a catalog color.");
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
index ab5492ab6..96891a8a9 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Tango.PPC.UI.csproj
@@ -132,6 +132,10 @@
<DependentUpon>InsufficientLiquidQuantityView.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\InsufficientLiquidQuantityViewVM.cs" />
+ <Compile Include="Dialogs\PowerUpView.xaml.cs">
+ <DependentUpon>PowerUpView.xaml</DependentUpon>
+ </Compile>
+ <Compile Include="Dialogs\PowerUpViewVM.cs" />
<Compile Include="Dialogs\ScreenLockView.xaml.cs">
<DependentUpon>ScreenLockView.xaml</DependentUpon>
</Compile>
@@ -145,6 +149,7 @@
<DependentUpon>UpdateFromFileView.xaml</DependentUpon>
</Compile>
<Compile Include="Dialogs\UpdateFromFileViewVM.cs" />
+ <Compile Include="InternalModule.cs" />
<Compile Include="Modules\DefaultStudioModuleLoader.cs" />
<Compile Include="Navigation\DefaultNavigationManager.cs" />
<Compile Include="Notifications\DefaultNotificationProvider.cs" />
@@ -160,6 +165,7 @@
<Compile Include="ViewModelLocator.cs" />
<Compile Include="ViewModels\EmergencyViewVM.cs" />
<Compile Include="ViewModels\ExternalBridgeViewVM.cs" />
+ <Compile Include="ViewModels\InternalModuleViewVM.cs" />
<Compile Include="ViewModels\LayoutViewVM.cs" />
<Compile Include="ViewModels\LoadingErrorViewVM.cs" />
<Compile Include="ViewModels\LoadingViewVM.cs" />
@@ -168,6 +174,7 @@
<Compile Include="ViewModels\MainViewVM.cs" />
<Compile Include="ViewModels\MachineUpdateViewVM.cs" />
<Compile Include="ViewModels\NoPermissionsViewVM.cs" />
+ <Compile Include="ViewModels\PowerOffViewVM.cs" />
<Compile Include="ViewModels\RestartingSystemViewVM.cs" />
<Compile Include="ViewModels\RestartingViewVM.cs" />
<Compile Include="ViewsContracts\ILayoutView.cs" />
@@ -176,6 +183,9 @@
<Compile Include="Views\ExternalBridgeView.xaml.cs">
<DependentUpon>ExternalBridgeView.xaml</DependentUpon>
</Compile>
+ <Compile Include="Views\InternalModuleView.xaml.cs">
+ <DependentUpon>InternalModuleView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\LayoutView.xaml.cs">
<DependentUpon>LayoutView.xaml</DependentUpon>
</Compile>
@@ -185,6 +195,9 @@
<Compile Include="Views\LoadingErrorView.xaml.cs">
<DependentUpon>LoadingErrorView.xaml</DependentUpon>
</Compile>
+ <Compile Include="Views\PowerOffView.xaml.cs">
+ <DependentUpon>PowerOffView.xaml</DependentUpon>
+ </Compile>
<Compile Include="Views\RestartingView.xaml.cs">
<DependentUpon>RestartingView.xaml</DependentUpon>
</Compile>
@@ -225,6 +238,10 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
+ <Page Include="Dialogs\PowerUpView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Dialogs\ScreenLockView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -269,6 +286,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\InternalModuleView.xaml">
+ <SubType>Designer</SubType>
+ <Generator>MSBuild:Compile</Generator>
+ </Page>
<Page Include="Views\LayoutView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
@@ -281,6 +302,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
+ <Page Include="Views\PowerOffView.xaml">
+ <Generator>MSBuild:Compile</Generator>
+ <SubType>Designer</SubType>
+ </Page>
<Page Include="Views\RestartingView.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -374,6 +399,8 @@
<Resource Include="Images\GlobalStatus\error.png" />
<Resource Include="Images\GlobalStatus\service.png" />
<Resource Include="Images\update_available.png" />
+ <Resource Include="Images\powerup.gif" />
+ <Resource Include="Images\power_off.gif" />
<Content Include="Manifests\release.xml" />
<Content Include="Manifests\debug.xml" />
<None Include="firmware_package.tfp">
@@ -465,6 +492,11 @@
<Project>{bc2753f8-c0f7-48f5-a85c-149ec7a2f8c7}</Project>
<Name>Tango.PPC.BackupRestore</Name>
</ProjectReference>
+ <ProjectReference Include="..\Modules\Tango.PPC.Browser\Tango.PPC.Browser.csproj">
+ <Project>{f02eaa84-ad59-465b-99a2-4422c13bfb72}</Project>
+ <Name>Tango.PPC.Browser</Name>
+ <Private>True</Private>
+ </ProjectReference>
<ProjectReference Include="..\Modules\Tango.PPC.BugReporting\Tango.PPC.BugReporting.csproj">
<Project>{8146fa0a-0725-4a1a-82e6-696c58f33a2b}</Project>
<Name>Tango.PPC.BugReporting</Name>
@@ -609,8 +641,8 @@ RD /S /Q "$(TargetDir)pt-BR\"
RD /S /Q "$(TargetDir)roslyn\"
RD /S /Q "$(TargetDir)ProtoCompilers\"
-RD /S /Q "$(TargetDir)x86\"
-RD /S /Q "$(TargetDir)x64\"
+if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)x86\"
+if $(ConfigurationName) == Release RD /S /Q "$(TargetDir)x64\"
copy /Y "$(SolutionDir)Referenced Assemblies\mscoree.dll" "$(TargetDir)"
copy /Y "$(SolutionDir)Referenced Assemblies\msvcp140d.dll" "$(TargetDir)"
@@ -626,7 +658,8 @@ if $(ConfigurationName) == Release del *.xml
if $(ConfigurationName) == Debug copy /Y "$(TargetDir)Packages" "$(TargetDir)"</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
- <PreBuildEvent>copy /Y "$(ProjectDir)Manifests\$(ConfigurationName).xml" "$(ProjectDir)app.manifest"</PreBuildEvent>
+ <PreBuildEvent>copy /Y "$(ProjectDir)Manifests\$(ConfigurationName).xml" "$(ProjectDir)app.manifest"
+</PreBuildEvent>
</PropertyGroup>
<ProjectExtensions>
<VisualStudio>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
index 60bce4e20..09ed7c6d0 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModelLocator.cs
@@ -1,4 +1,5 @@
using System;
+using System.Linq;
using System.Windows;
using Tango.Core.DI;
using Tango.Integration.ExternalBridge;
@@ -21,6 +22,7 @@ using Tango.PPC.Common.OS;
using Tango.PPC.Common.Printing;
using Tango.PPC.Common.RemoteAssistance;
using Tango.PPC.Common.Storage;
+using Tango.PPC.Common.Synchronization;
using Tango.PPC.Common.Threading;
using Tango.PPC.Common.UpdatePackages;
using Tango.PPC.Common.UWF;
@@ -75,8 +77,17 @@ namespace Tango.PPC.UI
TangoIOC.Default.Unregister<PPCWebClient>();
TangoIOC.Default.Unregister<IBackupManager>();
TangoIOC.Default.Unregister<IPackageRunner>();
+ TangoIOC.Default.Unregister<IMachineDataSynchronizer>();
+
+ if (App.StartupArgs.Contains("-webDebug"))
+ {
+ TangoIOC.Default.Register<PPCWebClient, PPCWebClient>(new PPCWebClient("http://localhost:1111", null));
+ }
+ else
+ {
+ TangoIOC.Default.Register<PPCWebClient, PPCWebClient>(new PPCWebClient());
+ }
- TangoIOC.Default.Register<PPCWebClient, PPCWebClient>(new PPCWebClient());
TangoIOC.Default.Register<IDispatcherProvider, DefaultDispatcherProvider>(new DefaultDispatcherProvider(Application.Current.Dispatcher));
TangoIOC.Default.Register<INotificationProvider, DefaultNotificationProvider>();
TangoIOC.Default.Register<IAuthenticationProvider, DefaultAuthenticationProvider>();
@@ -84,6 +95,7 @@ namespace Tango.PPC.UI
TangoIOC.Default.Register<INavigationManager, DefaultNavigationManager>();
TangoIOC.Default.Register<IMachineProvider, DefaultMachineProvider>();
TangoIOC.Default.Register<IEventLogger, DefaultEventLogger>();
+ TangoIOC.Default.Register<IMachineDataSynchronizer, DefaultMachineDataSynchronizer>();
TangoIOC.Default.Register<IPPCApplicationManager, DefaultPPCApplicationManager>();
TangoIOC.Default.Register<ExternalBridgeScanner, ExternalBridgeScanner>();
TangoIOC.Default.Register<IDiagnosticsFrameProvider, DefaultDiagnosticsFrameProvider>();
@@ -112,6 +124,8 @@ namespace Tango.PPC.UI
TangoIOC.Default.Register<RestartingSystemViewVM>();
TangoIOC.Default.Register<EmergencyViewVM>();
TangoIOC.Default.Register<RestartingViewVM>();
+ TangoIOC.Default.Register<InternalModuleViewVM>();
+ TangoIOC.Default.Register<PowerOffViewVM>();
TangoIOC.Default.GetInstance<IPPCApplicationManager>().ContentRendered += (_, __) =>
@@ -225,5 +239,21 @@ namespace Tango.PPC.UI
return TangoIOC.Default.GetInstance<RestartingViewVM>();
}
}
+
+ public static InternalModuleViewVM InternalModuleViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<InternalModuleViewVM>();
+ }
+ }
+
+ public static PowerOffViewVM PowerOffViewVM
+ {
+ get
+ {
+ return TangoIOC.Default.GetInstance<PowerOffViewVM>();
+ }
+ }
}
} \ No newline at end of file
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/InternalModuleViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/InternalModuleViewVM.cs
new file mode 100644
index 000000000..29e6417f4
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/InternalModuleViewVM.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.PPC.Common;
+
+namespace Tango.PPC.UI.ViewModels
+{
+ public class InternalModuleViewVM : PPCViewModel
+ {
+ public override void OnApplicationStarted()
+ {
+
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs
index 9e8a9fe34..e18354f89 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/LayoutViewVM.cs
@@ -10,6 +10,7 @@ using Tango.Integration.Operation;
using Tango.PPC.Common;
using Tango.PPC.Common.Modules;
using Tango.PPC.Common.Navigation;
+using Tango.PPC.UI.Views;
using Tango.PPC.UI.ViewsContracts;
using Tango.SharedUI;
@@ -121,6 +122,11 @@ namespace Tango.PPC.UI.ViewModels
/// </summary>
public RelayCommand RestartApplicationCommand { get; set; }
+ /// <summary>
+ /// Gets or sets the power off command.
+ /// </summary>
+ public RelayCommand PowerOffCommand { get; set; }
+
#endregion
#region Constructors
@@ -146,6 +152,7 @@ namespace Tango.PPC.UI.ViewModels
PowerCommand = new RelayCommand(() => IsPowerOpened = true);
RestartApplicationCommand = new RelayCommand(RestartApplication);
+ PowerOffCommand = new RelayCommand(PowerOffMachine);
}
#endregion
@@ -239,6 +246,12 @@ namespace Tango.PPC.UI.ViewModels
}
}
+ private async void PowerOffMachine()
+ {
+ IsMenuOpened = false;
+ await NavigationManager.NavigateTo<InternalModule>(nameof(PowerOffView));
+ }
+
#endregion
#region Override Methods
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs
index 0371e94da..49b2aef89 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MachineUpdateViewVM.cs
@@ -10,6 +10,7 @@ using Tango.Core.Helpers;
using Tango.Explorer;
using Tango.PPC.Common;
using Tango.PPC.Common.MachineUpdate;
+using Tango.PPC.Common.Publish;
using Tango.PPC.Common.Web;
using Tango.PPC.UI.Dialogs;
using Tango.PPC.UI.Notifications.NotificationItems;
@@ -209,7 +210,7 @@ namespace Tango.PPC.UI.ViewModels
try
{
- _update_result = await MachineUpdateManager.Update(MachineProvider.Machine.SerialNumber, _checkUpdateResponse.SetupFirmware, _checkUpdateResponse.SetupFPGA);
+ _update_result = await MachineUpdateManager.Update(_checkUpdateResponse.SetupFirmware, _checkUpdateResponse.SetupFPGA);
LogManager.Log("Machine update completed.");
await NavigateTo(MachineUpdateView.UpdateCompletedView);
}
@@ -248,15 +249,15 @@ namespace Tango.PPC.UI.ViewModels
{
LogManager.Log("Completing machine update...");
- if (!IsDbUpdate)
+ if (IsDbUpdate || !_update_result.RequiresBinariesUpdate)
{
- String updater_exe = Path.Combine(_update_result.UpdatePackagePath, "Tango.PPC.Updater.exe");
- ApplicationManager.UpdateApplication(updater_exe, PathHelper.GetStartupPath());
+ LogManager.Log("Restarting Application...");
+ ApplicationManager.Restart();
}
else
{
- LogManager.Log("Restarting Application...");
- ApplicationManager.Restart();
+ String updater_exe = Path.Combine(_update_result.UpdatePackagePath, "Tango.PPC.Updater.exe");
+ ApplicationManager.UpdateApplication(updater_exe, PathHelper.GetStartupPath());
}
}
@@ -296,7 +297,7 @@ namespace Tango.PPC.UI.ViewModels
}
else
{
- MachineUpdateManager.AutoCheckForUpdates = MachineProvider.Machine.AutoCheckForUpdates;
+ MachineUpdateManager.EnableAutoCheckForUpdates = true;
}
}
@@ -375,7 +376,7 @@ namespace Tango.PPC.UI.ViewModels
private async void HandleSoftwareUpdatePackageLoaded(ExplorerFileItem fileItem)
{
- UpdatePackageFile packageFile = null;
+ PublishInfo packageFile = null;
try
{
@@ -383,38 +384,33 @@ namespace Tango.PPC.UI.ViewModels
}
catch (Exception ex)
{
- LogManager.Log(ex, $"Error loading update package file from {fileItem.Path}.");
+ LogManager.Log(ex, $"Error loading publish info from {fileItem.Path}.");
await NotificationProvider.ShowError("An error occurred while trying to load the selected software update package. Please make sure the package is valid.");
return;
}
- if (ApplicationManager.Version <= packageFile.Version)
- {
- await NotificationProvider.ShowError($"The selected update package (v{packageFile.Version.ToString()}) contains an older software version.");
- return;
- }
-
UpdateFromFileViewVM vm = new UpdateFromFileViewVM();
- vm.Version = packageFile.Version.ToString();
+ vm.Version = packageFile.ApplicationVersion;
await NotificationProvider.ShowDialog(vm);
if (vm.DialogResult)
{
await NavigationManager.NavigateTo(Common.Navigation.NavigationView.MachineUpdateView);
- await NavigateTo(MachineUpdateView.UpdateFromPackageView);
+ await NavigateTo(MachineUpdateView.UpdateProgressView);
LogManager.Log("Starting machine update from package...");
try
{
- _update_result = await MachineUpdateManager.UpdateFromTUP(fileItem.Path);
+ _update_result = await MachineUpdateManager.UpdateFromTUP(fileItem.Path, MachineProvider.Machine.SetupFirmware, MachineProvider.Machine.SetupFpga);
LogManager.Log("Machine update from package completed.");
await NavigateTo(MachineUpdateView.UpdateCompletedView);
}
catch (Exception ex)
{
LogManager.Log(ex, "Machine update from package failed.");
+ FailedError = ex.FlattenMessage();
await NavigateTo(MachineUpdateView.UpdateFailedFromPackageView);
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MainViewVM.cs
index 01a47539e..8a4d20b76 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MainViewVM.cs
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/MainViewVM.cs
@@ -4,6 +4,9 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading;
+using Tango.BL;
+using Tango.BL.Builders;
+using Tango.BL.Entities;
using Tango.Core.DI;
using Tango.Integration.ExternalBridge;
using Tango.Integration.Operation;
@@ -17,6 +20,7 @@ using Tango.PPC.Common.Notifications;
using Tango.PPC.Common.WatchDog;
using Tango.PPC.UI.Dialogs;
using Tango.SharedUI;
+using System.Data.Entity;
namespace Tango.PPC.UI.ViewModels
{
@@ -58,6 +62,7 @@ namespace Tango.PPC.UI.ViewModels
{
base.OnApplicationReady();
MachineProvider.MachineOperator.CartridgeValidationRequestReceived += MachineOperator_CartridgeValidationRequestReceived;
+ MachineProvider.MachineOperator.PowerUpStarted += MachineOperator_PowerUpStarted;
}
#region Event Handlers
@@ -92,6 +97,86 @@ namespace Tango.PPC.UI.ViewModels
});
}
+ private async void MachineOperator_PowerUpStarted(object sender, EventArgs e)
+ {
+ LogManager.Log("Power up detected, showing power up screen...");
+
+ if (!Settings.DisplayPowerUpScreen)
+ {
+ LogManager.Log("Power up screen disabled. skipping...");
+ return;
+ }
+
+ PowerUpViewVM vm;
+
+ try
+ {
+ LogManager.Log("Loading site rmls...");
+
+ List<Rml> rmls = new List<Rml>();
+
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ rmls = await new RmlsCollectionBuilder(db).SetAll().WithSite(MachineProvider.Machine.SiteGuid).BuildListAsync();
+ }
+
+ var selectedRml = rmls.SingleOrDefault(x => x.Guid == Settings.LastPowerUpSelectedRmlGuid);
+
+ vm = new PowerUpViewVM();
+ vm.Rmls = rmls;
+ vm.SelectedRml = selectedRml != null ? selectedRml : rmls.FirstOrDefault();
+ vm.IsSelectedRml = selectedRml != null;
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error initializing power up screen.");
+ return;
+ }
+
+ InvokeUI(async () =>
+ {
+ await NotificationProvider.ShowDialog<PowerUpViewVM>(vm);
+
+ await Task.Factory.StartNew(() =>
+ {
+ LogManager.Log("Power up screen closed.");
+
+ try
+ {
+ using (ObservablesContext db = ObservablesContext.CreateDefault())
+ {
+ List<ProcessParametersTable> processTables = new List<ProcessParametersTable>();
+
+ if (vm.IsSelectedRml)
+ {
+ LogManager.Log($"Selected rml '{vm.SelectedRml.Name}'...");
+ processTables = new RmlBuilder(db).Set(vm.SelectedRml.Guid).WithActiveParametersGroup().Build().GetActiveProcessGroup().ProcessParametersTables.ToList();
+ }
+ else
+ {
+ LogManager.Log("Selected minimal temperature...");
+ var rmlsToAvg = new RmlsCollectionBuilder(db).SetAll().WithSite(MachineProvider.Machine.SiteGuid).WithActiveParametersGroup().Build();
+ processTables = rmlsToAvg.Select(x => x.GetActiveProcessGroup()).SelectMany(x => x.ProcessParametersTables).ToList();
+ }
+
+ var processToLoad = processTables.OrderBy(x => x.GetAverageTemperature()).First();
+
+ LogManager.Log($"Selected process parameters:\nRML: {processToLoad.ProcessParametersTablesGroup.Rml.Name}\nGroup: {processToLoad.ProcessParametersTablesGroup.Name}\nProcess Table: {processToLoad.Name}");
+ LogManager.Log("Uploading process parameters...");
+ var r = MachineProvider.MachineOperator.UploadProcessParameters(processToLoad).Result;
+
+ Settings.LastPowerUpSelectedRmlGuid = vm.IsSelectedRml ? vm.SelectedRml.Guid : null;
+ Settings.Save();
+ }
+ }
+ catch (Exception ex)
+ {
+ LogManager.Log(ex, "Error occurred while trying to get and upload the proper process parameters after power screen closed.");
+ }
+ });
+ });
+ }
+
#endregion
}
}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/PowerOffViewVM.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/PowerOffViewVM.cs
new file mode 100644
index 000000000..0d58b472f
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/ViewModels/PowerOffViewVM.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Tango.Core.Commands;
+using Tango.PPC.Common;
+
+namespace Tango.PPC.UI.ViewModels
+{
+ public class PowerOffViewVM : PPCViewModel
+ {
+ public RelayCommand AbortCommand { get; set; }
+
+ public PowerOffViewVM()
+ {
+ AbortCommand = new RelayCommand(AbortPowerOff);
+ }
+
+ public override void OnApplicationStarted()
+ {
+
+ }
+
+ private void AbortPowerOff()
+ {
+ NavigationManager.NavigateBack();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml
new file mode 100644
index 000000000..88981a9fa
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml
@@ -0,0 +1,18 @@
+<UserControl x:Class="Tango.PPC.UI.Views.InternalModuleView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:local="clr-namespace:Tango.PPC.UI.Views"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:controls="clr-namespace:Tango.SharedUI.Controls;assembly=Tango.SharedUI"
+ xmlns:vm="clr-namespace:Tango.PPC.UI.ViewModels"
+ xmlns:global="clr-namespace:Tango.PPC.UI"
+ mc:Ignorable="d"
+ d:DesignHeight="1280" d:DesignWidth="800" d:DataContext="{d:DesignInstance Type=vm:InternalModuleViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.InternalModuleViewVM}">
+ <Grid>
+ <controls:NavigationControl TransitionType="Zoom" KeepElementsAttached="True">
+ <local:PowerOffView/>
+ </controls:NavigationControl>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml.cs
new file mode 100644
index 000000000..f67d16dd9
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/InternalModuleView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.PPC.UI.Views
+{
+ /// <summary>
+ /// Interaction logic for InternalModuleView.xaml
+ /// </summary>
+ public partial class InternalModuleView : UserControl
+ {
+ public InternalModuleView()
+ {
+ InitializeComponent();
+ }
+ }
+}
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
index 9315f9f0e..b4f93fd0a 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/LayoutView.xaml
@@ -172,7 +172,7 @@
<Image Source="/Images/power-machine.png" Margin="30" />
<UniformGrid Grid.Column="1" Rows="2">
- <touch:TouchButton HorizontalAlignment="Left" VerticalAlignment="Center" Padding="50 20" Height="Auto" Style="{StaticResource TangoLinkButton}" FontSize="{StaticResource TangoTitleFontSize}" Foreground="{StaticResource TangoPrimaryBackgroundBrush}">Turn Off</touch:TouchButton>
+ <touch:TouchButton HorizontalAlignment="Left" VerticalAlignment="Center" Padding="50 20" Height="Auto" Style="{StaticResource TangoLinkButton}" FontSize="{StaticResource TangoTitleFontSize}" Foreground="{StaticResource TangoPrimaryBackgroundBrush}" Command="{Binding PowerOffCommand}" >Turn Off</touch:TouchButton>
<touch:TouchButton HorizontalAlignment="Left" VerticalAlignment="Center" Padding="50 20" Height="Auto" Style="{StaticResource TangoLinkButton}" FontSize="{StaticResource TangoTitleFontSize}" Foreground="{StaticResource TangoPrimaryBackgroundBrush}">Stand By</touch:TouchButton>
</UniformGrid>
</Grid>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml
index fba8a599d..beb09be0d 100644
--- a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/MachineUpdateView.xaml
@@ -194,8 +194,9 @@
<touch:TouchButton Padding="20" Width="300" Margin="0 0 0 130" CornerRadius="35" Command="{Binding CloseCommand}">CLOSE</touch:TouchButton>
</StackPanel>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Top" Margin="0 50 0 0">
- <touch:TouchIcon Icon="AlertOctagon" Foreground="{StaticResource TangoErrorBrush}" Width="70" Height="70" />
- <TextBlock VerticalAlignment="Center" Margin="0 10 0 0" Foreground="{StaticResource TangoErrorBrush}" FontSize="{StaticResource TangoTitleFontSize}">An error occurred while trying to update the machine.</TextBlock>
+ <touch:TouchIcon Icon="AlertOutline" Foreground="{StaticResource TangoErrorBrush}" Width="70" Height="70" />
+ <TextBlock HorizontalAlignment="Center" Margin="0 10 0 0" FontSize="{StaticResource TangoTitleFontSize}">Update Failed</TextBlock>
+ <TextBlock HorizontalAlignment="Center" Margin="0 5 0 0" Foreground="{StaticResource TangoErrorBrush}" TextAlignment="Center" Text="{Binding FailedError,FallbackValue='Unexpected error'}"></TextBlock>
</StackPanel>
</DockPanel>
</Grid>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml
new file mode 100644
index 000000000..9762ef621
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml
@@ -0,0 +1,20 @@
+<UserControl x:Class="Tango.PPC.UI.Views.PowerOffView"
+ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:vm="clr-namespace:Tango.PPC.UI.ViewModels"
+ xmlns:global="clr-namespace:Tango.PPC.UI"
+ xmlns:touch="clr-namespace:Tango.Touch.Controls;assembly=Tango.Touch"
+ xmlns:local="clr-namespace:Tango.PPC.UI.Views"
+ mc:Ignorable="d"
+ d:DesignHeight="1280" d:DesignWidth="800" Background="{StaticResource TangoPrimaryBackgroundBrush}" d:DataContext="{d:DesignInstance Type=vm:PowerOffViewVM, IsDesignTimeCreatable=False}" DataContext="{x:Static global:ViewModelLocator.PowerOffViewVM}">
+ <Grid>
+ <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
+ <touch:TouchGifAnimation Source="/Images/power_off.gif" EnableAnimation="{Binding IsVisible}" HorizontalAlignment="Center" />
+ <TextBlock HorizontalAlignment="Center" Margin="0 60 0 0" FontSize="{StaticResource TangoHeaderFontSize}">Machine is turning Off</TextBlock>
+ <TextBlock HorizontalAlignment="Center" Margin="0 20 0 0" FontSize="{StaticResource TangoTitleFontSize}" Foreground="{StaticResource TangoGrayTextBrush}">Do not unplug machine while turning off</TextBlock>
+ <touch:TouchButton Command="{Binding AbortCommand}" Style="{StaticResource TangoHollowButton}" Margin="0 100 0 0" HorizontalAlignment="Center" Width="200" Height="50">ABORT</touch:TouchButton>
+ </StackPanel>
+ </Grid>
+</UserControl>
diff --git a/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml.cs b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml.cs
new file mode 100644
index 000000000..ead34ae12
--- /dev/null
+++ b/Software/Visual_Studio/PPC/Tango.PPC.UI/Views/PowerOffView.xaml.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Tango.PPC.UI.Views
+{
+ /// <summary>
+ /// Interaction logic for LoadingView.xaml
+ /// </summary>
+ public partial class PowerOffView : UserControl
+ {
+ public PowerOffView()
+ {
+ InitializeComponent();
+ }
+ }
+}