using GalaSoft.MvvmLight.Ioc; 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.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using Tango.Core.Commands; using Tango.Integration.Services; using Tango.Logging; using Tango.MachineStudio.Common; using Tango.MachineStudio.Common.Authentication; using Tango.MachineStudio.Common.Modules; using Tango.MachineStudio.Common.Navigation; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.Common.StudioApplication; using Tango.MachineStudio.UI.StudioApplication; using Tango.MachineStudio.UI.SupervisingController; using Tango.MachineStudio.UI.Views; using Tango.MachineStudio.UI.Windows; using Tango.PMR.Stubs; using Tango.SharedUI; using Tango.SharedUI.Helpers; using Tango.Transport.Adapters; namespace Tango.MachineStudio.UI.ViewModels { /// /// Represents the Machine Studio main view, view model. /// /// public class MainViewVM : ViewModel { private IStudioModule _currentModule; private INavigationManager _navigation; private bool _isDisconnecting; /// /// Gets or sets the current loaded module. /// public IStudioModule CurrentModule { get { return _currentModule; } set { _currentModule = value; RaisePropertyChangedAuto(); } } private bool _isModuleLoaded; /// /// Gets or sets a value indicating whether any module is loaded at the moment. /// public bool IsModuleLoaded { get { return _isModuleLoaded; } set { _isModuleLoaded = value; RaisePropertyChangedAuto(); } } private bool _isMenuOpened; /// /// Gets or sets a value indicating whether the side menu is opened. /// public bool IsMenuOpened { get { return _isMenuOpened; } set { _isMenuOpened = value; RaisePropertyChangedAuto(); } } /// /// Gets or sets the start module command. /// public RelayCommand StartModuleCommand { get; set; } /// /// Gets or sets the open module in window command. /// public RelayCommand OpenModuleInWindowCommand { get; set; } /// /// Gets or sets the home command. /// public RelayCommand HomeCommand { get; set; } /// /// Gets or sets the connect command. /// public RelayCommand ConnectCommand { get; set; } /// /// Gets or sets the disconnect command. /// public RelayCommand DisconnectCommand { get; set; } /// /// Gets or sets the sign-out command. /// public RelayCommand SignoutCommand { get; set; } private IAuthenticationProvider _authenticationProvider; /// /// Gets or sets the authentication provider. /// public IAuthenticationProvider AuthenticationProvider { get { return _authenticationProvider; } set { _authenticationProvider = value; RaisePropertyChangedAuto(); } } private IStudioModuleLoader _studioModuleLoader; /// /// Gets or sets the studio module loader. /// public IStudioModuleLoader StudioModuleLoader { get { return _studioModuleLoader; } set { _studioModuleLoader = value; RaisePropertyChangedAuto(); } } private INotificationProvider _notificationProvider; /// /// Gets or sets the notification provider. /// public INotificationProvider NotificationProvider { get { return _notificationProvider; } set { _notificationProvider = value; RaisePropertyChangedAuto(); } } private IStudioApplicationManager _applicationManager; /// /// Gets or sets the application manager. /// public IStudioApplicationManager ApplicationManager { get { return _applicationManager; } set { _applicationManager = value; RaisePropertyChangedAuto(); } } /// /// Initializes a new instance of the class. /// /// The view. /// The authentication provider. /// The studio module loader. /// The notification provider. /// The application manager. /// The navigation manager. public MainViewVM( IMainView view, IAuthenticationProvider authenticationProvider, IStudioModuleLoader studioModuleLoader, INotificationProvider notificationProvider, IStudioApplicationManager applicationManager, INavigationManager navigationManager) : base(view) { _navigation = navigationManager; AuthenticationProvider = authenticationProvider; StudioModuleLoader = studioModuleLoader; NotificationProvider = notificationProvider; ApplicationManager = applicationManager; StartModuleCommand = new RelayCommand(StartModule); HomeCommand = new RelayCommand(Home); ConnectCommand = new RelayCommand(ConnectToMachine); SignoutCommand = new RelayCommand(SignOut); DisconnectCommand = new RelayCommand(DisconnectFromMachine, (x) => ApplicationManager.IsMachineConnected && !_isDisconnecting); OpenModuleInWindowCommand = new RelayCommand(OpenModuleInWindow); } /// /// Disconnected from the current connected machine. /// private async void DisconnectFromMachine() { using (_notificationProvider.PushTaskItem("Disconnecting from machine...")) { _isDisconnecting = true; InvalidateRelayCommands(); await ApplicationManager.ConnectedMachine.Disconnect(); ApplicationManager.ConnectedMachine = null; _isDisconnecting = false; InvalidateRelayCommands(); } } /// /// Signs-out the current logged-in user. /// private void SignOut() { _authenticationProvider.Logout(); _navigation.NavigateTo(NavigationView.LoginView); CurrentModule = null; IsMenuOpened = false; } /// /// Opens the machine connection dialog to allow the user to scan and connect to remote machines view USB/TCP. /// private void ConnectToMachine() { _notificationProvider.ShowModalDialog(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(async (login) => { using (NotificationProvider.PushTaskItem("Connecting to machine " + x.SelectedMachine.ToString() + "...")) { try { await x.SelectedMachine.Connect(); var authenticated = await x.SelectedMachine.As().Authenticate(login.Password); if (!authenticated) { _notificationProvider.ShowError("It seems like you are not authorized to access the selected machine."); } else { ApplicationManager.ConnectedMachine = x.SelectedMachine; } } catch (Exception ex) { LogManager.Log(ex); _notificationProvider.ShowError(ex.Message); } InvalidateRelayCommands(); } }); } else { using (NotificationProvider.PushTaskItem("Connecting to " + x.SelectedMachine.ToString() + "...")) { try { await x.SelectedMachine.Connect(); ApplicationManager.ConnectedMachine = x.SelectedMachine; } catch (Exception ex) { LogManager.Log(ex); _notificationProvider.ShowError(ex.Message); } InvalidateRelayCommands(); } } InvalidateRelayCommands(); } InvalidateRelayCommands(); }); } /// /// Navigates to the home screen. /// private void Home() { StartModule(null); } /// /// Starts the specified module. /// /// The module. internal void StartModule(IStudioModule module) { IsMenuOpened = false; foreach (var m in StudioModuleLoader.AllModules.Where(x => x != module)) { m.IsLoaded = false; } if (module != null) { CurrentModule = module; CurrentModule.IsLoaded = true; IsModuleLoaded = true; View.NavigateToModule(module); } else { IsModuleLoaded = false; View.NavigateToModule(null); } } /// /// Called when the is loaded and attached. /// protected override void OnViewAttached() { base.OnViewAttached(); } private void OpenModuleInWindow(IStudioModule module) { if (module == null) return; try { StartModule(null); module.InNewWindow = true; var parent = (MainView.Self as MainView).TransitionControl.Controls.SingleOrDefault(x => x.Tag.ToString() == module.Name).Content as Grid; var view = parent.Children[0] as FrameworkElement; parent.Children.Remove(view); ModuleWindowVM vm = new ModuleWindowVM(module, parent); ModuleWindow window = new ModuleWindow(this, vm, view); window.Closing += (x, y) => { window.grid.Children.Remove(view); parent.Children.Add(view); module.InNewWindow = false; }; window.Owner = MainWindow.Instance; 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); } } } }