aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Stubs/ViewModels/MainViewVM.cs
blob: afd5e4d70739a3864b6599f404083314e8ab2626 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
generated by cgit v1.3.1 (git 2.54.0) at 2026-07-25 18:58:27 +0000
 


f='#n537'>537
538
539
540
541
542
543
544
545
546
using Microsoft.Win32;
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 Tango.Core.Commands;
using Tango.MachineStudio.Common;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.Scripting;
using Tango.Settings;
using Tango.SharedUI;
using Tango.Stubs;
using Tango.Transport;
using Tango.Transport.Adapters;

namespace Tango.MachineStudio.Stubs.ViewModels
{
    /// <summary>
    /// Represents the script execution module main view model.
    /// </summary>
    /// <seealso cref="Tango.SharedUI.ViewModel" />
    public class MainViewVM : StudioViewModel<StubsModule>
    {
        private UsbTransportAdapter _adapter; //Holds the USB transport adapter.
        private StubManager _stubManager;
        private INotificationProvider _notification;
        private StubsModuleSettings _settings;

        #region Properties

        public IStudioApplicationManager ApplicationManager { get; set; }

        private bool _useConnectedMachine;
        /// <summary>
        /// Gets or sets a value indicating whether [use connected machine].
        /// </summary>
        public bool UseConnectedMachine
        {
            get { return _useConnectedMachine; }
            set
            {
                _useConnectedMachine = value;

                if (_useConnectedMachine && !ApplicationManager.IsMachineConnected)
                {
                    _notification.ShowError("No connected machine found.");
                    _useConnectedMachine = false;
                }

                RaisePropertyChangedAuto();
                InvalidateRelayCommands();
            }
        }

        /// <summary>
        /// Gets or sets the code tabs.
        /// </summary>
        public ObservableCollection<CodeTabVM> CodeTabs { get; set; }

        /// <summary>
        /// Gets or sets the additional highlight C# types.
        /// </summary>
        public ObservableCollection<KeyValuePair<String, Type>> HighlightTypes { get; set; }

        /// <summary>
        /// Gets or sets the collection of stub snippets.
        /// </summary>
        public ObservableCollection<StubSnippetVM> StubSnippets { get; set; }

        private StubSnippetVM _selectedStubSnippet;
        /// <summary>
        /// Gets or sets the selected stub snippet.
        /// </summary>
        public StubSnippetVM SelectedStubSnippet
        {
            get { return _selectedStubSnippet; }
            set { _selectedStubSnippet = value; RaisePropertyChanged(nameof(SelectedStubSnippet)); }
        }

        private String _log;
        /// <summary>
        /// Gets or sets the current response log.
        /// </summary>
        public String Log
        {
            get { return _log; }
            set { _log = value; RaisePropertyChanged(nameof(Log)); }
        }

        private CodeTabVM _selectedCodeTab;
        /// <summary>
        /// Gets or sets the selected code tab.
        /// </summary>
        public CodeTabVM SelectedCodeTab
        {
            get { return _selectedCodeTab; }
            set { _selectedCodeTab = value; RaisePropertyChanged(nameof(SelectedCodeTab)); InvalidateRelayCommands(); }
        }

        private bool _isConnected;
        /// <summary>
        /// Gets or sets a value indicating whether the USB adapter is connected.
        /// </summary>
        public bool IsConnected
        {
            get { return _isConnected; }
            set { _isConnected = value; RaisePropertyChanged(nameof(IsConnected)); InvalidateRelayCommands(); }
        }

        private List<String> _ports;
        /// <summary>
        /// Gets or sets the available USB ports.
        /// </summary>
        public List<String> Ports
        {
            get { return _ports; }
            set { _ports = value; RaisePropertyChanged(nameof(Ports)); }
        }

        private String _selectedPort;
        /// <summary>
        /// Gets or sets the selected USB port.
        /// </summary>
        public String SelectedPort
        {
            get { return _selectedPort; }
            set { _selectedPort = value; RaisePropertyChanged(nameof(SelectedPort)); InvalidateRelayCommands(); }
        }

        private String _status;
        /// <summary>
        /// Gets or sets the current status bar text.
        /// </summary>
        public String Status
        {
            get { return _status; }
            set { _status = value; RaisePropertyChanged(nameof(Status)); }
        }

        private bool _isRunning;
        /// <summary>
        /// Gets or sets a value indicating whether a stub is currently running.
        /// </summary>
        public bool IsRunning
        {
            get { return _isRunning; }
            set { _isRunning = value; RaisePropertyChanged(nameof(IsRunning)); InvalidateRelayCommands(); }
        }

        #endregion

        #region Commands

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

        /// <summary>
        /// Gets or sets the close tab command.
        /// </summary>
        public RelayCommand<CodeTabVM> CloseTabCommand { get; set; }

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

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

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

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

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

        /// <summary>
        /// Gets or sets the save as command.
        /// </summary>
        public RelayCommand SaveAsCommand { get; set; }

        /// <summary>
        /// Gets or sets the stub snippet selected command.
        /// </summary>
        public RelayCommand StubSnippetSelectedCommand { get; set; }

        /// <summary>
        /// Gets or sets the insert snippet command.
        /// </summary>
        public RelayCommand<String> InsertSnippetCommand { get; set; }

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

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="MainViewVM"/> class.
        /// </summary>
        public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notification)
        {
            _settings = SettingsManager.Default.GetOrCreate<StubsModuleSettings>();

            ApplicationManager = applicationManager;
            _notification = notification;

            CodeTabs = new ObservableCollection<CodeTabVM>();

            NewCommand = new RelayCommand(CreateNewTab);
            CloseTabCommand = new RelayCommand<CodeTabVM>(OnTabClosing);
            RunCommand = new RelayCommand(RunTab, (x) => (IsConnected || UseConnectedMachine) && !IsRunning && SelectedCodeTab != null);
            StopCommand = new RelayCommand(StopTab, (x) => (IsConnected || UseConnectedMachine) && IsRunning && SelectedCodeTab != null);
            InsertSnippetCommand = new RelayCommand<string>((x) => { });

            HighlightTypes = new ObservableCollection<KeyValuePair<string, Type>>();
            HighlightTypes.Add(new KeyValuePair<string, Type>("stubManager", typeof(StubManager)));

            StubSnippets = new ObservableCollection<StubSnippetVM>();

            foreach (var stubType in StubBase.GetAvailableRequestStubs())
            {
                StubSnippetVM snippet = new StubSnippetVM();
                snippet.Name = stubType.Name.Replace("Stub_", "");
                snippet.Code = String.Format("stubManager.Run(\"{0}\" ,{1});", stubType.Name, String.Join(", ", stubType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.PropertyType.Name == "string" ? "\"string\"" : x.PropertyType.Name)));
                StubSnippets.Add(snippet);
            }

            ToggleConnectionCommand = new RelayCommand(ToggleConnection, (x) => !IsRunning);
            OpenCommand = new RelayCommand(OpenFile);
            SaveCommand = new RelayCommand(SaveFile);
            SaveAsCommand = new RelayCommand(SaveAsFile);
            StubSnippetSelectedCommand = new RelayCommand(OnStubSnippetSelected);
            ExitCommand = new RelayCommand(() => Application.Current.Shutdown());

            Ports = new List<string>()
            {
                "COM1",
                "COM2",
                "COM3",
                "COM4",
                "COM5",
                "COM6",
                "COM7",
                "COM8",
                "COM9",
            };

            SelectedPort = _settings.SelectedPort != null ? _settings.SelectedPort : Ports.First();

            Status = "Ready";

            if (_settings.LastTabs.Count > 0)
            {
                foreach (var file in _settings.LastTabs)
                {
                    if (File.Exists(file))
                    {
                        OpenFile(file);
                    }
                }
            }
            else
            {
                CreateNewTab();
            }
        }

        #endregion

        #region Virtual Methods

        /// <summary>
        /// Called when a stub snippet is double clicked.
        /// </summary>
        protected virtual void OnStubSnippetSelected()
        {
            if (SelectedStubSnippet != null)
            {
                if (InsertSnippetCommand != null)
                {
                    InsertSnippetCommand.Execute(SelectedStubSnippet.Code);
                }
            }
        }

        /// <summary>
        /// Called when user closes a script tab.
        /// </summary>
        /// <param name="codeTab">The code tab.</param>
        protected virtual void OnTabClosing(CodeTabVM codeTab)
        {
            CodeTabs.Remove(codeTab);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Saves the selected script file.
        /// </summary>
        private void SaveFile()
        {
            if (SelectedCodeTab != null)
            {
                if (SelectedCodeTab.File == null)
                {
                    SaveAsFile();
                }
                else
                {
                    File.WriteAllText(SelectedCodeTab.File, SelectedCodeTab.Code);
                }
            }
        }

        /// <summary>
        /// Saves the selected script file.
        /// </summary>
        private void SaveAsFile()
        {
            if (SelectedCodeTab != null)
            {
                SaveFileDialog dlg = new SaveFileDialog();
                dlg.Filter = "C# Script Files|*.cs";
                dlg.DefaultExt = ".cs";
                if (dlg.ShowDialog().Value)
                {
                    File.WriteAllText(dlg.FileName, SelectedCodeTab.Code);
                    SelectedCodeTab.File = dlg.FileName;
                }
            }
        }

        /// <summary>
        /// Opens a script from HD.
        /// </summary>
        private void OpenFile()
        {
            OpenFileDialog dlg = new OpenFileDialog();
            dlg.Filter = "C# Script Files|*.cs";
            dlg.Multiselect = true;
            if (dlg.ShowDialog().Value)
            {
                foreach (var file in dlg.FileNames)
                {
                    OpenFile(file);
                }
            }
        }

        /// <summary>
        /// Opens the file.
        /// </summary>
        /// <param name="file">The file.</param>
        private void OpenFile(String file)
        {
            var newTab = new CodeTabVM();
            newTab.File = file;
            newTab.Code = File.ReadAllText(file);
            CodeTabs.Add(newTab);
            SelectedCodeTab = newTab;
        }

        /// <summary>
        /// Toggles the USB adapter connection.
        /// </summary>
        private void ToggleConnection()
        {
            try
            {
                if (!IsConnected)
                {
                    _adapter = new UsbTransportAdapter(SelectedPort);
                    _adapter.Connect().Wait();
                    IsConnected = true;
                }
                else
                {
                    _adapter.Disconnect().Wait();
                    IsConnected = false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "Tango");
            }
        }

        /// <summary>
        /// Creates a new script tab.
        /// </summary>
        private void CreateNewTab()
        {
            var newTab = new CodeTabVM();
            CodeTabs.Add(newTab);
            SelectedCodeTab = newTab;
        }

        /// <summary>
        /// Runs the selected script tab.
        /// </summary>
        private async void RunTab()
        {
            if (UseConnectedMachine && !ApplicationManager.IsMachineConnected)
            {
                _notification.ShowError("Cannot execute stub while 'Connected Machine' is set but no machine connected.");
                return;
            }

            IsRunning = true;
            SelectedCodeTab.IsRunning = true;
            Log = (DateTime.Now.ToTimeString() + ": ") + "Executing script '" + SelectedCodeTab.Title + "'..." + Environment.NewLine;

            await Task.Factory.StartNew(async () =>
            {
                try
                {
                    ITransportAdapter adapter = _adapter;

                    if (ApplicationManager.IsMachineConnected && UseConnectedMachine)
                    {
                        adapter = ApplicationManager.ConnectedMachine.Adapter;
                    }

                    _stubManager = new StubManager(adapter);
                    var thisStubManager = _stubManager;
                    _stubManager.Completed += Manager_Completed;
                    _stubManager.Failed += Manager_Failed;
                    _stubManager.Executed += Manager_Executed;

                    ScriptEngine engine = new ScriptEngine(new StubOnExecuteParameters(_stubManager));

                    engine.ReferencedAssemblies.Add(this.GetType());
                    await engine.Run(SelectedCodeTab.Code,null);

                    if (!thisStubManager.Aborted)
                    {
                        IsRunning = false;
                        SelectedCodeTab.IsRunning = false;
                    }
                }
                catch (Exception ex)
                {
                    IsRunning = false;
                    SelectedCodeTab.IsRunning = false;
                    MessageBox.Show(ex.Message, "Tango");
                }
            });
        }

        /// <summary>
        /// Stops the currently current script.
        /// </summary>
        private void StopTab()
        {
            if (_stubManager != null)
            {
                _stubManager.Abort();
                IsRunning = false;
                SelectedCodeTab.IsRunning = false;
                Status = "Stopped!";
                Log += (DateTime.Now.ToTimeString() + ": ") + "Stopped!" + Environment.NewLine;
            }
        }

        #endregion

        #region Event Handlers

        /// <summary>
        /// Handled the <see cref="StubManager"/> Executed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="stubName">Name of the stub.</param>
        private void Manager_Executed(object sender, string stubName)
        {
            Log += (DateTime.Now.ToTimeString() + ": ") + "Executing '" + stubName + "'..." + Environment.NewLine;
            Status = "Executing " + stubName + "...";
        }

        /// <summary>
        /// Handled the <see cref="StubManager"/> Failed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="ex">The exception.</param>
        private void Manager_Failed(object sender, Exception ex)
        {
            if (IsRunning)
            {
                Log += (DateTime.Now.ToTimeString() + ": ") + ex.Message + Environment.NewLine;
                Status = "Failed!";
            }
        }

        /// <summary>
        /// Handled the <see cref="StubManager"/> Completed event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="response">The response.</param>
        private void Manager_Completed(object sender, string response)
        {
            Log += (DateTime.Now.ToTimeString() + ": ") + "Response Received:" + Environment.NewLine;
            Log += (DateTime.Now.ToTimeString() + ": ") + response + Environment.NewLine;
            Status = "Completed";
        }

        #endregion

        #region Studio View Model

        /// <summary>
        /// Called when [shutdown request].
        /// </summary>
        /// <returns></returns>
        public override void OnShuttingDown()
        {
            _settings.SelectedPort = SelectedPort;
            _settings.LastTabs = CodeTabs.Select(x => x.File).ToList();
        }

        #endregion
    }
}