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; using Tango.PMR.Common; using Tango.SharedUI.Helpers; using Tango.Transport; using Tango.Integration.Printing; using Tango.Integration.Diagnostics; using Microsoft.Win32; using Tango.MachineStudio.Technician.ViewModels; using Tango.MachineStudio.Common.Diagnostics; using Tango.MachineStudio.Common.Video; using Tango.Integration.Services; using Tango.MachineStudio.Developer.Navigation; using System.Data.Entity; using Tango.MachineStudio.Common.Authentication; using DeepEqual.Syntax; 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; private int _fullScreenGraphIndex; private JobHandler _jobHandler; private DeveloperNavigationManager _navigation; private ObservablesContext _dbJobContext; private Job _jobFromList; private bool _blockInvalidateCommands; private IAuthenticationProvider _authentication; #region Properties private ObservableCollection _colorSpaces; /// /// Gets or sets the color spaces. /// public ObservableCollection ColorSpaces { get { return _colorSpaces; } set { _colorSpaces = value; RaisePropertyChangedAuto(); } } private ObservableCollection _rmls; /// /// Gets or sets the RMLS. /// public ObservableCollection Rmls { get { return _rmls; } set { _rmls = value; RaisePropertyChangedAuto(); } } /// /// Gets or sets the application manager. /// public IStudioApplicationManager ApplicationManager { get; set; } /// /// Gets or sets the video capture provider. /// public IVideoCaptureProvider VideoCaptureProvider { 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(); } } private ObservableCollection _selectedJobs; /// /// Gets or sets the selected jobs. /// public ObservableCollection SelectedJobs { get { return _selectedJobs; } set { _selectedJobs = value; RaisePropertyChangedAuto(); } } private Segment _selectedSegment; /// /// Gets or sets the job selected segment. /// public Segment SelectedSegment { get { return _selectedSegment; } set { _selectedSegment = value; RaisePropertyChangedAuto(); OnSelectedSegmentChanged(); } } private ObservableCollection _selectedSegments; /// /// Gets or sets the selected segments. /// public ObservableCollection SelectedSegments { get { return _selectedSegments; } set { _selectedSegments = value; RaisePropertyChangedAuto(); } } private BrushStop _selectedBrushStop; /// /// Gets or sets the selected segment selected brush stop. /// public BrushStop SelectedBrushStop { get { return _selectedBrushStop; } set { _selectedBrushStop = value; RaisePropertyChangedAuto(); } } private ObservableCollection _selectedBrushStops; /// /// Gets or sets the selected brush stops. /// public ObservableCollection SelectedBrushStops { get { return _selectedBrushStops; } set { _selectedBrushStops = 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 _availableGraphs; /// /// Gets or sets the available sensors. /// public ObservableCollection AvailableGraphs { get { return _availableGraphs; } set { _availableGraphs = 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(); } } private IMachineOperator _machineOperator; /// /// Gets or sets the machine operator. /// public IMachineOperator MachineOperator { get { return _machineOperator; } set { _machineOperator = value; RaisePropertyChangedAuto(); } } private IRealTimeGraph _fullScreenGraph; /// /// Gets or sets the full screen graph. /// public IRealTimeGraph FullScreenGraph { get { return _fullScreenGraph; } set { _fullScreenGraph = value; RaisePropertyChangedAuto(); } } private List _runningJobSegments; /// /// Gets or sets the running job segments. /// public List RunningJobSegments { get { return _runningJobSegments; } set { _runningJobSegments = 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 job command. /// public RelayCommand SaveJobCommand { get; set; } /// /// Gets or sets the discard job command. /// public RelayCommand DiscardJobCommand { 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; } /// /// Gets or sets the exit full screen command. /// public RelayCommand ExitFullScreenCommand { get; set; } /// /// Gets or sets the load job command. /// public RelayCommand LoadJobCommand { get; set; } /// /// Gets or sets the duplicate job command. /// public RelayCommand DuplicateJobCommand { get; set; } #endregion #region Constructors /// /// Initializes a new instance of the class. /// public MainViewVM(IMainView view) : base(view, true) { if (!this.DesignMode) { Adapter = ObservablesEntitiesAdapter.Instance; AvailableGraphs = Adapter.TechMonitors.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, IDiagnosticsFrameProvider diagnosticsFrameProvider, IVideoCaptureProvider videoCaptureProvider, DeveloperNavigationManager navigation, IAuthenticationProvider authentication) : this(view) { SelectedJobs = new ObservableCollection(); _authentication = authentication; _notification = notificationProvider; _navigation = navigation; ApplicationManager = applicationManager; VideoCaptureProvider = videoCaptureProvider; diagnosticsFrameProvider.FrameReceived += DiagnosticsFrameProvider_FrameReceived; //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); SaveJobCommand = new RelayCommand(SaveJob, () => SelectedMachine != null); DiscardJobCommand = new RelayCommand(DiscardJob, () => SelectedMachine != null); StartJobCommand = new RelayCommand(StartJob, () => SelectedJob != null && !IsJobRunning); StopJobCommand = new RelayCommand(StopJob, () => IsJobRunning); CloseJobCompletionStatusCommand = new RelayCommand(CloseJobCompletionStatusBar); ExitFullScreenCommand = new RelayCommand(ExitFullScreen); LoadJobCommand = new RelayCommand(LoadJob, () => SelectedJob != null); DuplicateJobCommand = new RelayCommand(DuplicateJob, () => SelectedJob != null); ToggleCameraCommand = new RelayCommand(ToggleCamera); ApplicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged; } #endregion #region Event Handlers /// /// Handles the diagnostics provider frame received event. /// /// The sender. /// The response. private void DiagnosticsFrameProvider_FrameReceived(object sender, PushDiagnosticsResponse response) { PopulateDiagnosticsData(response); } /// /// Handles the application manager connected machine changes event. /// /// The sender. /// The machine. private void ApplicationManager_ConnectedMachineChanged(object sender, IExternalBridgeClient machine) { MachineOperator = machine; } /// /// 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(); SelectedMachine.Reload(); } /// /// Handles the LengthChanged event of the SelectedJob. /// /// The source of the event. /// The instance containing the event data. private void SelectedJob_LengthChanged(object sender, EventArgs e) { UpdateEstimatedDuration(); } /// /// Handles the DyeingSpeedMinInkUptakeChanged event of the SelectedProcessParametersTable. /// /// The source of the event. /// The instance containing the event data. 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 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 async void DuplicateJob() { if (SelectedJobs.Count > 0) { using (_notification.PushTaskItem("Cloning selected jobs...")) { int index = SelectedMachine.Jobs.Max(x => x.JobIndex); foreach (var job in SelectedJobs) { var cloned = job.Clone(); cloned.JobIndex = ++index; SelectedMachine.Jobs.Add(cloned); } await SelectedMachine.SaveAsync(); } } } private async void LoadJob() { if (SelectedJob != null) { SelectedSegments = new ObservableCollection(); SelectedBrushStops = new ObservableCollection(); SelectedRML = null; SelectedSegment = null; SelectedGroupHistory = null; SelectedBrushStop = null; SelectedProcessParametersTable = null; RmlProcessParametersTableGroup = null; using (_notification.PushTaskItem("Loading job details...")) { //await Task.Factory.StartNew(() => //{ _blockInvalidateCommands = false; _dbJobContext = ObservablesContext.CreateDefault(); _dbJobContext.Configuration.LazyLoadingEnabled = true; ColorSpaces = _dbJobContext.ColorSpaces.ToObservableCollection(); Rmls = _dbJobContext.Rmls.ToObservableCollection(); _jobFromList = SelectedJob; _selectedJob = _dbJobContext.Jobs.SingleOrDefault(x => x.Guid == SelectedJob.Guid); _selectedRML = SelectedJob.Rml; _selectedSegment = SelectedJob.Segments.FirstOrDefault(); SelectedJob.LengthChanged -= SelectedJob_LengthChanged; SelectedJob.LengthChanged += SelectedJob_LengthChanged; SelectedJob = _selectedJob; SelectedRML = _selectedRML; SelectedSegment = _selectedSegment; UpdateEstimatedDuration(); _blockInvalidateCommands = false; InvalidateRelayCommands(); InvokeUI(() => _navigation.NavigateTo(DeveloperNavigationView.JobView)); //}); } } } private async void SaveJob() { if (SelectedJob != null) { using (_notification.PushTaskItem("Saving job to database...")) { SelectedJob.LastUpdated = DateTime.UtcNow; SelectedJob.Rml = SelectedRML; await SelectedJob.SaveAsync(_dbJobContext); _jobFromList = SelectedMachine.Jobs.SingleOrDefault(x => x.Guid == SelectedJob.Guid); await _jobFromList.Reload(); foreach (var segment in _jobFromList.Segments) { await segment.Reload(); foreach (var stop in segment.BrushStops) { await stop.Reload(); } } } } } private void DiscardJob() { //bool jobModified = !SelectedJob.WithDeepEqual(_jobFromList) // .IgnoreSourceProperty(x => x.Machine) // .IgnoreSourceProperty(x => x.JobRuns) // .IgnoreSourceProperty(x => x.Parameters) // .IgnoreSourceProperty(x => x.Rml) // .IgnoreSourceProperty(x => x.User) // .IgnoreSourceProperty(x => x.Segments) // .Compare(); bool jobModified = !SelectedJob.CompareUsingJson(_jobFromList); if (jobModified) { if (_notification.ShowQuestion("This will discard the current job changes. Are you sue?")) { _dbJobContext.Dispose(); _navigation.NavigateTo(DeveloperNavigationView.MachineJobSelectionView); } } else { _dbJobContext.Dispose(); _navigation.NavigateTo(DeveloperNavigationView.MachineJobSelectionView); } } private void ClearGraphs() { _controllers.ToList().ForEach(x => x.Value.Clear()); } private void PopulateDiagnosticsData(PushDiagnosticsResponse data) { foreach (var prop in data.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(data) as IEnumerable); (controller as GraphController).PushData(arr); } else { DoubleArray[] arrayOfDoubles = Enumerable.ToArray(prop.GetValue(data) as IEnumerable); (controller as GraphMultiController).PushData(arrayOfDoubles.Select(x => x.Data.ToList()).ToList()); } } } } private void ExitFullScreen() { if (FullScreenGraph != null) { FullScreenGraph.EnableToolBar = true; Graphs.Insert(_fullScreenGraphIndex, FullScreenGraph); FullScreenGraph = null; } } private void StartFullScreenGraph(IRealTimeGraph graph) { graph.EnableToolBar = false; _fullScreenGraphIndex = Graphs.IndexOf(graph); Graphs.Remove(graph); FullScreenGraph = graph; } private void ToggleCamera(CaptureDevice captureDevice) { if (captureDevice.Device != null) { captureDevice.IsStarted = !captureDevice.IsStarted; } } private void CloseJobCompletionStatusBar() { _navigation.NavigateTo(DeveloperNavigationView.JobView); IsJobCompleted = false; IsJobFailed = false; IsJobCanceled = false; ShowJobStatus = false; RunningJob = null; } private void StopJob() { IsJobRunning = false; IsJobCanceled = true; _jobHandler.Cancel(); } private void FailJob() { IsJobRunning = false; IsJobFailed = true; } private void CompleteJob() { IsJobRunning = false; IsJobCompleted = true; } private void StartJob() { if (MachineOperator == null || MachineOperator.State != TransportComponentState.Connected) { _notification.ShowError("No machine connected. Could not execute the specified job."); return; } if (SelectedProcessParametersTable == null) { _notification.ShowError("No process parameters table selected. Could not execute the specified job."); return; } RunningJobRemainingTime = TimeSpan.Zero; RunningJobProgress = 0; IsJobFailed = false; IsJobCanceled = false; IsJobCompleted = false; IsJobRunning = true; ShowJobStatus = true; RunningJob = SelectedJob; _runningJobEstimatedDuration = EstimatedDuration; RunningJobSegments = CreateRunningJobEffectiveSegments(RunningJob); _navigation.NavigateTo(DeveloperNavigationView.RunningJobView); _jobHandler = MachineOperator.Print(SelectedJob, SelectedProcessParametersTable); _jobHandler.StatusReceived += (x, status) => { RunningJobRemainingTime = _runningJobEstimatedDuration - TimeSpan.FromSeconds(RunningJobProgress / (SelectedProcessParametersTable.DyeingSpeed / 100d)); RunningJobProgress = status.Progress; foreach (var segment in RunningJobSegments) { var previousSegmentsWithThis = RunningJobSegments.Where(s => RunningJobSegments.IndexOf(s) <= RunningJobSegments.IndexOf(segment)).ToList(); var segmentsDuration = TimeSpan.FromSeconds(previousSegmentsWithThis.Sum(s => s.Length) / (SelectedProcessParametersTable.DyeingSpeed / 100d)); var segmentDuration = TimeSpan.FromSeconds(segment.Length / (SelectedProcessParametersTable.DyeingSpeed / 100d)); TimeSpan remaining = segmentsDuration - TimeSpan.FromSeconds(RunningJobProgress / (SelectedProcessParametersTable.DyeingSpeed / 100d)); if (remaining >= TimeSpan.Zero) { segment.RemainingTime = remaining; } if (remaining < segmentDuration) { segment.Started = true; } if (remaining <= TimeSpan.Zero) { segment.Completed = true; segment.Started = false; } } }; _jobHandler.Failed += (x, ex) => { FailJob(); InvokeUI(() => { _notification.ShowError("Job failed. " + ex.Message); }); }; _jobHandler.Completed += (x, e) => { CompleteJob(); }; _jobHandler.Canceled += (x, y) => { //Finally Canceled.. }; } private void UpdateEstimatedDuration() { if (SelectedJob != null && SelectedProcessParametersTable != null && SelectedProcessParametersTable.DyeingSpeed > 0) { 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.ToList().SingleOrDefault(x => x.Active); _selectedGroupHistory = RmlProcessParametersTableGroup; 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(); RaisePropertyChangedAuto(nameof(SelectedGroupHistory)); } } /// /// 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 async void RemoveJob() { if (SelectedMachine != null && SelectedJob != null) { if (_notification.ShowQuestion("Are you sure you want to delete the selected jobs?")) { SelectedJobs.ToList().ForEach(x => { x.DefferedDelete(); }); await SelectedMachine.SaveAsync(); } } } /// /// Adds a new job to the selected machine. /// private void AddJob() { if (SelectedMachine != null) { String jobName = _notification.ShowTextInput("Please provide a job name", "Name"); if (!String.IsNullOrWhiteSpace(jobName)) { Job newJob = new Job(); newJob.Name = jobName; newJob.CreationDate = DateTime.UtcNow; newJob.User = _authentication.CurrentUser; newJob.Rml = Adapter.Rmls.FirstOrDefault(); SelectedJob = newJob; LoadJob(); } } } /// /// Removes the selected brush stop. /// private void RemoveBrushStop() { if (SelectedBrushStop != null && SelectedSegment != null) { SelectedSegment.BrushStops.Remove(SelectedBrushStop); if (SelectedSegment.BrushStops.Count > 1) { SelectedSegment.BrushStops.Last().OffsetPercent = 100; } SelectedSegment.BrushStops.ToList().ForEach(x => x.RaiseOffsetChanged()); } } /// /// Adds a new brush stop to the selected segment. /// private void AddBrushStop() { if (SelectedSegment != null) { var stop = new BrushStop(); stop.OffsetPercent = 100; stop.Segment = SelectedSegment; stop.ColorSpace = Adapter.ColorSpaces.FirstOrDefault(); stop.Color = Colors.Black; stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML, SelectedProcessParametersTable); SelectedSegment.BrushStops.Add(stop); SelectedSegment.BrushStops.ToList().ForEach(x => x.RaiseOffsetChanged()); } } private List CreateRunningJobEffectiveSegments(Job job) { List segments = new List(); foreach (var s in job.Segments) { s.Completed = false; s.Started = false; segments.Add(s); if (job.EnableInterSegment && job.Segments.IndexOf(s) != job.Segments.Count - 1) { segments.Add(new Segment() { Length = job.InterSegmentLength, BrushStops = new System.Collections.ObjectModel.ObservableCollection() { new BrushStop() { Color = Colors.White, } }, Started = false, Completed = false }); } } return segments; } #endregion #region Override Methods protected override void RaisePropertyChangedAuto([CallerMemberName] string caller = null) { base.RaisePropertyChangedAuto(caller); if (!_blockInvalidateCommands) { InvalidateRelayCommands(); } } #endregion #region Public Methods /// /// Add sensor graph from available sensors to displayed graphs. /// /// The sensor. public void OnDropAvailableGraph(TechMonitor 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++) { var randomColor = new SolidColorBrush(Core.Helpers.ColorHelper.GetRandomColor()); (controller as GraphMultiController).AddSeries(new DataYSeries() { Name = sensor.Description.First().ToString() + (i + 1), UseFillAndStroke = true, Stroke = randomColor }); } 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); }; graphControl.GraphFullScreenButtonPressed += (sender, _) => { StartFullScreenGraph(sender as IRealTimeGraph); }; Graphs.Add(graphControl); AvailableGraphs.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) { SelectedSegment.BrushStops.Swap(draggedStop, droppedStop); int tmpIndex = draggedStop.StopIndex; draggedStop.StopIndex = droppedStop.StopIndex; droppedStop.StopIndex = tmpIndex; if (SelectedSegment.BrushStops.Count > 1) { SelectedSegment.BrushStops.First().OffsetPercent = 0; SelectedSegment.BrushStops.Last().OffsetPercent = 100; } } /// /// Removes the graph. /// /// The graph. public void RemoveGraph(IRealTimeGraph graph) { var sensor = graph.Tag as TechMonitor; _controllers.Remove(sensor.Name); graph.InnerGraph.Dispose(); Graphs.Remove(graph); AvailableGraphs.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.LastSelectedJobGuid = SelectedJob != null ? SelectedJob.Guid : null; 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.LastSelectedJobGuid != null && SelectedMachine != null) { SelectedJob = SelectedMachine.Jobs.SingleOrDefault(x => x.Guid == SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedJobGuid); } } #endregion } }