using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Tango.Core.Helpers; using Tango.MachineStudio.Common.StudioApplication; using Tango.MachineStudio.Common.Navigation; using System.Reflection; using System.Collections; using Tango.Core; using Tango.Logging; using Tango.MachineStudio.Common.Modules; using Tango.MachineStudio.Common; using Tango.Settings; using System.Windows; using Tango.Integration.ExternalBridge; using Tango.MachineStudio.Common.EventLogging; using Tango.BL.Enumerations; using Tango.Core.DI; using Tango.BL.Entities; using Tango.BL; using Tango.MachineStudio.UI.ViewModels; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.UI.Views; using Tango.Integration.Operation; using Tango.MachineStudio.UI.Windows; using Tango.BL.Builders; namespace Tango.MachineStudio.UI.StudioApplication { /// /// Represents the default Machine Studio Application Manager. /// /// /// public class DefaultStudioApplicationManager : ExtendedObject, IStudioApplicationManager { private INavigationManager _navigationManager; private IStudioModuleLoader _moduleLoader; private INotificationProvider _notification; private List _openedWindows; private List _notified_view_models; private bool _isDialogShown; /// /// Occurs when the application is ready. /// public event EventHandler ApplicationReady; /// /// Occurs when the connected machine session has been lost and an automatic reconnection with the last machine is required. /// public event EventHandler ReconnectionRequired; /// /// Initializes a new instance of the class. /// /// The navigation manager. public DefaultStudioApplicationManager(INavigationManager navigationManager, IStudioModuleLoader moduleLoader, INotificationProvider notification) { _moduleLoader = moduleLoader; _navigationManager = navigationManager; _notification = notification; _openedWindows = new List(); _notified_view_models = new List(); Application.Current.MainWindow.ContentRendered += (_, __) => { TangoIOC.Default.GetAllInstancesByBase().ToList().ForEach(x => x.OnApplicationStarted()); }; } /// /// Gets a value indicating whether Machine Studio is shutting down. /// public bool IsShuttingDown { get; private set; } /// /// Occurs when the connected machine property has changed. /// public event EventHandler ConnectedMachineChanged; /// /// Gets or sets the machine. /// public Machine Machine { get; private set; } private IExternalBridgeClient _connectedMachine; /// /// Gets or sets the currently connected machine if any. /// public IExternalBridgeClient ConnectedMachine { get { return _connectedMachine; } private set { if (_connectedMachine != value) { _connectedMachine = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(IsMachineConnected)); RaisePropertyChanged(nameof(IsMachineConnectedViaTCP)); if (_connectedMachine != null) { _connectedMachine.StateChanged -= ConnectedMachine_StateChanged; _connectedMachine.StateChanged += ConnectedMachine_StateChanged; } ConnectedMachineChanged?.Invoke(this, _connectedMachine); } } } /// /// Gets a value indicating whether the is valid and connected through TCP/IP. /// public bool IsMachineConnectedViaTCP { get { return IsMachineConnected && ConnectedMachine is ExternalBridgeTcpClient; } } /// /// Handles the state changed event. /// /// The sender. /// The e. private void ConnectedMachine_StateChanged(object sender, Transport.TransportComponentState e) { if (e == Transport.TransportComponentState.Disconnected || e == Transport.TransportComponentState.Failed) { ConnectedMachine = null; if (e == Transport.TransportComponentState.Failed) { String failed_reason = (sender as IMachineOperator).FailedStateException.Message; if (!_isDialogShown) { _isDialogShown = true; ConnectionLostViewVM vm = new ConnectionLostViewVM() { Exception = failed_reason, AutoReconnect = true, }; InvokeUI(() => { _notification.ShowModalDialog(vm, (x) => { _isDialogShown = false; ReconnectionRequired?.Invoke(this, new EventArgs()); }, () => { _isDialogShown = false; }); }); } } } } /// /// Gets a value indicating whether the is valid. /// public bool IsMachineConnected { get { return ConnectedMachine != null; } } /// /// Gets the machine studio application version. /// public Version Version { get { return AssemblyHelper.GetCurrentAssemblyVersion(); } } /// /// Shutdown the application. /// public async void ShutDown() { if (IsShuttingDown) return; IsShuttingDown = true; try { Rect r = new Rect( MainWindow.Instance.Left, MainWindow.Instance.Top, MainWindow.Instance.Width, MainWindow.Instance.Height); await Task.Factory.StartNew(async () => { try { //Do Shutdown Procedures... foreach (var vm in TangoIOC.Default.GetAllInstancesByBase()) { try { var result = await vm.OnShutdownRequest(); if (!result) { IsShuttingDown = false; return; } } catch (Exception ex) { LogManager.Log(ex, "Error on shutdown request with " + vm.GetType().Name); } } foreach (var vm in TangoIOC.Default.GetAllInstancesByBase()) { vm.OnShuttingDown(); } var settings = SettingsManager.Default.GetOrCreate(); settings.LastBounds = r; settings.StudioModulesBounds.Clear(); foreach (var window in _openedWindows.OfType()) { window.Invoke(() => { var context = window.ModuleContext; if (context != null) { settings.StudioModulesBounds.Add(new MachineStudioSettings.StudioModuleBounds() { Bounds = window.RestoreBounds, State = window.WindowState, Name = context.Module.Name, }); } }); } var mainViewVM = TangoIOC.Default.GetInstance(); settings.LastMainModuleName = mainViewVM.CurrentModule != null ? mainViewVM.CurrentModule.Name : null; try { SettingsManager.Default.Save(); } catch (Exception ex) { LogManager.Log(ex, "Error saving settings."); } await _navigationManager.NavigateTo(NavigationView.ShutdownView); Thread.Sleep(1500); foreach (var window in _openedWindows) { ThreadsHelper.InvokeUI(() => { window.Close(); }); } try { if (ConnectedMachine != null) { ConnectedMachine.Disconnect().Wait(); } } catch (Exception ex) { LogManager.Log(ex, "Error disconnecting from machine."); } var eventLogger = TangoIOC.Default.GetInstance(); if (eventLogger != null) { //eventLogger.Log(EventTypes.APPLICATION_TERMINATED, "Application Terminated!"); eventLogger.FlushAll(); } Thread.Sleep(1500); Environment.Exit(0); } catch { Environment.Exit(0); } }); } catch (Exception ex) { IsShuttingDown = false; LogManager.Log(ex, "An error occurred while shutting down machine studio."); } } /// /// Notify the application manager about an external opened window. /// When application exists. All registered windows will be closed. /// /// The window. public void RegisterOpenedWindow(Window window) { _openedWindows.Add(window); window.Closed += (x, y) => { _openedWindows.Remove(window); }; } public bool IsModuleInNewWindow(IStudioModule module) { return _openedWindows.Exists(x => (x as ModuleWindow).ModuleContext.Module == module); } /// /// Gets the core libraries version. /// public Version CoreVersion { get { return typeof(ExtendedObject).Assembly.GetName().Version; } } /// /// Gets the build date. /// public string BuildDate { get { return AssemblyHelper.GetCurrentAssemblyBuildDate().ToShortDateString(); } } /// /// Gets the change log. /// public string ChangeLog { get { return EmbeddedResourceHelper.GetEmbeddedResourceText("Tango.MachineStudio.UI.ChangeLog.txt"); } } /// /// Raises the application ready event. /// public void NotifyApplicationReady() { TangoIOC.Default.GetAllInstancesByBase().ToList().ForEach(x => { if (!_notified_view_models.Contains(x)) { x.OnApplicationReady(); _notified_view_models.Add(x); } }); ApplicationReady?.Invoke(this, new EventArgs()); } /// /// Sets the connected machine. /// /// The connected machine. public void SetConnectedMachine(IExternalBridgeClient connectedMachine) { if (connectedMachine != null) { Machine = ObservablesStaticCollections.Instance.Machines.SingleOrDefault(x => x.SerialNumber == connectedMachine.SerialNumber); if (Machine == null) { throw new NullReferenceException($"The specified machine '{connectedMachine.SerialNumber}' could not be found on the database."); } connectedMachine.SetMachine(Machine); ConnectedMachine = connectedMachine; var settings = SettingsManager.Default.GetOrCreate(); ConnectedMachine.JobUploadStrategy = settings.JobUploadStrategy; } else { Machine = null; ConnectedMachine = null; } } } }