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;
using System.ComponentModel;
using System.Windows.Data;
namespace Tango.MachineStudio.Developer.ViewModels
{
///
/// Represents the developer module main view, view model.
///
///
public class MainViewVM : ViewModel, IShutdownRequestBlocker
{
private static object _syncLock = new object();
private INotificationProvider _notification;
private TimeSpan _runningJobEstimatedDuration;
private JobHandler _jobHandler;
private DeveloperNavigationManager _navigation;
private ObservablesContext _dbJobContext;
private bool _blockInvalidateCommands;
private IAuthenticationProvider _authentication;
private ObservablesContext _machineDBContext;
#region Properties
private ObservableCollection _machines;
///
/// Gets or sets the machines.
///
public ObservableCollection Machines
{
get { return _machines; }
set { _machines = value; RaisePropertyChangedAuto(); }
}
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(); }
}
private ObservableCollection _windingMethods;
public ObservableCollection WindingMethods
{
get { return _windingMethods; }
set { _windingMethods = 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; }
protected Machine _selectedMachine;
///
/// Gets or sets the selected machine.
///
public Machine SelectedMachine
{
get { return _selectedMachine; }
set
{
_selectedMachine = value;
OnSelectedMachineChanged();
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(); }
}
public void OnDropSegment(Segment dragged, Segment dropped)
{
dragged.SegmentIndex = dropped.SegmentIndex;
dropped.SegmentIndex++;
int index = 1;
foreach (var segment in ActiveJob.Segments.OrderBy(x => x.SegmentIndex))
{
segment.SegmentIndex = index++;
}
SegmentsCollectionView.Refresh();
}
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 _activeJob;
///
/// Gets or sets the selected machine job.
///
public Job ActiveJob
{
get { return _activeJob; }
set
{
_activeJob = value;
RaisePropertyChangedAuto();
OnActiveJobChanged();
}
}
private Job _selectedMachineJob;
///
/// Gets or sets the selected machine job.
///
public Job SelectedMachineJob
{
get { return _selectedMachineJob; }
set { _selectedMachineJob = 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 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(); }
}
private ICollectionView _jobsCollectionView;
///
/// Gets or sets the jobs collection view.
///
public ICollectionView JobsCollectionView
{
get { return _jobsCollectionView; }
set
{
_jobsCollectionView = value;
BindingOperations.EnableCollectionSynchronization(_jobsCollectionView, _syncLock);
RaisePropertyChangedAuto();
}
}
private ICollectionView _segmentsCollectionView;
///
/// Gets or sets the segments collection view.
///
public ICollectionView SegmentsCollectionView
{
get { return _segmentsCollectionView; }
set
{
_segmentsCollectionView = value;
BindingOperations.EnableCollectionSynchronization(_segmentsCollectionView, _syncLock);
RaisePropertyChangedAuto();
}
}
private ICollectionView _brushStopsCollectionView;
///
/// Gets or sets the brush stops collection view.
///
public ICollectionView BrushStopsCollectionView
{
get { return _brushStopsCollectionView; }
set
{
_brushStopsCollectionView = value;
BindingOperations.EnableCollectionSynchronization(_brushStopsCollectionView, _syncLock);
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 load job command.
///
public RelayCommand LoadJobCommand { get; set; }
///
/// Gets or sets the duplicate job command.
///
public RelayCommand DuplicateJobCommand { get; set; }
///
/// Gets or sets the duplicate segment command.
///
public RelayCommand DuplicateSegmentCommand { get; set; }
///
/// Gets or sets the duplicate brush stop command.
///
public RelayCommand DuplicateBrushStopCommand { get; set; }
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
public MainViewVM() : base()
{
}
///
/// Initializes a new instance of the class.
///
/// The application manager.
/// The notification provider.
[PreferredConstructor]
public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IDiagnosticsFrameProvider diagnosticsFrameProvider, IVideoCaptureProvider videoCaptureProvider, DeveloperNavigationManager navigation, IAuthenticationProvider authentication) : this()
{
using (var db = ObservablesContext.CreateDefault())
{
Machines = db.Machines.ToObservableCollection();
}
_machineDBContext = ObservablesContext.CreateDefault();
SelectedJobs = new ObservableCollection();
_authentication = authentication;
_notification = notificationProvider;
_navigation = navigation;
ApplicationManager = applicationManager;
VideoCaptureProvider = videoCaptureProvider;
//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, () => ActiveJob != null);
RemoveSegmentCommand = new RelayCommand(RemoveSelectedSegments, () => SelectedSegment != null);
AddJobCommand = new RelayCommand(AddJob, () => SelectedMachine != null);
RemoveJobCommand = new RelayCommand(RemoveSelectedJobs, () => SelectedMachineJob != null);
AddBrushStopCommand = new RelayCommand(AddBrushStop, () => SelectedSegment != null);
RemoveBrushStopCommand = new RelayCommand(RemoveSelectedBrushStops, () => SelectedBrushStop != null);
SaveJobCommand = new RelayCommand(SaveJob, () => SelectedMachine != null);
DiscardJobCommand = new RelayCommand(DiscardJob, () => SelectedMachine != null);
StartJobCommand = new RelayCommand(StartJob, () => ActiveJob != null && !IsJobRunning);
StopJobCommand = new RelayCommand(StopJob, () => IsJobRunning);
CloseJobCompletionStatusCommand = new RelayCommand(CloseJobCompletionStatusBar);
LoadJobCommand = new RelayCommand(LoadJob, () => SelectedMachineJob != null);
DuplicateJobCommand = new RelayCommand(DuplicateSelectedJobs, () => SelectedMachineJob != null);
DuplicateSegmentCommand = new RelayCommand(DuplicateSelectedSegments, () => SelectedSegment != null);
DuplicateBrushStopCommand = new RelayCommand(DuplicateSelectedBrushStops, () => SelectedBrushStop != null);
ApplicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged;
}
#endregion
#region Event Handlers
///
/// 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(_machineDBContext);
}
///
/// Handles the LengthChanged event of the SelectedJob.
///
/// The source of the event.
/// The instance containing the event data.
private void ActiveJob_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);
UpdateEstimatedDuration();
}
///
/// 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();
BrushStopsCollectionView = CollectionViewSource.GetDefaultView(SelectedSegment.BrushStops);
BrushStopsCollectionView.SortDescriptions.Add(new SortDescription(nameof(BrushStop.StopIndex), ListSortDirection.Ascending));
}
}
///
/// 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 OnSelectedMachineChanged()
{
if (SelectedMachine != null)
{
ReloadMachine();
JobsCollectionView = CollectionViewSource.GetDefaultView(SelectedMachine.Jobs);
JobsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Job.LastUpdated), ListSortDirection.Descending));
InvalidateLiquidFactorsAndProcessTables();
}
}
private void ReloadMachine()
{
_machineDBContext.Dispose();
_machineDBContext = ObservablesContext.CreateDefault();
_machineDBContext.Configuration.LazyLoadingEnabled = true;
_selectedMachine = _machineDBContext.Machines.SingleOrDefault(x => x.Guid == _selectedMachine.Guid);
RaisePropertyChanged(nameof(SelectedMachine));
JobsCollectionView = CollectionViewSource.GetDefaultView(SelectedMachine.Jobs);
JobsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Job.LastUpdated), ListSortDirection.Descending));
}
#endregion
#region Private Methods
private void OnActiveJobChanged()
{
if (ActiveJob != null)
{
SegmentsCollectionView = CollectionViewSource.GetDefaultView(ActiveJob.Segments);
SegmentsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Segment.SegmentIndex), ListSortDirection.Ascending));
}
}
private void LoadJob()
{
if (SelectedMachineJob != 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();
WindingMethods = _dbJobContext.WindingMethods.ToObservableCollection();
_activeJob = _dbJobContext.Jobs.SingleOrDefault(x => x.Guid == SelectedMachineJob.Guid);
_selectedRML = ActiveJob.Rml;
_selectedSegment = ActiveJob.Segments.FirstOrDefault();
ActiveJob.LengthChanged -= ActiveJob_LengthChanged;
ActiveJob.LengthChanged += ActiveJob_LengthChanged;
ActiveJob = _activeJob;
SelectedRML = _selectedRML;
SelectedSegment = _selectedSegment;
UpdateEstimatedDuration();
_blockInvalidateCommands = false;
InvalidateRelayCommands();
InvokeUI(() => _navigation.NavigateTo(DeveloperNavigationView.JobView));
//});
}
}
}
private async void SaveJob()
{
if (ActiveJob != null)
{
using (_notification.PushTaskItem("Saving job to database..."))
{
ActiveJob.LastUpdated = DateTime.UtcNow;
ActiveJob.Rml = SelectedRML;
await ActiveJob.SaveAsync(_dbJobContext);
ReloadMachine();
SelectedMachineJob = SelectedMachine.Jobs.SingleOrDefault(x => x.Guid == ActiveJob.Guid);
}
}
}
private void DiscardJob()
{
bool jobModified = !ActiveJob.CompareUsingJson(SelectedMachineJob);
if (jobModified)
{
if (_notification.ShowQuestion("This will discard the current job changes. Are you sure?"))
{
_dbJobContext.Dispose();
_navigation.NavigateTo(DeveloperNavigationView.MachineJobSelectionView);
}
}
else
{
_dbJobContext.Dispose();
_navigation.NavigateTo(DeveloperNavigationView.MachineJobSelectionView);
}
}
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 = ActiveJob;
_runningJobEstimatedDuration = EstimatedDuration;
RunningJobSegments = CreateRunningJobEffectiveSegments(RunningJob);
_navigation.NavigateTo(DeveloperNavigationView.RunningJobView);
_jobHandler = MachineOperator.Print(ActiveJob, 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 (ActiveJob != null && SelectedProcessParametersTable != null && SelectedProcessParametersTable.DyeingSpeed > 0)
{
EstimatedDuration = TimeSpan.FromSeconds(ActiveJob.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;
}
SelectedRML.ProcessParametersTablesGroups.Add(group);
await SelectedRML.SaveAsync();
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));
}
}
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 Add / Remove / Duplicate Jobs, Segments & Brush Stops
private void ArrangeSegmentsIndices()
{
int index = 1;
foreach (var segment in ActiveJob.Segments.OrderBy(x => x.SegmentIndex))
{
segment.SegmentIndex = index++;
}
SegmentsCollectionView.Refresh();
}
private void ArrangeBrushStopsIndices()
{
int index = 0;
foreach (var stop in SelectedSegment.BrushStops.OrderBy(x => x.StopIndex))
{
stop.SetStopIndex(index++);
}
if (SelectedSegment.BrushStops.Count > 1)
{
SelectedSegment.BrushStops.OrderBy(x => x.StopIndex).First().OffsetPercent = 0;
SelectedSegment.BrushStops.OrderBy(x => x.StopIndex).Last().OffsetPercent = 100;
}
foreach (var stop in SelectedSegment.BrushStops.OrderBy(x => x.StopIndex))
{
stop.RaiseStopIndex();
stop.RaiseOffsetChanged();
}
BrushStopsCollectionView.Refresh();
}
///
/// Removes the selected segments.
///
private void RemoveSelectedSegments()
{
if (ActiveJob != null && SelectedSegment != null)
{
if (_notification.ShowQuestion("Are you sure you want to delete the selected segments?"))
{
SelectedSegments.ToList().ForEach(x =>
{
ActiveJob.Segments.Remove(x);
x.DefferedDelete(_dbJobContext);
});
ArrangeSegmentsIndices();
}
}
}
///
/// Adds a new segment.
///
private void AddSegment()
{
if (ActiveJob != null)
{
Segment seg = new Segment();
seg.Name = "Untitled Segment";
seg.Length = 10;
if (ActiveJob.Segments.Count > 0)
{
seg.SegmentIndex = ActiveJob.Segments.Max(x => x.SegmentIndex) + 1;
}
else
{
seg.SegmentIndex = 1;
}
ActiveJob.Segments.Add(seg);
SelectedSegment = seg;
AddBrushStop();
ArrangeSegmentsIndices();
}
}
///
/// Removes the selected jobs.
///
private async void RemoveSelectedJobs()
{
if (SelectedMachine != null && SelectedMachineJob != null)
{
if (_notification.ShowQuestion("Are you sure you want to delete the selected jobs?"))
{
SelectedJobs.ToList().ForEach(x =>
{
SelectedMachine.Jobs.Remove(x);
x.DefferedDelete(_machineDBContext);
});
using (_notification.PushTaskItem("Removing selected jobs..."))
{
await SelectedMachine.SaveAsync(_machineDBContext);
}
}
}
}
///
/// Adds a new job to the selected machine.
///
private async 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 = _machineDBContext.Rmls.FirstOrDefault();
newJob.WindingMethod = _machineDBContext.WindingMethods.FirstOrDefault();
newJob.Machine = SelectedMachine;
SelectedMachine.Jobs.Add(newJob);
await SelectedMachine.SaveAsync(_machineDBContext);
SelectedMachineJob = newJob;
LoadJob();
AddSegment();
}
}
}
///
/// Removes the selected brush stop.
///
private void RemoveSelectedBrushStops()
{
if (SelectedBrushStop != null && SelectedSegment != null)
{
if (_notification.ShowQuestion("Are you sure you want to delete the selected colors?"))
{
SelectedBrushStops.ToList().ForEach(x =>
{
SelectedSegment.BrushStops.Remove(x);
x.DefferedDelete(_dbJobContext);
});
ArrangeBrushStopsIndices();
}
}
}
///
/// Adds a new brush stop to the selected segment.
///
private void AddBrushStop()
{
if (SelectedSegment != null)
{
var stop = new BrushStop();
if (SelectedSegment.BrushStops.Count > 0)
{
stop.StopIndex = SelectedSegment.BrushStops.Max(x => x.StopIndex) + 1;
}
else
{
stop.StopIndex = 0;
}
stop.OffsetPercent = 100;
stop.Segment = SelectedSegment;
stop.ColorSpace = _dbJobContext.ColorSpaces.FirstOrDefault();
stop.Color = Colors.Black;
stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML, SelectedProcessParametersTable);
SelectedSegment.BrushStops.Add(stop);
SelectedSegment.BrushStops.ToList().ForEach(x => x.RaiseOffsetChanged());
ArrangeBrushStopsIndices();
}
}
///
/// Duplicates the selected brush stops.
///
private void DuplicateSelectedBrushStops()
{
foreach (var stop in SelectedBrushStops.OrderBy(x => x.StopIndex))
{
var cloned = stop.Clone();
cloned.StopIndex = SelectedSegment.BrushStops.Max(x => x.StopIndex) + 1;
SelectedSegment.BrushStops.Add(cloned);
}
ArrangeBrushStopsIndices();
}
///
/// Duplicates the selected segments.
///
private void DuplicateSelectedSegments()
{
foreach (var segment in SelectedSegments.OrderBy(x => x.SegmentIndex))
{
var cloned = segment.Clone();
cloned.SegmentIndex = ActiveJob.Segments.Max(x => x.SegmentIndex) + 1;
ActiveJob.Segments.Add(cloned);
}
ArrangeSegmentsIndices();
}
///
/// Duplicates the selected jobs.
///
private async void DuplicateSelectedJobs()
{
if (SelectedMachineJob != null)
{
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(_machineDBContext);
}
}
}
#endregion
#region Override Methods
protected override void RaisePropertyChangedAuto([CallerMemberName] string caller = null)
{
base.RaisePropertyChangedAuto(caller);
if (!_blockInvalidateCommands)
{
InvalidateRelayCommands();
}
}
#endregion
#region Public Methods
///
/// Switch the brush stop position in the segment.
///
/// The dragged stop.
/// The dropped stop.
public void OnDropBrushStop(BrushStop draggedStop, BrushStop droppedStop)
{
draggedStop.SetStopIndex(droppedStop.StopIndex);
droppedStop.SetStopIndex(droppedStop.StopIndex + 1);
ArrangeBrushStopsIndices();
}
#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 = ActiveJob != null ? ActiveJob.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)
// //{
// // ActiveJob = SelectedMachine.Jobs.SingleOrDefault(x => x.Guid == SettingsManager.Default.MachineStudio.DeveloperModule.LastSelectedJobGuid);
// //}
//}
#endregion
}
}