aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.Common/ExtensionMethods/CommonDialogExtensions.cs
blob: 886ccdd1ea16da200a69c178d1e9d6c1f863c9cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
{
    /// <summary>
    /// Represents the default Machine Studio <see cref="IStudioApplicationManager">Application Manager</see>.
    /// </summary>
    /// <seealso cref="Tango.Core.ExtendedObject" />
    /// <seealso cref="Tango.MachineStudio.Common.StudioApplication.IStudioApplicationManager" />
    public class DefaultStudioApplicationManager : ExtendedObject, IStudioApplicationManager
    {
        private INavigationManager _navigationManager;
        private IStudioModuleLoader _moduleLoader;
        private INotificationProvider _notification;
        private List<Window> _openedWindows;
        private List<IStudioViewModel> _notified_view_models;
        private bool _isDialogShown;

        /// <summary>
        /// Occurs when the application is ready.
        /// </summary>
        public event EventHandler ApplicationReady;

        /// <summary>
        /// Occurs when the connected machine session has been lost and an automatic reconnection with the last machine is required.
        /// </summary>
        public event EventHandler ReconnectionRequired;

        /// <summary>
        /// Initializes a new instance of the <see cref="DefaultStudioApplicationManager" /> class.
        /// </summary>
        /// <param name="navigationManager">The navigation manager.</param>
        public DefaultStudioApplicationManager(INavigationManager navigationManager, IStudioModuleLoader moduleLoader, INotificationProvider notification)
        {
            _moduleLoader = moduleLoader;
            _navigationManager = navigationManager;
            _notification = notification;
            _openedWindows = new List<Window>();
            _notified_view_models = new List<IStudioViewModel>();

            Application.Current.MainWindow.ContentRendered += (_, __) =>
            {
                TangoIOC.Default.GetAllInstancesByBase<IStudioViewModel>().ToList().ForEach(x => x.OnApplicationStarted());
            };
        }

        /// <summary>
        /// Gets a value indicating whether Machine Studio is shutting down.
        /// </summary>
        public bool IsShuttingDown { get; private set; }

        /// <summary>
        /// Occurs when the connected machine property has changed.
        /// </summary>
        public event EventHandler<IExternalBridgeClient> ConnectedMachineChanged;

        /// <summary>
        /// Gets or sets the machine.
        /// </summary>
        public Machine Machine { get; private set; }

        private IExternalBridgeClient _connectedMachine;
        /// <summary>
        /// Gets or sets the currently connected machine if any.
        /// </summary>
        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);
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether the <see cref="P:Tango.MachineStudio.Common.StudioApplication.IStudioApplicationManager.ConnectedMachine" /> is valid and connected through TCP/IP.
        /// </summary>
        public bool IsMachineConnectedViaTCP
        {
            get { return IsMachineConnected && ConnectedMachine is ExternalBridgeTcpClient; }
        }

        /// <summary>
        /// Handles the <see cref="ConnectedMachine"/> state changed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The e.</param>
        private void ConnectedMachine_StateChanged(object sender, Transport.TransportComponentState e)
        {
            if (e == Transport.TransportComponentState.Disconnected || e == Transport.TransportComponentState.Failed)
            {
                bool reconnect = ConnectedMachine is IExternalBridgeSecureClient;

                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 = reconnect,
                        };

                        InvokeUI(() =>
                        {
                            _notification.ShowModalDialog<ConnectionLostViewVM, ConnectionLostView>(vm, (x) =>
                            {
                                _isDialogShown = false;
                                ReconnectionRequired?.Invoke(this, new EventArgs());
                            }, () =>
                            {
                                _isDialogShown = false;
                            });
                        });
                    }
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether the <see cref="P:Tango.MachineStudio.Common.StudioApplication.IStudioApplicationManager.ConnectedMachine" /> is valid.
        /// </summary>
        public bool IsMachineConnected
        {
            get { return ConnectedMachine != null; }
        }

        /// <summary>
        /// Gets the machine studio application version.
        /// </summary>
        public Version Version
        {
            get
            {
                return AssemblyHelper.GetCurrentAssemblyVersion();
            }
        }

        /// <summary>
        /// Shutdown the application.
        /// </summary>
        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<IStudioViewModel>())
                        {
                            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<IStudioViewModel>())
                        {
                            vm.OnShuttingDown();
                        }


                        var settings = SettingsManager.Default.GetOrCreate<MachineStudioSettings>();
                        settings.LastBounds = r;
                        settings.StudioModulesBounds.Clear();


                        foreach (var window in _openedWindows.OfType<Windows.ModuleWindow>())
                        {
                            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<MainViewVM>();

                        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<IEventLogger>();
                        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.");
            }
        }

        /// <summary>
        /// Notify the application manager about an external opened window.
        /// When application exists. All registered windows will be closed.
        /// </summary>
        /// <param name="window">The window.</param>
        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);
        }

        /// <summary>
        /// Gets the core libraries version.
        /// </summary>
        public Version CoreVersion
        {
            get
            {
                return typeof(ExtendedObject).Assembly.GetName().Version;
            }
        }

        /// <summary>
        /// Gets the build date.
        /// </summary>
        public string BuildDate
        {
            get
            {
                return AssemblyHelper.GetCurrentAssemblyBuildDate().ToShortDateString();
            }
        }

        /// <summary>
        /// Gets the change log.
        /// </summary>
        public string ChangeLog
        {
            get
            {
                return EmbeddedResourceHelper.GetEmbeddedResourceText("Tango.MachineStudio.UI.ChangeLog.txt");
            }
        }

        /// <summary>
        /// Raises the application ready event.
        /// </summary>
        public void NotifyApplicationReady()
        {
            TangoIOC.Default.GetAllInstancesByBase<IStudioViewModel>().ToList().ForEach(x =>
            {
                if (!_notified_view_models.Contains(x))
                {
                    x.OnApplicationReady();
                    _notified_view_models.Add(x);
                }
            });

            ApplicationReady?.Invoke(this, new EventArgs());
        }

        /// <summary>
        /// Sets the connected machine.
        /// </summary>
        /// <param name="connectedMachine">The connected machine.</param>
        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<MachineStudioSettings>();
                ConnectedMachine.JobUploadStrategy = settings.JobUploadStrategy;
            }
            else
            {
                Machine = null;
                ConnectedMachine = null;
            }
        }
    }
}