aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage
diff options
context:
space:
mode:
authorRoy Ben Shabat <Roy.mail.net@gmail.com>2020-07-28 19:20:58 +0300
committerRoy Ben Shabat <Roy.mail.net@gmail.com>2020-07-28 19:20:58 +0300
commit1b6f1e483a866bbd13cad7343e95dfebf0f08a21 (patch)
tree1cae743f7466867d99d445b6754d3157232c8846 /Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage
parent0281068b4adb3f94af50f2c758d3e0fa0fe5f191 (diff)
downloadTango-1b6f1e483a866bbd13cad7343e95dfebf0f08a21.tar.gz
Tango-1b6f1e483a866bbd13cad7343e95dfebf0f08a21.zip
Fixed issue with Monitor Widget Decimal Places.
Diffstat (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Storage')
0 files changed, 0 insertions, 0 deletions
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Tango.BL;
using Tango.BL.Entities;
using Tango.Core.Commands;
using Tango.Core.DI;
using Tango.Integration.ExternalBridge;
using Tango.Logging;
using Tango.MachineStudio.Common;
using Tango.MachineStudio.Common.Authentication;
using Tango.MachineStudio.Common.Diagnostics;
using Tango.MachineStudio.Common.EventLogging;
using Tango.MachineStudio.Common.Html;
using Tango.MachineStudio.Common.Messages;
using Tango.MachineStudio.Common.Modules;
using Tango.MachineStudio.Common.Navigation;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.Common.Speech;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.MachineStudio.Common.Update;
using Tango.MachineStudio.UI.StudioApplication;
using Tango.MachineStudio.UI.SupervisingController;
using Tango.MachineStudio.UI.TFS;
using Tango.MachineStudio.UI.Views;
using Tango.MachineStudio.UI.Windows;
using Tango.PMR.Stubs;
using Tango.Settings;
using Tango.SharedUI;
using Tango.SharedUI.Controls;
using Tango.SharedUI.Helpers;
using Tango.Transport;
using Tango.Transport.Adapters;

namespace Tango.MachineStudio.UI.ViewModels
{
    /// <summary>
    /// Represents the Machine Studio main view, view model.
    /// </summary>
    /// <seealso cref="Tango.SharedUI.ViewModel{Tango.MachineStudio.UI.SupervisingController.IMainView}" />
    public class MainViewVM : ViewModel
    {
        private IStudioModule _currentModule;
        private INavigationManager _navigation;
        private bool _isDisconnecting;
        private Thread _updateCheckThread;
        private IEventLogger _eventLogger;
        private IHtmlPresenter _htmlPresenter;
        private MachineStudioSettings _settings;

        /// <summary>
        /// Gets or sets the current loaded module.
        /// </summary>
        public IStudioModule CurrentModule
        {
            get { return _currentModule; }
            set { _currentModule = value; RaisePropertyChangedAuto(); }
        }

        private bool _isModuleLoaded;
        /// <summary>
        /// Gets or sets a value indicating whether any module is loaded at the moment.
        /// </summary>
        public bool IsModuleLoaded
        {
            get { return _isModuleLoaded; }
            set { _isModuleLoaded = value; RaisePropertyChangedAuto(); }
        }

        private bool _isMenuOpened;
        /// <summary>
        /// Gets or sets a value indicating whether the side menu is opened.
        /// </summary>
        public bool IsMenuOpened
        {
            get { return _isMenuOpened; }
            set { _isMenuOpened = value; RaisePropertyChangedAuto(); }
        }

        private bool _isMachineErrorsOpened;
        /// <summary>
        /// Gets or sets a value indicating whether to display the machine errors.
        /// </summary>
        public bool IsMachineErrorsOpened
        {
            get { return _isMachineErrorsOpened; }
            set { _isMachineErrorsOpened = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets or sets the start module command.
        /// </summary>
        public RelayCommand<IStudioModule> StartModuleCommand { get; set; }

        /// <summary>
        /// Gets or sets the open module in window command.
        /// </summary>
        public RelayCommand<IStudioModule> OpenModuleInWindowCommand { get; set; }

        /// <summary>
        /// Gets or sets the home command.
        /// </summary>
        public RelayCommand HomeCommand { get; set; }

        /// <summary>
        /// Gets or sets the connect command.
        /// </summary>
        public RelayCommand ConnectCommand { get; set; }

        /// <summary>
        /// Gets or sets the disconnect command.
        /// </summary>
        public RelayCommand DisconnectCommand { get; set; }

        /// <summary>
        /// Gets or sets the sign-out command.
        /// </summary>
        public RelayCommand SignoutCommand { get; set; }

        /// <summary>
        /// Gets or sets the exit command.
        /// </summary>
        public RelayCommand ExitCommand { get; set; }

        /// <summary>
        /// Gets or sets the update center command.
        /// </summary>
        public RelayCommand UpdateCenterCommand { get; set; }

        /// <summary>
        /// Gets or sets the toggle speech command.
        /// </summary>
        public RelayCommand ToggleSpeechCommand { get; set; }

        /// <summary>
        /// Gets or sets the display HTML command.
        /// </summary>
        public RelayCommand<MachinesEvent> ResolveMachineEventCommand { get; set; }

        /// <summary>
        /// Gets or sets the report issue command.
        /// </summary>
        public RelayCommand ReportIssueCommand { get; set; }

        /// <summary>
        /// Gets or sets the open resolved bugs.
        /// </summary>
        public RelayCommand OpenResolvedBugsCommand { get; set; }

        /// <summary>
        /// Gets or sets the open developer console command.
        /// </summary>
        public RelayCommand OpenDeveloperConsoleCommand { get; set; }

        /// <summary>
        /// Gets or sets the about command.
        /// </summary>
        public RelayCommand AboutCommand { get; set; }

        private IAuthenticationProvider _authenticationProvider;
        /// <summary>
        /// Gets or sets the authentication provider.
        /// </summary>
        public IAuthenticationProvider AuthenticationProvider
        {
            get { return _authenticationProvider; }
            set { _authenticationProvider = value; RaisePropertyChangedAuto(); }
        }

        private IStudioModuleLoader _studioModuleLoader;
        /// <summary>
        /// Gets or sets the studio module loader.
        /// </summary>
        public IStudioModuleLoader StudioModuleLoader
        {
            get { return _studioModuleLoader; }
            set { _studioModuleLoader = value; RaisePropertyChangedAuto(); }
        }

        private INotificationProvider _notificationProvider;
        /// <summary>
        /// Gets or sets the notification provider.
        /// </summary>
        public INotificationProvider NotificationProvider
        {
            get { return _notificationProvider; }
            set { _notificationProvider = value; RaisePropertyChangedAuto(); }
        }

        private IStudioApplicationManager _applicationManager;
        /// <summary>
        /// Gets or sets the application manager.
        /// </summary>
        public IStudioApplicationManager ApplicationManager
        {
            get { return _applicationManager; }
            set { _applicationManager = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets or sets the TFS client.
        /// </summary>
        public TeamFoundationServiceExtendedClient TFSClient { get; set; }

        /// <summary>
        /// Gets or sets the speech provider.
        /// </summary>
        public ISpeechProvider SpeechProvider { get; set; }

        private bool _isUpdateAvailable;
        /// <summary>
        /// Gets or sets a value indicating whether a new version update is available.
        /// </summary>
        public bool IsUpdateAvailable
        {
            get { return _isUpdateAvailable; }
            set { _isUpdateAvailable = value; RaisePropertyChangedAuto(); }
        }

        private String _latestVersion;
        /// <summary>
        /// Gets or sets the latest version.
        /// </summary>
        public String LatestVersion
        {
            get { return _latestVersion; }
            set { _latestVersion = value; RaisePropertyChangedAuto(); }
        }

        private bool _disableCheckForUpdates;
        /// <summary>
        /// Gets or sets a value indicating whether [disable check for updates].
        /// </summary>
        public bool DisableCheckForUpdates
        {
            get { return _disableCheckForUpdates; }
            set { _disableCheckForUpdates = value; RaisePropertyChangedAuto(); }
        }

        private IDiagnosticsFrameProvider _diagnosticsFrameProvider;
        /// <summary>
        /// Gets or sets the diagnostics frame provider.
        /// </summary>
        public IDiagnosticsFrameProvider DiagnosticsFrameProvider
        {
            get { return _diagnosticsFrameProvider; }
            set { _diagnosticsFrameProvider = value; RaisePropertyChangedAuto(); }
        }


        /// <summary>
        /// Initializes a new instance of the <see cref="MainViewVM"/> class.
        /// </summary>
        /// <param name="view">The view.</param>
        /// <param name="authenticationProvider">The authentication provider.</param>
        /// <param name="studioModuleLoader">The studio module loader.</param>
        /// <param name="notificationProvider">The notification provider.</param>
        /// <param name="applicationManager">The application manager.</param>
        /// <param name="navigationManager">The navigation manager.</param>
        public MainViewVM(
            IAuthenticationProvider authenticationProvider,
            IStudioModuleLoader studioModuleLoader,
            INotificationProvider notificationProvider,
            IStudioApplicationManager applicationManager,
            INavigationManager navigationManager,
            IEventLogger eventLogger,
            IDiagnosticsFrameProvider frameProvider,
            ISpeechProvider speechProvider,
            IHtmlPresenter htmlPresenter, TeamFoundationServiceExtendedClient tfs) : base()
        {
            TFSClient = tfs;
            _eventLogger = eventLogger;
            _navigation = navigationManager;
            AuthenticationProvider = authenticationProvider;
            StudioModuleLoader = studioModuleLoader;
            NotificationProvider = notificationProvider;
            ApplicationManager = applicationManager;
            DiagnosticsFrameProvider = frameProvider;
            SpeechProvider = speechProvider;
            _htmlPresenter = htmlPresenter;

            _settings = SettingsManager.Default.GetOrCreate<MachineStudioSettings>();

            StartModuleCommand = new RelayCommand<IStudioModule>(StartModule);

            HomeCommand = new RelayCommand(Home);
            ConnectCommand = new RelayCommand(ConnectToMachine);
            SignoutCommand = new RelayCommand(SignOut);
            DisconnectCommand = new RelayCommand(DisconnectFromMachine, (x) => ApplicationManager.IsMachineConnected && !_isDisconnecting);
            OpenModuleInWindowCommand = new RelayCommand<IStudioModule>(OpenModuleInWindow);
            ExitCommand = new RelayCommand(ExitApplication);
            UpdateCenterCommand = new RelayCommand(NavigateToUpdateCenter);

            _updateCheckThread = new Thread(UpdateCheckThreadMethod);
            _updateCheckThread.IsBackground = true;
            _updateCheckThread.Start();

            ApplicationManager.ConnectedMachineChanged += (sender, machine) =>
            {
                if (machine != null)
                {
                    machine.MachineEventsStateProvider.NewEvents -= MachineEventsStateProvider_NewEvents;
                    machine.MachineEventsStateProvider.NewEvents += MachineEventsStateProvider_NewEvents;

                    machine.MachineEventsStateProvider.EventsResolved -= MachineEventsStateProvider_EventsResolved;
                    machine.MachineEventsStateProvider.EventsResolved += MachineEventsStateProvider_EventsResolved;
                }
            };

            ToggleSpeechCommand = new RelayCommand(() => { SpeechProvider.Mute = !SpeechProvider.Mute; });

            ResolveMachineEventCommand = new RelayCommand<MachinesEvent>(ResolveMachineEvent);

            ReportIssueCommand = new RelayCommand(ReportIssue);
            OpenResolvedBugsCommand = new RelayCommand(OpenResolvedBugs);
            OpenDeveloperConsoleCommand = new RelayCommand(OpenDeveloperConsole);

            TangoMessenger.Default.Register<Messages.ForcedUpdateMessage>((x) => DisableCheckForUpdates = true);

            AboutCommand = new RelayCommand(ShowAboutDialog);
        }

        private void MachineEventsStateProvider_EventsResolved(object sender, IEnumerable<MachinesEvent> e)
        {
            if (ApplicationManager.ConnectedMachine.MachineEventsStateProvider.Events.Count == 0)
            {
                IsMachineErrorsOpened = false;
            }
        }

        private void MachineEventsStateProvider_NewEvents(object sender, IEnumerable<MachinesEvent> e)
        {
            IsMachineErrorsOpened = true;
        }

        private void UpdateCheckThreadMethod()
        {
            while (!DisableCheckForUpdates)
            {
                Thread.Sleep(TimeSpan.FromMinutes(0.2));

                try
                {
                    if (_authenticationProvider.CurrentUser != null)
                    {
                        var service = UpdateServiceHelper.GetUpdateServiceChannel();
                        var client = service.CreateChannel();

                        CheckForUpdatesResponse response = client.CheckForUpdates(new CheckForUpdatesRequest()
                        {
                            Email = _authenticationProvider.CurrentUser.Email,
                            Password = _authenticationProvider.CurrentUser.Password,
                            Version = _applicationManager.Version.ToString(),
                        });

                        IsUpdateAvailable = response.IsUpdateAvailable;
                        LatestVersion = response.Version;
                    }
                }
                catch (Exception ex)
                {
                    LogManager.Log(ex, "Error in version update periodic check...");
                }

                Thread.Sleep(TimeSpan.FromMinutes(4));
            }
        }

        /// <summary>
        /// Disconnected from the current connected machine.
        /// </summary>
        private async void DisconnectFromMachine()
        {
            using (_notificationProvider.PushTaskItem("Disconnecting from machine..."))
            {
                try
                {
                    _isDisconnecting = true;
                    InvalidateRelayCommands();
                    String serial = ApplicationManager.ConnectedMachine.SerialNumber;
                    await ApplicationManager.ConnectedMachine.Disconnect();
                    ApplicationManager.SetConnectedMachine(null);
                    _eventLogger.Log("Disconnected from machine " + serial);

                    PostMessage(new MachineConnectionChangedMessage() { Machine = null });
                }
                catch (Exception ex)
                {
                    _eventLogger.Log(ex, "Error disconnecting from machine.");
                    LogManager.Log(ex, "Could not disconnect from machine.");
                }
                finally
                {
                    _isDisconnecting = false;
                    InvalidateRelayCommands();
                }
            }
        }

        /// <summary>
        /// Signs-out the current logged-in user.
        /// </summary>
        private void SignOut()
        {
            _authenticationProvider.Logout();
            _navigation.NavigateTo(NavigationView.LoginView);
            CurrentModule = null;
            IsMenuOpened = false;
        }

        /// <summary>
        /// Opens the machine connection dialog to allow the user to scan and connect to remote machines view USB/TCP.
        /// </summary>
        private void ConnectToMachine()
        {
            if (ApplicationManager.ConnectedMachine == null)
            {
                _notificationProvider.ShowModalDialog<MachineConnectionViewVM>(async (x) =>
                {
                    if (x.SelectedMachine != null)
                    {
                        if (ApplicationManager.IsMachineConnected)
                        {
                            using (_notificationProvider.PushTaskItem("Disconnecting..."))
                            {
                                await ApplicationManager.ConnectedMachine.Disconnect();
                                await Task.Delay(1000);
                            }
                        }

                        if (x.SelectedMachine.RequiresAuthentication)
                        {
                            _notificationProvider.ShowModalDialog<MachineLoginViewVM>(async (login) =>
                            {
                                using (NotificationProvider.PushTaskItem("Connecting to machine " + x.SelectedMachine.ToString() + "..."))
                                {
                                    try
                                    {
                                        if (x.SelectedMachine.EnableDiagnostics)
                                        {
                                            x.SelectedMachine.EnableEmbeddedDebugging = true;
                                        }

                                        await x.SelectedMachine.As<IExternalBridgeSecureClient>().Connect(new PMR.Integration.ExternalBridgeLoginRequest()
                                        {
                                            AppID = "Machine Studio",
                                            HostName = Environment.MachineName,
                                            Password = login.Password,
                                            UserGuid = AuthenticationProvider.CurrentUser.Guid,
                                            Intent = PMR.Integration.ExternalBridgeLoginIntent.Override,
                                        });

                                        ApplicationManager.SetConnectedMachine(x.SelectedMachine);
                                        (x.SelectedMachine as IExternalBridgeSecureClient).SessionClosed += (_, __) =>
                                        {
                                            InvokeUI(() =>
                                            {
                                                _notificationProvider.ShowError("The remote machine has closed the current session. Machine disconnected.");
                                                ApplicationManager.SetConnectedMachine(null);
                                            });
                                        };
                                        PostMessage(new MachineConnectionChangedMessage() { Machine = x.SelectedMachine });
                                        _eventLogger.Log(String.Format("Successfully connected to machine {0} via TCP", x.SelectedMachine.SerialNumber));

                                    }
                                    catch (ResponseErrorException ex)
                                    {
                                        LogManager.Log(ex);
                                        _eventLogger.Log(ex, "Error connecting to machine " + x.SelectedMachine.SerialNumber);
                                        _notificationProvider.ShowError("Could not connect to the selected machine." + Environment.NewLine + ex.Container.ErrorMessage);
                                    }
                                    catch (Exception ex)
                                    {
                                        LogManager.Log(ex);
                                        _eventLogger.Log(ex, "Error connecting to machine " + x.SelectedMachine.SerialNumber);
                                        _notificationProvider.ShowError("Could not connect to the selected machine." + Environment.NewLine + ex.Message);
                                    }

                                    InvalidateRelayCommands();
                                }
                            });
                        }
                        else
                        {
                            _notificationProvider.ShowModalDialog<MachineSerialViewVM>(async (vm) =>
                            {
                                if (vm.SelectedMachine != null)
                                {
                                    using (NotificationProvider.PushTaskItem("Connecting to " + x.SelectedMachine.ToString() + "..."))
                                    {
                                        try
                                        {
                                            if (x.SelectedMachine.EnableDiagnostics)
                                            {
                                                x.SelectedMachine.EnableEmbeddedDebugging = true;
                                            }

                                            await x.SelectedMachine.Connect();
                                            x.SelectedMachine.SerialNumber = vm.SelectedMachine.SerialNumber;
                                            ApplicationManager.SetConnectedMachine(x.SelectedMachine);

                                            PostMessage(new MachineConnectionChangedMessage() { Machine = x.SelectedMachine });
                                            _eventLogger.Log(String.Format("Successfully connected to machine {0} via USB", x.SelectedMachine.SerialNumber));
                                            _settings.LastVirtualMachineSerialNumber = vm.SelectedMachine.SerialNumber;
                                            _settings.Save();
                                        }
                                        catch (Exception ex)
                                        {
                                            LogManager.Log(ex);

                                            if (x.SelectedMachine != null)
                                            {
                                                _eventLogger.Log(ex, "Error connecting to machine " + x.SelectedMachine.SerialNumber);
                                            }

                                            _notificationProvider.ShowError("Could not connect to the selected machine." + Environment.NewLine + ex.Message);

                                        }

                                        InvalidateRelayCommands();
                                    }
                                }
                            });
                        }

                        InvalidateRelayCommands();
                    }

                    InvalidateRelayCommands();
                });
            }
            else
            {
                _notificationProvider.ShowModalDialog<ConnectedMachineViewVM>(async (x) =>
                {
                    if (x.Result == ConnectedMachineViewVM.ConnectedMachineVMResult.Disconnect)
                    {
                        DisconnectFromMachine();
                    }
                    else if (x.Result == ConnectedMachineViewVM.ConnectedMachineVMResult.UploadHardwareConfig)
                    {
                        if (NotificationProvider.ShowQuestion("This will reset the machine hardware configuration to the database configuration. Are you sure?"))
                        {
                            using (NotificationProvider.PushTaskItem("Uploading hardware configuration..."))
                            {
                                try
                                {
                                    using (ObservablesContext db = ObservablesContext.CreateDefault())
                                    {
                                        var config = db.Adapter.GetConfiguration(s => s.Guid == ApplicationManager.Machine.ConfigurationGuid);
                                        var hw = db.Adapter.GetHardwareVersionByMachine(ApplicationManager.Machine.Guid);

                                        await ApplicationManager.ConnectedMachine.UploadHardwareConfiguration(hw, config);
                                    }
                                    NotificationProvider.ShowInfo("Hardware configuration uploaded successfully.");
                                }
                                catch (Exception ex)
                                {
                                    LogManager.Log(ex, "Error uploading hardware configuration.");
                                    NotificationProvider.ShowError("Error uploading hardware configuration." + Environment.NewLine + ex.Message);
                                }
                            }
                        }
                    }
                    else if (x.Result == ConnectedMachineViewVM.ConnectedMachineVMResult.Reset)
                    {
                        if (NotificationProvider.ShowQuestion("This will reset the embedded device. Are you sure?"))
                        {
                            using (NotificationProvider.PushTaskItem("Resetting the embedded device..."))
                            {
                                try
                                {
                                    await ApplicationManager.ConnectedMachine.Reset();
                                    NotificationProvider.ShowInfo("Embedded device has been restarted.");
                                }
                                catch (Exception ex)
                                {
                                    LogManager.Log(ex, "Error resetting embedded device.");
                                    NotificationProvider.ShowError("Error resetting embedded device." + Environment.NewLine + ex.Message);
                                }
                            }
                        }
                    }
                    else if (x.Result == ConnectedMachineViewVM.ConnectedMachineVMResult.TurnOffHeaters)
                    {
                        if (NotificationProvider.ShowQuestion("This will reset the process parameters. Are you sure?"))
                        {
                            using (NotificationProvider.PushTaskItem("Resetting process parameters..."))
                            {
                                try
                                {
                                    await ApplicationManager.ConnectedMachine.UploadProcessParameters(new ProcessParametersTable());
                                    NotificationProvider.ShowInfo("Heaters are turned off.");
                                }
                                catch (Exception ex)
                                {
                                    LogManager.Log(ex, "Error resetting process parameters.");
                                    NotificationProvider.ShowError("Error resetting process parameters." + Environment.NewLine + ex.Message);
                                }
                            }
                        }
                    }
                });
            }

            InvalidateRelayCommands();
        }

        /// <summary>
        /// Navigates to the home screen.
        /// </summary>
        private void Home()
        {
            StartModule(null);
        }

        /// <summary>
        /// Starts the specified module.
        /// </summary>
        /// <param name="module">The module.</param>
        internal void StartModule(IStudioModule module)
        {
            IsMenuOpened = false;

            if (module != null)
            {
                LogManager.Log(String.Format("Starting module '{0}'...", module.Name));

                if (!(MainView.Self as MainView).NavigationControl.Elements.ToList().Exists(x => x.GetType() == module.MainViewType))
                {
                    LogManager.Log("Module was not initialized. Initializing...");

                    FrameworkElement view = Activator.CreateInstance(module.MainViewType) as FrameworkElement;
                    NavigationControl.SetNavigationName(view, module.Name);
                    (MainView.Self as MainView).NavigationControl.Elements.Add(view);
                }
            }

            foreach (var m in StudioModuleLoader.AllModules.Where(x => x != module && !x.InNewWindow))
            {
                m.IsLoaded = false;
            }

            if (module != null)
            {
                CurrentModule = module;
                CurrentModule.IsLoaded = true;
                IsModuleLoaded = true;

                LogManager.Log(String.Format("Navigating to module '{0}'...", module.Name));
                (MainView.Self as MainView).NavigationControl.NavigateTo(module.Name);
            }
            else
            {
                IsModuleLoaded = false;
                LogManager.Log(String.Format("Navigating to Home..."));
                (MainView.Self as MainView).NavigationControl.NavigateTo("Home");
            }
        }

        /// <summary>
        /// Opens the module in a new window.
        /// </summary>
        /// <param name="module">The module.</param>
        private void OpenModuleInWindow(IStudioModule module)
        {
            if (module == null) return;

            try
            {
                module.InNewWindow = true;

                StartModule(null);

                LogManager.Log(String.Format("Starting module '{0}' in new window...", module.Name));

                if (!(MainView.Self as MainView).NavigationControl.Elements.ToList().Exists(x => x.GetType() == module.MainViewType))
                {
                    LogManager.Log("Module was not initialized. Initializing...");
                    FrameworkElement v = Activator.CreateInstance(module.MainViewType) as FrameworkElement;
                    NavigationControl.SetNavigationName(v, module.Name);
                    (MainView.Self as MainView).NavigationControl.Elements.Add(v);
                }

                LogManager.Log("Detaching module view...");
                var view = (MainView.Self as MainView).NavigationControl.GetAndDetach(module.Name);

                ModuleWindowVM vm = new ModuleWindowVM(module);
                ModuleWindow window = new ModuleWindow(this, vm, view);

                window.Closing += (x, y) =>
                {
                    LogManager.Log(String.Format("Closing module '{0}' on new window...", module.Name));

                    window.grid.Children.Remove(view);
                    module.InNewWindow = false;
                };

                window.Owner = MainWindow.Instance;

                LogManager.Log("Opening new window...");
                window.Show();

                (_applicationManager as DefaultStudioApplicationManager).RegisterOpenedWindow(window);
            }
            catch (Exception ex)
            {
                LogManager.Log(ex, "Error popping out module " + module.Name);
                _notificationProvider.ShowError("Error popping out module " + module.Name);
            }
        }

        /// <summary>
        /// Navigates to update center.
        /// </summary>
        private void NavigateToUpdateCenter()
        {
            _navigation.NavigateTo(NavigationView.UpdateView);
        }

        /// <summary>
        /// Exits the application.
        /// </summary>
        private void ExitApplication()
        {
            _applicationManager.ShutDown();
        }

        /// <summary>
        /// Displays the HTML.
        /// </summary>
        /// <param name="machineEvent">The HTML page.</param>
        private async void ResolveMachineEvent(MachinesEvent machineEvent)
        {
            if (machineEvent.EventType.HtmlPage != null)
            {
                if (_htmlPresenter.DisplayHtml(machineEvent.EventType.HtmlPage))
                {
                    if (ApplicationManager.ConnectedMachine != null && machineEvent.EventType.Resolvable)
                    {
                        _eventLogger.Log(String.Format("Event '{0}' resolved by user.", machineEvent.EventType.Name));
                        await ApplicationManager.ConnectedMachine.ResolveEvent((PMR.Diagnostics.EventType)machineEvent.Type);
                    }
                }
            }
            else
            {
                _notificationProvider.ShowWarning("Could not locate guidance content for the specified event.");
            }
        }

        /// <summary>
        /// Shows the about dialog.
        /// </summary>
        private void ShowAboutDialog()
        {
            NotificationProvider.ShowModalDialog<AboutViewVM>((x) => { });
        }

        private void ReportIssue()
        {
            var bug = TFSClient.CreateBug();

            _notificationProvider.ShowModalDialog<ReportIssueViewVM, ReportIssueView>(new ReportIssueViewVM(TFSClient.Project, bug), async (vm) =>
             {
                 using (_notificationProvider.PushTaskItem("Uploading bug report..."))
                 {
                     try
                     {
                         TFSClient.FinalizeBug(vm.WorkItem);
                         await TFSClient.UploadWorkItem(vm.WorkItem);
                     }
                     catch (Exception ex)
                     {
                         _notificationProvider.ShowError("An error occurred while trying to create the issue." + Environment.NewLine + ex.Message);
                     }
                 }

             }, null);
        }

        private void OpenResolvedBugs()
        {
            ResolvedIssuesViewVM vm = null;

            vm = new ResolvedIssuesViewVM(TFSClient, async (item) =>
            {
                //Approve
                using (_notificationProvider.PushTaskItem("Approving issue..."))
                {
                    vm.IsAvailable = false;
                    try
                    {
                        await TFSClient.CloseWorkItem(item);
                    }
                    catch (Exception ex)
                    {
                        _notificationProvider.ShowError("An error occurred while trying to update the issue." + Environment.NewLine + ex.Message);
                    }
                    vm.IsAvailable = true;

                    if (TFSClient.ResolvedWorkItems.Count == 0)
                    {
                        vm.Close();
                    }
                }
            }, async (item) =>
            {
                //Decline
                using (_notificationProvider.PushTaskItem("Reactivating issue..."))
                {
                    vm.IsAvailable = false;
                    try
                    {
                        await TFSClient.ReactivateWorkItem(item);
                    }
                    catch (Exception ex)
                    {
                        _notificationProvider.ShowError("An error occurred while trying to update the issue." + Environment.NewLine + ex.Message);
                    }

                    vm.IsAvailable = true;

                    if (TFSClient.ResolvedWorkItems.Count == 0)
                    {
                        vm.Close();
                    }
                }
            });

            _notificationProvider.ShowModalDialog<ResolvedIssuesViewVM, ResolvedIssuesView>(vm, (_) => { }, null);
        }

        private void OpenDeveloperConsole()
        {
            Console.ConsoleWindow console = new Console.ConsoleWindow();
            ApplicationManager.RegisterOpenedWindow(console);
            console.Owner = MainWindow.Instance;
            console.Show();
        }
    }
}