using GalaSoft.MvvmLight.Ioc; using RealTimeGraphEx.Controllers; using RealTimeGraphEx.DataSeries; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Media; using Tango.Core.Commands; using Tango.Integration.Observables; using Tango.MachineStudio.Common.Controls; using Tango.MachineStudio.Common.Notifications; using Tango.MachineStudio.Common.StudioApplication; using Tango.SharedUI; using System.Runtime.CompilerServices; using System.Windows.Threading; using Tango.Settings; using Tango.MachineStudio.Developer.Views; using Tango.Video.DirectCapture; using Tango.Integration.Operators; using Tango.PMR.Diagnostics; using System.Reflection; namespace Tango.MachineStudio.Developer.ViewModels { /// /// Represents the developer module main view, view model. /// /// public class MainViewVM : ViewModel, IShutdownRequestBlocker { private INotificationProvider _notification; private TimeSpan _runningJobEstimatedDuration; private Dictionary _controllers; #region Properties /// /// Gets or sets the application manager. /// public IStudioApplicationManager ApplicationManager { get; set; } /// /// Gets or sets observable entites database the adapter. /// public ObservablesEntitiesAdapter Adapter { get; set; } protected Machine _selectedMachine; /// /// Gets or sets the selected machine. /// public Machine SelectedMachine { get { return _selectedMachine; } set { _selectedMachine = value; OnMachineChanged(); RaisePropertyChangedAuto(); InvalidateRelayCommands(); if (_selectedMachine != null) { _selectedMachine.Saved -= SelectedMachine_Saved; _selectedMachine.Saved += SelectedMachine_Saved; } } } private List _liquidTypesRmls; /// /// Gets or sets the liquid types RMLS. /// public List LiquidTypesRmls { get { return _liquidTypesRmls; } set { _liquidTypesRmls = value; RaisePropertyChangedAuto(); } } private ProcessParametersTablesGroup _rmlProcessParametersTablesGroup; /// /// Gets or sets the RML process parameters table group (cloned). /// public ProcessParametersTablesGroup RmlProcessParametersTableGroup { get { return _rmlProcessParametersTablesGroup; } set { _rmlProcessParametersTablesGroup = value; RaisePropertyChangedAuto(); OnProcessParametersTableGroupChanged(); } } private ObservableCollection _groupsHistory; /// /// Gets or sets the RML process parameters groups history. /// public ObservableCollection GroupsHistory { get { return _groupsHistory; } set { _groupsHistory = value; RaisePropertyChangedAuto(); } } private ProcessParametersTablesGroup _selectedGroupHistory; /// /// Gets or sets the selected process parameters tables group history. /// public ProcessParametersTablesGroup SelectedGroupHistory { get { return _selectedGroupHistory; } set { _selectedGroupHistory = value; RaisePropertyChangedAuto(); OnSelectedGroupHistoryChanged(); } } private ProcessParametersTable _selectedProcessParametersTable; /// /// Gets or sets the selected process parameters table. /// public ProcessParametersTable SelectedProcessParametersTable { get { return _selectedProcessParametersTable; } set { _selectedProcessParametersTable = value; RaisePropertyChangedAuto(); OnSelectedParametersTableChanged(); } } private Job _selectedJob; /// /// Gets or sets the selected machine job. /// public Job SelectedJob { get { return _selectedJob; } set { _selectedJob = value; RaisePropertyChangedAuto(); OnSelectedJobChanged(); } } private Segment _selectedSegment; /// /// Gets or sets the job selected segment. /// public Segment SelectedSegment { get { return _selectedSegment; } set { _selectedSegment = value; RaisePropertyChangedAuto(); OnSelectedSegmentChanged(); } } private BrushStop _selectedBrushStop; /// /// Gets or sets the selected segment selected brush stop. /// public BrushStop SelectedBrushStop { get { return _selectedBrushStop; } set { _selectedBrushStop = value; RaisePropertyChangedAuto(); } } private Rml _selectedRML; /// /// Gets or sets the selected RML. /// public Rml SelectedRML { get { return _selectedRML; } set { _selectedRML = value; InvalidateLiquidFactorsAndProcessTables(); RaisePropertyChangedAuto(); InvalidateRelayCommands(); } } private bool _isSideBarOpened; /// /// Gets or sets a value indicating whether the configuration panels are opened. /// public bool IsSideBarOpened { get { return _isSideBarOpened; } set { _isSideBarOpened = value; RaisePropertyChangedAuto(); } } private ObservableCollection _availableSensors; /// /// Gets or sets the available sensors. /// public ObservableCollection AvailableSensors { get { return _availableSensors; } set { _availableSensors = value; RaisePropertyChangedAuto(); } } private ObservableCollection _graphs; /// /// Gets or sets the collection of displayed graph controls. /// public ObservableCollection Graphs { get { return _graphs; } set { _graphs = value; RaisePropertyChangedAuto(); } } private TimeSpan _estimatedDuration; /// /// Gets or sets the estimated duration for the selected job. /// public TimeSpan EstimatedDuration { get { return _estimatedDuration; } set { _estimatedDuration = value; RaisePropertyChangedAuto(); } } private bool _isJobRunning; /// /// Gets or sets a value indicating whether a job is currently running. /// public bool IsJobRunning { get { return _isJobRunning; } set { _isJobRunning = value; RaisePropertyChangedAuto(); } } private Job _runningJob; /// /// Gets or sets the currently running job. /// public Job RunningJob { get { return _runningJob; } set { _runningJob = value; RaisePropertyChangedAuto(); } } private double _runningJobProgress; /// /// Gets or sets the running job current progress. /// public double RunningJobProgress { get { return _runningJobProgress; } set { _runningJobProgress = value; RaisePropertyChangedAuto(); } } private TimeSpan _runningJobRemainingTime; /// /// Gets or sets the job remaining time. /// public TimeSpan RunningJobRemainingTime { get { return _runningJobRemainingTime; } set { _runningJobRemainingTime = value; RaisePropertyChangedAuto(); } } private bool _isJobCompleted; /// /// Gets or sets a value indicating whether the running job has completed successfully. /// public bool IsJobCompleted { get { return _isJobCompleted; } set { _isJobCompleted = value; RaisePropertyChangedAuto(); } } private bool _isJobFailed; /// /// Gets or sets a value indicating whether the running job has failed. /// public bool IsJobFailed { get { return _isJobFailed; } set { _isJobFailed = value; RaisePropertyChangedAuto(); } } private bool _showJobStatus; /// /// Gets or sets a value indicating whether to show all the relevant job status areas. /// public bool ShowJobStatus { get { return _showJobStatus; } set { _showJobStatus = value; RaisePropertyChangedAuto(); } } private bool _isJobCanceled; /// /// Gets or sets a value indicating whether the last running job was canceled. /// public bool IsJobCanceled { get { return _isJobCanceled; } set { _isJobCanceled = value; RaisePropertyChangedAuto(); } } /// /// Gets or sets the capture devices. /// public ObservableCollection CaptureDevices { get; set; } private IMachineOperator _machineOperator; /// /// Gets or sets the machine operator. /// public IMachineOperator MachineOperator { get { return _machineOperator; } set { _machineOperator = value; RaisePropertyChangedAuto(); } } #endregion #region Commands /// /// Gets or sets the edit machine command. /// public RelayCommand EditMachineCommand { get; set; } /// /// Gets or sets the edit RML command. /// public RelayCommand EditRMLCommand { get; set; } /// /// Gets or sets the toggle side bar command. /// public RelayCommand ToggleSideBarCommand { get; set; } /// /// Gets or sets the save process parameters command. /// public RelayCommand SaveProcessParametersCommand { get; set; } /// /// Gets or sets the save liquid factors command. /// public RelayCommand SaveLiquidFactorsCommand { get; set; } /// /// Gets or sets the add segment command. /// public RelayCommand AddSegmentCommand { get; set; } /// /// Gets or sets the remove segment command. /// public RelayCommand RemoveSegmentCommand { get; set; } /// /// Gets or sets the add job command. /// public RelayCommand AddJobCommand { get; set; } /// /// Gets or sets the remove job command. /// public RelayCommand RemoveJobCommand { get; set; } /// /// Gets or sets the add brush stop command. /// public RelayCommand AddBrushStopCommand { get; set; } /// /// Gets or sets the remove brush stop command. /// public RelayCommand RemoveBrushStopCommand { get; set; } /// /// Gets or sets the save jobs command. /// public RelayCommand SaveJobsCommand { get; set; } /// /// Gets or sets the start job command. /// public RelayCommand StartJobCommand { get; set; } /// /// Gets or sets the stop job command. /// public RelayCommand StopJobCommand { get; set; } /// /// Gets or sets the close job completion status command. /// public RelayCommand CloseJobCompletionStatusCommand { get; set; } /// /// Gets or sets the toggle camera command. /// public RelayCommand ToggleCameraCommand { get; set; } #endregion #region Constructors /// /// Initializes a new instance of the class. /// public MainViewVM(IMainView view) : base(view, true) { IsSideBarOpened = true; if (!this.DesignMode) { Adapter = ObservablesEntitiesAdapter.Instance; AvailableSensors = Adapter.Sensors.ToObservableCollection(); } Graphs = new ObservableCollection(); _controllers = new Dictionary(); } /// /// Initializes a new instance of the class. /// /// The application manager. /// The notification provider. [PreferredConstructor] public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IMainView view) : this(view) { _notification = notificationProvider; ApplicationManager = applicationManager; //Initialize Commands... EditMachineCommand = new RelayCommand(EditMachine, () => SelectedMachine != null); EditRMLCommand = new RelayCommand(EditRML, () => SelectedRML != null); ToggleSideBarCommand = new RelayCommand(() => IsSideBarOpened = !IsSideBarOpened); SaveProcessParametersCommand = new RelayCommand(SaveProcessParameters, () => SelectedRML != null && SelectedRML.ProcessParametersTablesGroups.Count > 0); SaveLiquidFactorsCommand = new RelayCommand(SaveLiquidFactors, () => SelectedRML != null); AddSegmentCommand = new RelayCommand(AddSegment, () => SelectedJob != null); RemoveSegmentCommand = new RelayCommand(RemoveSegment, () => SelectedSegment != null); AddJobCommand = new RelayCommand(AddJob, () => SelectedMachine != null); RemoveJobCommand = new RelayCommand(RemoveJob, () => SelectedJob != null); AddBrushStopCommand = new RelayCommand(AddBrushStop, () => SelectedSegment != null); RemoveBrushStopCommand = new RelayCommand(RemoveBrushStop, () => SelectedBrushStop != null); SaveJobsCommand = new RelayCommand(SaveJobs, () => SelectedMachine != null); StartJobCommand = new RelayCommand(StartJob, () => SelectedJob != null && !IsJobRunning); StopJobCommand = new RelayCommand(StopJob, () => IsJobRunning); CloseJobCompletionStatusCommand = new RelayCommand(CloseJobCompletionStatusBar); CaptureDevices = new ObservableCollection(); var availableDevices = CaptureDevice.GetAvailableCaptureDevices(); for (int i = 0; i < 3; i++) { if (i > availableDevices.Count - 1) { CaptureDevices.Add(new CaptureDevice() { Device = null }); } else { CaptureDevices.Add(new CaptureDevice() { Device = availableDevices[i] }); } } ToggleCameraCommand = new RelayCommand(ToggleCamera); ApplicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged; } private void ApplicationManager_ConnectedMachineChanged(object sender, Integration.Services.IExternalBridgeClient machine) { MachineOperator = machine; if (MachineOperator != null) { MachineOperator.EnableSensorsUpdate = true; MachineOperator.DiagnosticsDataAvailable += MachineOperator_DiagnosticsDataAvailable; } } private void MachineOperator_DiagnosticsDataAvailable(object sender, StartDiagnosticsResponse response) { foreach (var prop in response.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)) { GraphControllerBase controller = null; if (_controllers.TryGetValue(prop.Name, out controller)) { if (controller is GraphController) { double[] arr = Enumerable.ToArray(prop.GetValue(response) as IEnumerable); (controller as GraphController).PushData(arr); } else { //Multi Graph... } } } } #endregion #region Event Handlers /// /// Handles the Saved event of the SelectedMachine. /// /// The source of the event. /// The instance containing the event data. private void SelectedMachine_Saved(object sender, EventArgs e) { InvalidateLiquidFactorsAndProcessTables(); } private void SelectedJob_LengthChanged(object sender, EventArgs e) { UpdateEstimatedDuration(); } private void SelectedProcessParametersTable_DyeingSpeedMinInkUptakeChanged(object sender, EventArgs e) { if (SelectedSegment != null) { foreach (var liquidVolume in SelectedSegment.BrushStops.SelectMany(x => x.LiquidVolumes)) { liquidVolume.Invalidate(); } } UpdateEstimatedDuration(); } #endregion #region Virtual Methods protected virtual void OnSelectedParametersTableChanged() { if (SelectedProcessParametersTable != null) { SelectedProcessParametersTable.DyeingSpeedMinInkUptakeChanged -= SelectedProcessParametersTable_DyeingSpeedMinInkUptakeChanged; SelectedProcessParametersTable.DyeingSpeedMinInkUptakeChanged += SelectedProcessParametersTable_DyeingSpeedMinInkUptakeChanged; } SetSegmentBrushStopsLiquidVolumes(SelectedSegment); } /// /// Called when the process parameters table group has been changed /// /// private void OnProcessParametersTableGroupChanged() { if (RmlProcessParametersTableGroup != null && RmlProcessParametersTableGroup.ProcessParametersTables.Count > 0) { SelectedProcessParametersTable = RmlProcessParametersTableGroup.ProcessParametersTables.First(); } UpdateEstimatedDuration(); } /// /// Called when the selected segment has been changed /// protected virtual void OnSelectedSegmentChanged() { if (SelectedSegment != null) { SetSegmentBrushStopsLiquidVolumes(SelectedSegment); SelectedBrushStop = SelectedSegment.BrushStops.FirstOrDefault(); } } /// /// Called when the selected job has been changed. /// protected virtual void OnSelectedJobChanged() { if (SelectedJob != null) { SelectedSegment = SelectedJob.Segments.FirstOrDefault(); SelectedJob.LengthChanged -= SelectedJob_LengthChanged; SelectedJob.LengthChanged += SelectedJob_LengthChanged; UpdateEstimatedDuration(); } } /// /// Called when the selected group history has been changed /// protected virtual void OnSelectedGroupHistoryChanged() { if (SelectedGroupHistory != null) { RmlProcessParametersTableGroup = SelectedGroupHistory.CloneGroup(); } } /// /// Called when the machine has been changed /// protected virtual void OnMachineChanged() { InvalidateLiquidFactorsAndProcessTables(); } #endregion #region Private Methods private void ToggleCamera(CaptureDevice captureDevice) { if (captureDevice.Device != null) { captureDevice.IsStarted = !captureDevice.IsStarted; } } private void CloseJobCompletionStatusBar() { IsJobCompleted = false; IsJobFailed = false; IsJobCanceled = false; ShowJobStatus = false; RunningJob = null; } private void StopJob() { IsJobRunning = false; IsJobCanceled = true; } private void CompleteJob() { IsJobRunning = false; IsJobCompleted = true; } private void StartJob() { RunningJobRemainingTime = TimeSpan.Zero; RunningJobProgress = 0; IsJobFailed = false; IsJobCanceled = false; IsJobCompleted = false; IsJobRunning = true; ShowJobStatus = true; RunningJob = SelectedJob; _runningJobEstimatedDuration = EstimatedDuration; DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(0.03); timer.Tick += (x, y) => { RunningJobRemainingTime = _runningJobEstimatedDuration - TimeSpan.FromSeconds(RunningJobProgress / (SelectedProcessParametersTable.DyeingSpeed / 100d)); RunningJobProgress += 0.03; if (!IsJobRunning) { timer.Stop(); return; } else if (RunningJobProgress >= RunningJob.Length) { timer.Stop(); CompleteJob(); return; } }; timer.Start(); } private async void SaveJobs() { if (SelectedJob != null) { using (_notification.PushTaskItem("Saving machine jobs...")) { await SelectedJob.SaveAsync(); } } } private void UpdateEstimatedDuration() { if (SelectedJob != null && SelectedProcessParametersTable != null) { EstimatedDuration = TimeSpan.FromSeconds(SelectedJob.Length / (SelectedProcessParametersTable.DyeingSpeed / 100d)); } } private void SetSegmentBrushStopsLiquidVolumes(Segment segment) { if (!DesignMode && segment != null) { foreach (var stop in segment.BrushStops) { stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML, SelectedProcessParametersTable); } } } /// /// Saves the liquid factors. /// private async void SaveLiquidFactors() { if (SelectedRML != null) { using (_notification.PushTaskItem("Saving Liquid Factors...")) { await SelectedRML.SaveAsync(); InvalidateLiquidFactorsAndProcessTables(); } } } /// /// Navigates to the DB Module in order to edit the selected RML. /// private void EditRML() { ApplicationManager.RequestModule("Data Base", SelectedRML); } /// /// Navigates to the Machine Designer Module in order to edit the selected machine. /// private void EditMachine() { ApplicationManager.RequestModule("Machine Designer", SelectedMachine); } /// /// Saves the process parameters group. /// private async void SaveProcessParameters() { var response = _notification.ShowTextInput("Enter Group Name", "Group Name"); if (response == null) return; using (_notification.PushTaskItem("Saving Parameters Group...")) { ProcessParametersTablesGroup group = new ProcessParametersTablesGroup(); List tables = new List(); foreach (var table in RmlProcessParametersTableGroup.ProcessParametersTables) { var newTable = table.CloneEntity(); newTable.ProcessParametersTablesGroup = group; tables.Add(newTable); } group.Active = true; group.ProcessParametersTables = tables.ToObservableCollection(); group.Rml = SelectedRML; group.Name = response; group.SaveDate = DateTime.UtcNow; foreach (var g in SelectedRML.ProcessParametersTablesGroups) { g.Active = false; } //String machineGuid = SelectedMachine.Guid; //String rmlGuid = SelectedRML.Guid; SelectedRML.ProcessParametersTablesGroups.Add(group); await SelectedRML.SaveAsync(); //SelectedMachine = Adapter.Machines.SingleOrDefault(x => x.Guid == machineGuid); //SelectedRML = Adapter.Rmls.SingleOrDefault(x => x.Guid == rmlGuid); InvalidateLiquidFactorsAndProcessTables(); } } /// /// Invalidates the liquid factors and process parameters tables. /// private void InvalidateLiquidFactorsAndProcessTables() { if (SelectedRML != null && SelectedMachine != null) { LiquidTypesRmls = SelectedMachine.Configuration.IdsPacks.OrderBy(x => x.PackIndex).Select(x => x.LiquidType).SelectMany(x => x.LiquidTypesRmls).Where(x => x.Rml.Guid == SelectedRML.Guid).ToList(); RmlProcessParametersTableGroup = SelectedRML.ProcessParametersTablesGroups.SingleOrDefault(x => x.Active); if (RmlProcessParametersTableGroup != null) { RmlProcessParametersTableGroup = RmlProcessParametersTableGroup.CloneGroup(); RmlProcessParametersTableGroup.ProcessParametersTables = RmlProcessParametersTableGroup.ProcessParametersTables.OrderBy(x => x.TableIndex).ToObservableCollection(); } GroupsHistory = SelectedRML.ProcessParametersTablesGroups.OrderByDescending(x => x.SaveDate).OrderBy(x => !x.Active).ToObservableCollection(); } } /// /// Removes the selected segment. /// private void RemoveSegment() { if (SelectedJob != null && SelectedSegment != null) { SelectedJob.Segments.Remove(SelectedSegment); } } /// /// Adds a new segment. /// private void AddSegment() { if (SelectedJob != null) { Segment seg = new Segment(); seg.Name = "Untitled Segment"; seg.Length = 1; SelectedJob.Segments.Add(seg); SelectedSegment = seg; AddBrushStop(); } } /// /// Removes the selected job. /// private void RemoveJob() { if (SelectedMachine != null && SelectedJob != null) { SelectedMachine.Jobs.Remove(SelectedJob); } } /// /// Adds a new job to the selected machine. /// private void AddJob() { if (SelectedMachine != null) { SelectedMachine.Jobs.Add(new Job() { Name = "Untitled Job", CreationDate = DateTime.UtcNow, }); } } /// /// Removes the selected brush stop. /// private void RemoveBrushStop() { if (SelectedBrushStop != null && SelectedSegment != null) { SelectedSegment.BrushStops.Remove(SelectedBrushStop); } } /// /// Adds a new brush stop to the selected segment. /// private void AddBrushStop() { if (SelectedSegment != null) { var stop = new BrushStop(); stop.ColorSpace = Adapter.ColorSpaces.FirstOrDefault(); stop.Color = Colors.Black; stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML, SelectedProcessParametersTable); SelectedSegment.BrushStops.Add(stop); } } #endregion #region Override Methods protected override void RaisePropertyChangedAuto([CallerMemberName] string caller = null) { base.RaisePropertyChangedAuto(caller); InvalidateRelayCommands(); } #endregion #region Public Events /// /// Add sensor graph from available sensors to displayed graphs. /// /// The sensor. public void OnDropAvailableSensor(Sensor sensor) { if (Graphs.Count < 8) { IRealTimeGraph graphControl = null; GraphControllerBase controller = null; if (!sensor.MultiChannel) { graphControl = new RealTimeGraphControl(); controller = new GraphController(); graphControl.Controller = controller; } else { graphControl = new RealTimeGraphMultiControl(); controller = new GraphMultiController(); for (int i = 0; i < sensor.ChannelCount; i++) { (controller as GraphMultiController).AddSeries(new DataYSeries() { Name = sensor.Description.First().ToString() + (i + 1), UseFillAndStroke = true, Stroke = new SolidColorBrush(Core.Helpers.ColorHelper.GetRandomColor()) }); } graphControl.Controller = controller; } graphControl.Tag = sensor; graphControl.SensorName = sensor.Description; graphControl.SensorUnits = sensor.Units; graphControl.InnerGraph.Minimum = sensor.Min; graphControl.InnerGraph.Maximum = sensor.Max; graphControl.InnerGraph.MaxPoints = Common.Helpers.GraphsHelper.GetMaxPoints(sensor.PointsPerFrame); graphControl.GraphRemoveButtonPressed += (sender, __) => { RemoveGraph(sender as IRealTimeGraph); }; Graphs.Add(graphControl); AvailableSensors.Remove(sensor); _controllers.Add(sensor.Name, controller); } else { _notification.ShowInfo("The maximum number of real-time graphs is eight. Please remove a graph to add another."); } } /// /// Switch the brush stop position in the segment. /// /// The dragged stop. /// The dropped stop. public void OnDropBrushStop(BrushStop draggedStop, BrushStop droppedStop) { int tmpIndex = draggedStop.StopIndex; draggedStop.StopIndex = droppedStop.StopIndex; droppedStop.StopIndex = tmpIndex; SelectedSegment.BrushStops.Swap(draggedStop, droppedStop); } /// /// Removes the graph. /// /// The graph. public void RemoveGraph(IRealTimeGraph graph) { var sensor = graph.Tag as Sensor; _controllers.Remove(sensor.Name); graph.InnerGraph.Dispose(); Graphs.Remove(graph); AvailableSensors.Insert(0, sensor); } #endregion #region IShutdownRequestBlocker public Task OnShutdownRequest() { if (IsJobRunning) { InvokeUI(() => { _notification.ShowWarning("Please stop the currently running job before closing the developer module."); }); return Task.FromResult(false); } SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedMachineGuid = SelectedMachine != null ? SelectedMachine.Guid : null; SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedRMLGuid = SelectedRML != null ? SelectedRML.Guid : null; SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedJobGuid = SelectedJob != null ? SelectedJob.Guid : null; SettingsManager.SaveDefaultSettings(); return Task.FromResult(true); } #endregion #region IMainView protected override void OnViewAttached() { base.OnViewAttached(); if (SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedMachineGuid != null) { SelectedMachine = Adapter.Machines.SingleOrDefault(x => x.Guid == SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedMachineGuid); } if (SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedRMLGuid != null) { SelectedRML = Adapter.Rmls.SingleOrDefault(x => x.Guid == SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedRMLGuid); } if (SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedJobGuid != null && SelectedMachine != null) { SelectedJob = SelectedMachine.Jobs.SingleOrDefault(x => x.Guid == SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedJobGuid); } } #endregion } }