using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Data;
using System.Windows.Media;
using Tango.Core.Commands;
using Tango.BL.Entities;
using Tango.Integration.Operation;
using Tango.Integration.ExternalBridge;
using Tango.Logging;
using Tango.MachineStudio.Common.Authentication;
using Tango.MachineStudio.Common.Controls;
using Tango.MachineStudio.Common.Diagnostics;
using Tango.MachineStudio.Common.Notifications;
using Tango.MachineStudio.Common.StudioApplication;
using Tango.MachineStudio.Common.Video;
using Tango.MachineStudio.Developer.Navigation;
using Tango.MachineStudio.Developer.Views;
using Tango.Settings;
using Tango.SharedUI;
using Tango.Transport;
using Tango.BL;
using Microsoft.Win32;
using Tango.PMR.Embroidery;
using Tango.EmbroideryUI;
using System.IO;
using System.Windows;
using Tango.Core.Helpers;
using System.Speech.Synthesis;
using System.Media;
using Tango.MachineStudio.Common.EventLogging;
using Tango.MachineStudio.Common.Speech;
using System.Threading;
using Tango.SharedUI.Helpers;
using Tango.Core.DI;
using Tango.MachineStudio.Common;
using Tango.BL.ColorConversion;
using Tango.MachineStudio.Logging.ViewModels;
using Tango.MachineStudio.Logging.Views;
using Tango.AutoComplete.Editors;
using System.Data.Entity;
using System.Runtime.ExceptionServices;
using Tango.BL.Builders;
using Tango.MachineStudio.Common.Navigation;
using System.Diagnostics;
namespace Tango.MachineStudio.Developer.ViewModels
{
///
/// Represents the developer module main view, view model.
///
///
[TangoCreateWhenRegistered]
public class MainViewVM : StudioViewModel
{
private static object _syncLock = new object();
private const string EMB_FORMATS_EXPORT = "Baby Lock (PES)|*.pes|Tajima (DST)|*.dst|EXP|*.exp|PCS|*.pcs|HUS|*.hus|KSM|*.ksm";
private const string EMB_FORMATS_IMPORT = "Embroidery Files|*.pes;*.hus;*.dst";
private INotificationProvider _notification;
private TimeSpan _runningJobEstimatedDuration;
private DeveloperNavigationManager _navigation;
private INavigationManager _msNavigation;
private bool _blockInvalidateCommands;
private ObservablesContext _machineDbContext;
private ObservablesContext _activeJobDbContext;
private IEventLogger _eventLogger;
private ISpeechProvider _speech;
private DataCapture.ViewModels.MainViewVM _dataCaptureVM;
private bool _isRecording;
private DeveloperModuleSettings _settings;
private Thread _colorConversionThread;
private bool _hiveOpened;
private bool _color_changed_from_hive;
private bool _dialog_shown;
private bool _disable_gamut_check;
private bool _rml_has_no_cct;
private TaskItem _preparingTaskItem;
#region Properties
private List _hiveSuggestions;
///
/// Gets or sets the hive suggestions.
///
public List HiveSuggestions
{
get { return _hiveSuggestions; }
set { _hiveSuggestions = value; RaisePropertyChangedAuto(); }
}
private ColorConversionSuggestion _selectedSuggestion;
///
/// Gets or sets the selected suggestion.
///
public ColorConversionSuggestion SelectedSuggestion
{
get { return _selectedSuggestion; }
set { _selectedSuggestion = value; RaisePropertyChangedAuto(); OnSelectedSuggestionChanged(); }
}
private RunningJobStatus _runningJobStatus;
///
/// Gets or sets the running job status.
///
public RunningJobStatus RunningJobStatus
{
get { return _runningJobStatus; }
set { _runningJobStatus = value; RaisePropertyChangedAuto(); }
}
private JobHandler _jobHandler;
///
/// Gets or sets the current running job handler.
///
public JobHandler JobHandler
{
get
{
return _jobHandler;
}
set
{
_jobHandler = 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;
///
/// Gets or sets the winding methods.
///
public ObservableCollection WindingMethods
{
get { return _windingMethods; }
set { _windingMethods = value; RaisePropertyChangedAuto(); }
}
private ObservableCollection _spoolTypes;
///
/// Gets or sets the spool types.
///
public ObservableCollection SpoolTypes
{
get { return _spoolTypes; }
set { _spoolTypes = 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
{
if (value != null && _selectedMachine != value)
{
_selectedMachine = value;
OnSelectedMachineChanged();
RaisePropertyChangedAuto();
InvalidateRelayCommands();
if (_selectedMachine != null)
{
_selectedMachine.Modified -= SelectedMachine_Modified;
_selectedMachine.Modified += SelectedMachine_Modified;
}
}
}
}
private bool _canWork;
///
/// Gets or sets a value indicating whether this instance is loading machine.
///
public bool CanWork
{
get { return _canWork; }
set { _canWork = value; RaisePropertyChangedAuto(); }
}
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 _activeJob;
///
/// Gets or sets the selected machine job.
///
public Job ActiveJob
{
get { return _activeJob; }
set
{
_activeJob = value;
RaisePropertyChangedAuto();
}
}
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;
OnSelectedRMLChanged();
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 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 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;
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();
}
}
private String _jobFilter;
///
/// Gets or sets the job filter.
///
public String JobFilter
{
get { return _jobFilter; }
set { _jobFilter = value; RaisePropertyChangedAuto(); OnJobFilterChanged(); }
}
private ObservableCollection _jobEvents;
///
/// Gets or sets the running job events.
///
public ObservableCollection JobEvents
{
get { return _jobEvents; }
set { _jobEvents = value; RaisePropertyChangedAuto(); }
}
private MachinesEvent _selectedJobEvent;
///
/// Gets or sets the selected job event.
///
public MachinesEvent SelectedJobEvent
{
get { return _selectedJobEvent; }
set { _selectedJobEvent = value; RaisePropertyChangedAuto(); OnSelectedJobEventChanged(); }
}
///
/// Gets or sets the machines providers.
///
public ISuggestionProvider MachinesProvider { get; set; }
///
/// Gets or sets a value indicating whether the job details view is visible.
///
public bool IsJobVisible { get; set; }
private bool _enableColorConversion;
///
/// Gets or sets a value indicating whether to enable color conversion processes.
///
public bool EnableColorConversion
{
get { return _enableColorConversion; }
set { _enableColorConversion = value; RaisePropertyChangedAuto(); }
}
public IAuthenticationProvider AuthenticationProvider { get; set; }
#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 start job and record command.
///
public RelayCommand StartJobAndRecordCommand { 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; }
///
/// Gets or sets the push process parameters command.
///
public RelayCommand PushProcessParametersCommand { get; set; }
///
/// Gets or sets the import embroidery file command.
///
public RelayCommand ImportEmbroideryFileCommand { get; set; }
///
/// Gets or sets the display job embroidery file command.
///
public RelayCommand DisplayJobEmbroideryFileCommand { get; set; }
///
/// Gets or sets the reload machines command.
///
public RelayCommand ReloadMachinesCommand { get; set; }
///
/// Gets or sets the back to job command.
///
public RelayCommand BackToJobCommand { get; set; }
///
/// Gets or sets to running job command.
///
public RelayCommand ToRunningJobCommand { get; set; }
///
/// Gets or sets the reset process parameters command.
///
public RelayCommand ResetProcessParametersCommand { get; set; }
#endregion
#region Constructors
///
/// Initializes a new instance of the class.
///
/// The application manager.
/// The notification provider.
public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IDiagnosticsFrameProvider diagnosticsFrameProvider, IVideoCaptureProvider videoCaptureProvider, DeveloperNavigationManager navigation, INavigationManager navigationManager, IAuthenticationProvider authentication, IEventLogger eventLogger, ISpeechProvider speech)
{
CanWork = true;
EnableColorConversion = true;
AuthenticationProvider = authentication;
_notification = notificationProvider;
_speech = speech;
_navigation = navigation;
_msNavigation = navigationManager;
ApplicationManager = applicationManager;
VideoCaptureProvider = videoCaptureProvider;
_eventLogger = eventLogger;
LogManager.Log("Initializing relay commands...");
TangoIOC.Default.GetInstanceWhenAvailable((vm) =>
{
_dataCaptureVM = vm;
_dataCaptureVM.RelayCommandsInvalidated += (_, __) => StartJobAndRecordCommand.RaiseCanExecuteChanged();
});
//Initialize Commands...
EditMachineCommand = new RelayCommand(EditMachine, () => SelectedMachine != null && CanWork);
EditRMLCommand = new RelayCommand(EditRML, () => SelectedRML != null && CanWork);
ToggleSideBarCommand = new RelayCommand(() => IsSideBarOpened = !IsSideBarOpened);
SaveLiquidFactorsCommand = new RelayCommand(SaveLiquidFactors, () => SelectedRML != null && CanWork);
AddSegmentCommand = new RelayCommand(AddSegment, () => ActiveJob != null && CanWork);
RemoveSegmentCommand = new RelayCommand(RemoveSelectedSegments, () => SelectedSegment != null && CanWork);
AddJobCommand = new RelayCommand(AddJob, () => SelectedMachine != null && CanWork);
RemoveJobCommand = new RelayCommand(RemoveSelectedJobs, () => SelectedMachineJob != null && CanWork);
AddBrushStopCommand = new RelayCommand(AddBrushStop, () => SelectedSegment != null && CanWork);
RemoveBrushStopCommand = new RelayCommand(RemoveSelectedBrushStops, () => SelectedBrushStop != null && CanWork);
SaveJobCommand = new RelayCommand(SaveActiveJob, () => SelectedMachine != null && CanWork);
DiscardJobCommand = new RelayCommand(BackToJobs, () => SelectedMachine != null && CanWork);
StartJobCommand = new RelayCommand(() => StartJob(), () => ActiveJob != null && CanWork && !IsJobRunning && MachineOperator != null);
StartJobAndRecordCommand = new RelayCommand(StartJobAndRecord, () => _dataCaptureVM != null && !_dataCaptureVM.Recorder.IsRecording && !_dataCaptureVM.Player.IsPlaying && ActiveJob != null && !IsJobRunning && MachineOperator != null && CanWork);
StopJobCommand = new RelayCommand(StopJob, () => IsJobRunning && CanWork);
CloseJobCompletionStatusCommand = new RelayCommand(CloseJobCompletionStatusBar);
LoadJobCommand = new RelayCommand(() => LoadSelectedJob(), () => SelectedMachineJob != null && CanWork);
DuplicateJobCommand = new RelayCommand(DuplicateSelectedJobs, () => SelectedMachineJob != null && CanWork);
DuplicateSegmentCommand = new RelayCommand(DuplicateSelectedSegments, () => SelectedSegment != null && CanWork);
DuplicateBrushStopCommand = new RelayCommand(DuplicateSelectedBrushStops, () => SelectedBrushStop != null && CanWork);
SaveProcessParametersCommand = new RelayCommand(SaveProcessParameters, () => SelectedRML != null && CanWork && SelectedRML.ProcessParametersTablesGroups.Count > 0);
PushProcessParametersCommand = new RelayCommand(PushProcessParameters, () => SelectedRML != null && CanWork && SelectedRML.ProcessParametersTablesGroups.Count > 0 && SelectedProcessParametersTable != null && MachineOperator != null);
ImportEmbroideryFileCommand = new RelayCommand(ImportEmbroideryFile, () => SelectedMachine != null && CanWork);
DisplayJobEmbroideryFileCommand = new RelayCommand(DisplayJobEmbroideryFile, () => CanWork);
ReloadMachinesCommand = new RelayCommand(() => LoadMachine(), () => CanWork && SelectedMachine != null);
ResetProcessParametersCommand = new RelayCommand(ResetProcessParameters, () => CanWork && MachineOperator != null);
ApplicationManager.ConnectedMachineChanged += ApplicationManager_ConnectedMachineChanged;
_eventLogger.NewLog += _eventLogger_NewLog;
MachinesProvider = new SuggestionProvider((filter) =>
{
try
{
return _machineDbContext.Machines.Where(x => x.SerialNumber.StartsWith(filter)).ToList();
}
catch
{
return null;
}
});
BackToJobCommand = new RelayCommand(BackToJob);
ToRunningJobCommand = new RelayCommand(ToRunningJob);
}
#endregion
#region Application Ready
public override void OnApplicationReady()
{
_settings = SettingsManager.Default.GetOrCreate();
SelectedJobs = new ObservableCollection();
JobEvents = new ObservableCollection();
LogManager.Log("Initializing machine Db context...");
_machineDbContext = ObservablesContext.CreateDefault();
if (_settings.LastSelectedMachineGuid != null)
{
LogManager.Log("Setting last selected machine from settings...");
SelectedMachine = _machineDbContext.Machines.SingleOrDefault(x => x.Guid == _settings.LastSelectedMachineGuid);
}
if (_settings.LastSelectedJobGuid != null && SelectedMachine != null)
{
LogManager.Log("Setting last selected job from settings...");
SelectedMachineJob = SelectedMachine.Jobs.SingleOrDefault(x => x.Guid == _settings.LastSelectedJobGuid);
}
_colorConversionThread = new Thread(ColorConversionThreadMethod);
_colorConversionThread.IsBackground = true;
_colorConversionThread.Start();
}
#endregion
#region Color Conversion
[HandleProcessCorruptedStateExceptions]
private void ColorConversionThreadMethod()
{
while (true)
{
if (!_rml_has_no_cct && EnableColorConversion && !_disable_gamut_check && IsJobVisible && IsVisible && ActiveJob != null && ActiveJob.Segments != null)
{
try
{
var stops = ActiveJob.Segments.SelectMany(x => x.BrushStops).Where(x => !x.Corrected && !x.OutOfGamutChecked).ToList();
foreach (var stop in stops)
{
if (stop.ColorSpace.Code == BL.Enumerations.ColorSpaces.Volume.ToInt32() && !stop.IsLiquidVolumesOutOfRange)
{
try
{
var output = TangoColorConverter.GetSuggestions(stop);
stop.Red = output.SingleCoordinates.Red;
stop.Green = output.SingleCoordinates.Green;
stop.Blue = output.SingleCoordinates.Blue;
stop.Corrected = true;
stop.IsOutOfGamut = false;
}
catch { }
}
else if (stop.ColorSpace.Code == BL.Enumerations.ColorSpaces.RGB.ToInt32() || stop.ColorSpace.Code == BL.Enumerations.ColorSpaces.LAB.ToInt32())
{
try
{
stop.IsOutOfGamut = TangoColorConverter.IsOutOfGamut(stop);
stop.OutOfGamutChecked = true;
}
catch { }
}
}
}
catch { }
}
Thread.Sleep(500);
}
}
public void OnHivePopupOpened()
{
if (SelectedBrushStop != null)
{
_hiveOpened = true;
try
{
HiveSuggestions = TangoColorConverter.CreateHiveSuggestions(TangoColorConverter.GetSuggestions(SelectedBrushStop));
}
catch (Exception ex)
{
_hiveOpened = false;
LogManager.Log(ex);
_notification.ShowError($"Error occurred while trying to convert the source color.\n{ex.Message}");
}
}
}
private void OnSelectedSuggestionChanged()
{
if (SelectedSuggestion != null && SelectedBrushStop != null && _hiveOpened)
{
_color_changed_from_hive = true;
SelectedBrushStop.Color = SelectedSuggestion.Color;
SelectedBrushStop.Corrected = true;
SelectedBrushStop.IsOutOfGamut = false;
var coords = SelectedSuggestion.Coordinates;
foreach (var liquid in coords.OutputLiquids)
{
var liquidVolume = SelectedBrushStop.LiquidVolumes.SingleOrDefault(x => x.IdsPack.LiquidType.Code == liquid.LiquidType.ToInt32());
if (liquidVolume != null)
{
liquidVolume.Volume = liquid.Volume;
}
}
_color_changed_from_hive = false;
}
}
public void OnSelectedBrushColorChanged(Color color)
{
if (!_color_changed_from_hive && _hiveOpened)
{
SelectedBrushStop.Corrected = false;
HiveSuggestions = TangoColorConverter.CreateHiveSuggestions(TangoColorConverter.GetSuggestions(SelectedBrushStop));
}
}
public void OnHivePopupClosed()
{
_hiveOpened = false;
}
///
/// Called when the brush stop field value has been changed (This called from the view!).
///
/// The brush stop.
public void OnBrushStopFieldValueChanged(BrushStop brushStop)
{
brushStop.Corrected = false;
brushStop.OutOfGamutChecked = false;
}
#endregion
#region Event Handlers
private void _eventLogger_NewLog(object sender, MachinesEvent e)
{
if (IsJobRunning)
{
InvokeUI(() =>
{
JobEvents.Insert(0, e);
});
}
}
///
/// Handles the application manager connected machine changes event.
///
/// The sender.
/// The machine.
private void ApplicationManager_ConnectedMachineChanged(object sender, IExternalBridgeClient machine)
{
MachineOperator = machine;
if (MachineOperator != null)
{
MachineOperator.MachineEventsStateProvider.EventsChanged -= MachineEventsStateProvider_EventsChanged;
MachineOperator.MachineEventsStateProvider.EventsChanged += MachineEventsStateProvider_EventsChanged;
MachineOperator.MachineEventsStateProvider.NewEvents -= MachineEventsStateProvider_NewEvents;
MachineOperator.MachineEventsStateProvider.NewEvents += MachineEventsStateProvider_NewEvents;
MachineOperator.ResumingJob -= MachineOperator_ResumingJob;
MachineOperator.ResumingJob += MachineOperator_ResumingJob;
MachineOperator.PreparingJobProgress -= MachineOperator_PreparingJobProgress;
MachineOperator.PreparingJobProgress += MachineOperator_PreparingJobProgress;
}
}
private void MachineOperator_PreparingJobProgress(object sender, PreparingJobProgressEventArgs e)
{
var percent = (e.Progress / e.Total * 100d);
if (_preparingTaskItem == null && percent == 0)
{
_preparingTaskItem = _notification.PushTaskItem("Preparing job for printing...");
}
else if (percent == 100)
{
_preparingTaskItem.Pop();
_preparingTaskItem = null;
}
else
{
if (_preparingTaskItem != null)
{
_preparingTaskItem.Message = $"Preparing job for printing {(e.Progress / e.Total * 100d).ToString("0.0")}%...";
}
}
}
private void MachineOperator_ResumingJob(object sender, ResumingJobEventArgs e)
{
if (_notification.ShowQuestion("Machine studio has detected a job in progress. Would you like to try and continue from there you were?"))
{
var job = _machineDbContext.Jobs.SingleOrDefault(x => x.Guid == e.JobGuid);
if (job != null)
{
_msNavigation.NavigateToModule();
SelectedMachine = _machineDbContext.Machines.SingleOrDefault(x => x.Guid == job.MachineGuid);
SelectedMachineJob = SelectedMachine.Jobs.SingleOrDefault(x => x.Guid == job.Guid);
LoadSelectedJob(() =>
{
StartJob(e.Approve);
});
}
else
{
LogManager.Log($"Could not resume job. The running job with guid '{e.JobGuid}' was not found.");
_notification.ShowError("Could not resume job. The running job was not found.");
}
}
}
private void MachineEventsStateProvider_NewEvents(object sender, IEnumerable events)
{
HandleNewHardwareEvents(events);
}
private void MachineEventsStateProvider_EventsChanged(object sender, IEnumerable changedEvents)
{
InvokeUI(StartJobCommand.RaiseCanExecuteChanged);
InvokeUI(StartJobAndRecordCommand.RaiseCanExecuteChanged);
}
///
/// Handles the Saved event of the SelectedMachine.
///
/// The source of the event.
/// The instance containing the event data.
private void SelectedMachine_Modified(object sender, ObservableModifiedEventArgs e)
{
if (e.IsOtherContext)
{
InvokeUI(() =>
{
SelectedMachine.Reload(_machineDbContext);
InvalidateLiquidFactorsAndProcessTables();
if (SelectedSegment != null)
{
OnSelectedSegmentChanged();
}
});
}
}
///
/// 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 Hardware Events
private void HandleNewHardwareEvents(IEnumerable events)
{
if (IsJobRunning)
{
_speech.SpeakError(events.Last().EventType.Name);
//if (events.ToList().Exists(x => x.Actions.Contains(BL.Enumerations.EventTypeActions.StopJob)))
//{
// if (JobHandler != null)
// {
// InvokeUI(StopJob);
// }
//}
}
}
#endregion
#region Properties Changes
///
/// Called when the selected parameters table has changed.
///
protected virtual void OnSelectedParametersTableChanged()
{
if (SelectedProcessParametersTable != null)
{
LogManager.Log("Selected process parameters table changed.");
SelectedProcessParametersTable.DyeingSpeedMinInkUptakeChanged -= SelectedProcessParametersTable_DyeingSpeedMinInkUptakeChanged;
SelectedProcessParametersTable.DyeingSpeedMinInkUptakeChanged += SelectedProcessParametersTable_DyeingSpeedMinInkUptakeChanged;
foreach (var segment in ActiveJob.Segments)
{
SetSegmentBrushStopsLiquidVolumes(segment);
}
UpdateEstimatedDuration();
}
}
///
/// Called when the process parameters table group has been changed
///
protected virtual void OnProcessParametersTableGroupChanged()
{
if (RmlProcessParametersTableGroup != null && RmlProcessParametersTableGroup.ProcessParametersTables.Count > 0)
{
LogManager.Log("Process parameters group changed...");
InvokeUI(() =>
{
SelectedProcessParametersTable = RmlProcessParametersTableGroup.ProcessParametersTables.OrderBy(x => x.TableIndex).FirstOrDefault();
UpdateEstimatedDuration();
});
}
}
///
/// Called when the selected segment has been changed
///
protected virtual void OnSelectedSegmentChanged()
{
if (SelectedSegment != null)
{
LogManager.Log("Selected segment changed...");
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)
{
LogManager.Log(String.Format("Parameters group {0} selected from history.", SelectedGroupHistory.Name));
RmlProcessParametersTableGroup = SelectedGroupHistory.Clone();
}
}
///
/// Called when the machine has been changed
///
protected virtual void OnSelectedMachineChanged()
{
if (SelectedMachine != null)
{
LogManager.Log(String.Format("Machine {0} changed.", SelectedMachine.SerialNumber));
LoadMachine();
}
}
///
/// Called when the job filtering has changed.
///
protected virtual void OnJobFilterChanged()
{
String filter = JobFilter.ToLower();
JobsCollectionView.Filter = (job) =>
{
Job j = job as Job;
return String.IsNullOrWhiteSpace(filter)
||
j.Name.ToLower().Contains(filter) //Job name
||
j.User.Contact.FirstName.ToLower().Contains(filter) // User first name
||
j.Length.ToString().Contains(filter); //Job length
};
}
#endregion
#region Drag & Drop
///
/// Switch the segment position in the job.
///
/// The dragged.
/// The dropped.
public void OnDropSegment(Segment dragged, Segment dropped)
{
LogManager.Log(String.Format("Segment {0} Dropped on segment {1}", dragged.SegmentIndex, dropped.SegmentIndex));
dragged.SegmentIndex = dropped.SegmentIndex;
dropped.SegmentIndex++;
int index = 1;
foreach (var segment in ActiveJob.Segments.OrderBy(x => x.SegmentIndex))
{
segment.SegmentIndex = index++;
}
SegmentsCollectionView.Refresh();
}
///
/// Switch the brush stop position in the segment.
///
/// The dragged stop.
/// The dropped stop.
public void OnDropBrushStop(BrushStop dragged, BrushStop dropped)
{
LogManager.Log(String.Format("BrushStop {0} Dropped on BrushStop {1}", dragged.StopIndex, dropped.StopIndex));
dragged.SetStopIndex(dropped.StopIndex);
dropped.SetStopIndex(dropped.StopIndex + 1);
ArrangeBrushStopsIndices();
}
#endregion
#region Running Job Management
private void OnSelectedJobEventChanged()
{
if (SelectedJobEvent != null && SelectedJobEvent.Type != BL.Enumerations.EventTypes.APPLICATION_STARTED && !_dialog_shown)
{
_dialog_shown = true;
_notification.ShowModalDialog(new EventDetailsViewVM(SelectedJobEvent), (x) =>
{
}, () =>
{
_dialog_shown = false;
});
}
}
///
/// Closes the job completion status bar.
///
private void CloseJobCompletionStatusBar()
{
LogManager.Log("Closing job completion status bar...");
_navigation.NavigateTo(DeveloperNavigationView.JobView);
IsJobCompleted = false;
IsJobFailed = false;
IsJobCanceled = false;
ShowJobStatus = false;
RunningJob = null;
}
///
/// Stops the job.
///
private void StopJob()
{
LogManager.Log("Stopping job...");
IsJobRunning = false;
IsJobCanceled = true;
JobHandler.Cancel();
}
///
/// Fails the job.
///
private void SetJobFailed()
{
if (IsJobRunning)
{
LogManager.Log("Setting job failed state...");
IsJobRunning = false;
IsJobFailed = true;
_speech.SpeakError("Job Failed!");
}
}
///
/// Completes the job.
///
private void SetJobCompleted()
{
LogManager.Log("Setting job completed state...");
IsJobRunning = false;
IsJobCompleted = true;
_speech.SpeakInfo("Job Completed!");
}
///
/// Starts the job.
///
private async void StartJob(Func resumeFunc = null)
{
SettingsManager.Default.Save();
LogManager.Log(String.Format("Starting job {0}...", ActiveJob.Name));
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;
}
foreach (var stop in ActiveJob.Segments.SelectMany(x => x.BrushStops).Where(x => x.LiquidVolumes == null))
{
stop.SetLiquidVolumes(SelectedMachine.Configuration, SelectedRML, SelectedProcessParametersTable);
}
JobEvents.Clear();
IsJobFailed = false;
IsJobCanceled = false;
IsJobCompleted = false;
RunningJob = ActiveJob;
_runningJobEstimatedDuration = EstimatedDuration;
RunningJobSegments = RunningJob.EffectiveSegments.ToList();
try
{
IsFree = false;
LogManager.Log("Sending job to machine operator...");
if (resumeFunc == null)
{
JobHandler = await MachineOperator.Print(ActiveJob, SelectedProcessParametersTable);
}
else
{
JobHandler = resumeFunc(ActiveJob);
}
_navigation.NavigateTo(DeveloperNavigationView.RunningJobView);
IsJobRunning = true;
ShowJobStatus = true;
_eventLogger.Log(String.Format("Job '{0}' started...", ActiveJob.Name));
JobHandler.StatusChanged += (x, status) =>
{
if (IsJobRunning)
{
RunningJobStatus = status;
if (status.Message != null)
{
// TODO: Write to db when shlomo is not sending test messages anymore.
_eventLogger.Log(BL.Enumerations.EventTypes.JOB_STATUS, status.Message, false);
}
}
};
JobHandler.SegmentStarted += (x, segment) =>
{
if (!segment.IsInterSegment)
{
_speech.SpeakInfo(String.Format("Segment {0} Started.", segment.SegmentIndex));
_eventLogger.Log(String.Format("Segment {0} Started.", segment.SegmentIndex) + Environment.NewLine + segment.ToJsonString());
}
else
{
_speech.SpeakInfo(String.Format("Inter Segment Started."));
_eventLogger.Log("Inter Segment Started.");
}
};
JobHandler.UnitCompleted += (x, unit) =>
{
_speech.SpeakInfo(String.Format("{0} Units Completed.", unit + 1));
_eventLogger.Log(String.Format("{0} Units Completed.", unit + 1));
};
JobHandler.Failed += (x, ex) =>
{
LogManager.Log(ex, String.Format("Job {0} has failed.", RunningJob.Name));
_eventLogger.Log(ex, String.Format("Job {0} has failed.", RunningJob.Name));
SetJobFailed();
InvokeUI(() =>
{
_notification.ShowError("Job failed. " + ex.FlattenMessage());
StopRecordingIfInProgress();
});
};
JobHandler.Finalizing += (_, __) =>
{
_speech.SpeakInfo("Finalizing job...");
LogManager.Log(String.Format("Finalizing job {0}.", RunningJob.Name));
_eventLogger.Log(String.Format("Finalizing job {0}.", RunningJob.Name));
};
JobHandler.Completed += (x, e) =>
{
LogManager.Log(String.Format("Job {0} has completed.", RunningJob.Name));
_eventLogger.Log(String.Format("Job {0} has completed.", RunningJob.Name));
SetJobCompleted();
StopRecordingIfInProgress();
};
JobHandler.Canceled += (x, y) =>
{
if (_preparingTaskItem != null)
{
_preparingTaskItem.Pop();
_preparingTaskItem = null;
}
LogManager.Log(String.Format("Job {0} has been canceled.", RunningJob.Name));
_eventLogger.Log(String.Format("Job {0} has been canceled.", RunningJob.Name));
StopRecordingIfInProgress();
//Finally Canceled..
};
}
catch (Exception ex)
{
LogManager.Log(ex);
_eventLogger.Log(ex, "An error occurred while starting the job.");
_notification.ShowError("An error occurred while starting the job. " + Environment.NewLine + ex.Message);
SetJobFailed();
StopRecordingIfInProgress();
}
finally
{
IsFree = true;
}
}
///
/// Starts the job and record using the data capture module.
///
private void StartJobAndRecord()
{
_isRecording = true;
_dataCaptureVM.StartDiagnosticsRecording();
StartJob();
}
///
/// Stops the recording if in progress.
///
private void StopRecordingIfInProgress()
{
if (_isRecording)
{
_isRecording = false;
InvokeUI(() => _dataCaptureVM.StopRecorderOrPlayer());
}
}
private void BackToJob()
{
_navigation.NavigateTo(DeveloperNavigationView.JobView);
}
private void ToRunningJob()
{
_navigation.NavigateTo(DeveloperNavigationView.RunningJobView);
}
#endregion
#region RML
///
/// Saves the liquid factors.
///
private async void SaveLiquidFactors()
{
if (SelectedRML != null)
{
CanWork = false;
using (_notification.PushTaskItem("Saving Liquid Factors..."))
{
LogManager.Log(String.Format("Saving liquid factors for RML {0}...", SelectedRML.Name));
await SelectedRML.SaveAsync(_activeJobDbContext);
LiquidTypesRmls = ActiveJob.Machine.Configuration.GetSupportedIdsPacks(SelectedRML).Select(x => x.LiquidType).SelectMany(x => x.LiquidTypesRmls).Where(x => x.Rml.Guid == SelectedRML.Guid).ToList();
foreach (var segment in ActiveJob.Segments)
{
SetSegmentBrushStopsLiquidVolumes(segment);
}
}
CanWork = true;
}
}
///
/// Navigates to the DB Module in order to edit the selected RML.
///
private void EditRML()
{
LogManager.Log(String.Format("Requesting DB module for RML {0} editing...", SelectedRML.Name));
}
///
/// Invalidates the liquid factors and process parameters tables.
///
private void InvalidateLiquidFactorsAndProcessTables()
{
if (SelectedRML != null && SelectedMachine != null)
{
LogManager.Log("Invalidating liquid factors, process parameters and process group history...");
_selectedRML = new RmlBuilder(_activeJobDbContext).Set(SelectedRML).WithAllParametersGroup().WithCAT(SelectedMachine.Guid).WithCCT().WithLiquidFactors().Build();
if (_selectedRML.Ccts.Count == 0)
{
InvokeUI(() =>
{
_rml_has_no_cct = true;
_notification.ShowWarning(LogManager.Log($"No color conversion table defined for the selected RML '{_selectedRML.Name}'. Color conversion is disabled.", LogCategory.Warning));
});
}
else
{
_rml_has_no_cct = false;
}
LiquidTypesRmls = ActiveJob.Machine.Configuration.GetSupportedIdsPacks(SelectedRML).Select(x => x.LiquidType).SelectMany(x => x.LiquidTypesRmls).Where(x => x.Rml.Guid == SelectedRML.Guid).ToList();
RmlProcessParametersTableGroup = SelectedRML.ProcessParametersTablesGroups.ToList().SingleOrDefault(x => x.Active);
var selectedHistory = RmlProcessParametersTableGroup;
if (RmlProcessParametersTableGroup != null)
{
RmlProcessParametersTableGroup = RmlProcessParametersTableGroup.Clone();
RmlProcessParametersTableGroup.ProcessParametersTables = RmlProcessParametersTableGroup.ProcessParametersTables.OrderBy(x => x.TableIndex).ToSynchronizedObservableCollection();
}
GroupsHistory = SelectedRML.ProcessParametersTablesGroups.OrderByDescending(x => x.SaveDate).OrderBy(x => !x.Active).ToObservableCollection();
_selectedGroupHistory = selectedHistory;
InvokeUI(() =>
{
RaisePropertyChanged(nameof(SelectedGroupHistory));
RaisePropertyChanged(nameof(RmlProcessParametersTableGroup));
});
ActiveJob.Rml = SelectedRML;
}
}
private async void OnSelectedRMLChanged()
{
if (SelectedRML != null && SelectedMachine != null)
{
using (_notification.PushTaskItem("Loading RML..."))
{
await Task.Factory.StartNew(() =>
{
InvalidateLiquidFactorsAndProcessTables();
});
}
}
}
#endregion
#region Process Parameters Management
///
/// Uploads the selected process parameters table.
///
private async void PushProcessParameters()
{
using (_notification.PushTaskItem("Uploading Process Parameters..."))
{
try
{
LogManager.Log(String.Format("Uploading process parameters table {0}...", SelectedProcessParametersTable.Name));
await MachineOperator.UploadProcessParameters(SelectedProcessParametersTable);
}
catch (Exception ex)
{
LogManager.LogFormat(ex, "Failed to upload process parameters table {0}", SelectedProcessParametersTable.Name);
_notification.ShowError("Failed to upload the selected process parameters." + Environment.NewLine + ex.Message);
}
}
}
///
/// Saves the process parameters group.
///
private async void SaveProcessParameters()
{
var response = _notification.ShowTextInput("Enter Group Name", "Group Name");
if (response == null) return;
CanWork = false;
using (_notification.PushTaskItem("Saving Parameters Group..."))
{
using (var db = ObservablesContext.CreateDefault())
{
var active_groups = db.ProcessParametersTablesGroups.Where(x => x.RmlGuid == SelectedRML.Guid && x.Active).ToList();
foreach (var g in active_groups)
{
g.Active = false;
}
await db.SaveChangesAsync();
}
LogManager.Log(String.Format("Saving process parameters group under the name {0}...", response));
ProcessParametersTablesGroup group = new ProcessParametersTablesGroup();
List tables = new List();
int index = 0;
foreach (var table in RmlProcessParametersTableGroup.ProcessParametersTables)
{
var newTable = table.Clone();
newTable.TableIndex = index++;
newTable.ProcessParametersTablesGroup = group;
tables.Add(newTable);
}
group.Active = true;
group.ProcessParametersTables = tables.ToSynchronizedObservableCollection();
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(_activeJobDbContext);
InvalidateLiquidFactorsAndProcessTables();
}
CanWork = true;
}
///
/// Resets the process parameters.
///
private async void ResetProcessParameters()
{
if (_notification.ShowQuestion("This will reset the process parameters. Are you sure?"))
{
using (_notification.PushTaskItem("Resetting process parameters..."))
{
try
{
await ApplicationManager.ConnectedMachine.UploadProcessParameters(new ProcessParametersTable());
_notification.ShowInfo("Heaters are turned off.");
}
catch (Exception ex)
{
LogManager.Log(ex, "Error resetting process parameters.");
_notification.ShowError("Error resetting process parameters." + Environment.NewLine + ex.Message);
}
}
}
}
#endregion
#region Active Job Management
///
/// Loads the selected job.
///
private async void LoadSelectedJob(Action onCompleted = null)
{
if (SelectedMachineJob != null)
{
CanWork = false;
using (_notification.PushTaskItem("Loading job details..."))
{
await Task.Factory.StartNew(() =>
{
_disable_gamut_check = true;
LogManager.Log(String.Format("Loading job {0}...", SelectedMachineJob.Name));
SelectedSegments = new ObservableCollection();
SelectedBrushStops = new ObservableCollection();
SelectedRML = null;
SelectedSegment = null;
SelectedGroupHistory = null;
SelectedBrushStop = null;
SelectedProcessParametersTable = null;
RmlProcessParametersTableGroup = null;
_blockInvalidateCommands = false;
LogManager.Log("Creating active job DB context...");
_activeJobDbContext = ObservablesContext.CreateDefault();
LogManager.Log("Initializing available color spaces, RMLs & Winding methods...");
//var processParamsGroups = _activeJobDbContext.ProcessParametersTablesGroups.ToList();
//var processParams = _activeJobDbContext.ProcessParametersTables.ToList();
ColorSpaces = _activeJobDbContext.ColorSpaces.ToObservableCollection();
Rmls = _activeJobDbContext.Rmls.ToObservableCollection();
WindingMethods = _activeJobDbContext.WindingMethods.ToObservableCollection();
SpoolTypes = _activeJobDbContext.SpoolTypes.ToObservableCollection();
LogManager.Log("Loading machine spools...");
_activeJobDbContext.Spools.Where(x => x.MachineGuid == SelectedMachine.Guid).Load();
LogManager.Log("Setting active job...");
ActiveJob = new JobBuilder(_activeJobDbContext).Set(SelectedMachineJob.Guid).WithUser().WithSegments().WithBrushStops().WithConfiguration().WithRML().Build();
//_activeJobDbContext.Ccts.Where(x => x.RmlGuid == ActiveJob.RmlGuid).ToList();
//_activeJobDbContext.Cats.Where(x => x.RmlGuid == ActiveJob.RmlGuid).ToList();
//_activeJobDbContext.Machines.SingleOrDefault(x => x.Guid == ActiveJob.MachineGuid);
//_activeJobDbContext.Configurations.SingleOrDefault(x => x.Guid == ActiveJob.Machine.ConfigurationGuid);
//_activeJobDbContext.LiquidTypesRmls.ToList();
//_activeJobDbContext.IdsPackFormulas.ToList();
//_activeJobDbContext.LiquidTypes.ToList();
//_activeJobDbContext.MidTankTypes.ToList();
//_activeJobDbContext.DispenserTypes.ToList();
//_activeJobDbContext.IdsPacks.Where(x => x.ConfigurationGuid == ActiveJob.Machine.ConfigurationGuid).ToList();
LogManager.Log("Setting selected segment...");
_selectedSegment = ActiveJob.OrderedSegments.FirstOrDefault();
ActiveJob.LengthChanged -= ActiveJob_LengthChanged;
ActiveJob.LengthChanged += ActiveJob_LengthChanged;
_selectedRML = ActiveJob.Rml;
InvalidateLiquidFactorsAndProcessTables();
RaisePropertyChanged(nameof(SelectedRML));
UpdateEstimatedDuration();
_blockInvalidateCommands = false;
InvalidateRelayCommands();
_disable_gamut_check = false;
_settings.LastSelectedMachineGuid = SelectedMachine != null ? SelectedMachine.Guid : null;
_settings.LastSelectedJobGuid = SelectedMachineJob != null ? SelectedMachineJob.Guid : null;
_settings.Save();
});
SegmentsCollectionView = CollectionViewSource.GetDefaultView(ActiveJob.Segments);
SegmentsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Segment.SegmentIndex), ListSortDirection.Ascending));
foreach (var segment in ActiveJob.Segments)
{
SetSegmentBrushStopsLiquidVolumes(segment);
}
SelectedSegment = _selectedSegment;
UIHelper.DoEvents();
_navigation.NavigateTo(DeveloperNavigationView.JobView);
}
CanWork = true;
onCompleted?.Invoke();
}
}
///
/// Saves the active job.
///
private async void SaveActiveJob()
{
if (ActiveJob != null)
{
CanWork = false;
using (_notification.PushTaskItem("Saving job details..."))
{
await Task.Factory.StartNew(() =>
{
LogManager.Log(String.Format("Saving the active job {0}...", ActiveJob.Name));
ActiveJob.LastUpdated = DateTime.UtcNow;
ActiveJob.Rml = SelectedRML;
ActiveJob.EstimatedDurationMili = (int)EstimatedDuration.TotalMilliseconds;
_activeJobDbContext.SaveChanges();
_machineDbContext.Entry(SelectedMachineJob).Reload();
_machineDbContext.Entry(SelectedMachineJob).Collection(x => x.Segments).Load();
foreach (var segment in SelectedMachineJob.Segments.ToList())
{
_machineDbContext.Entry(segment).Collection(x => x.BrushStops).Load();
foreach (var brushStop in segment.BrushStops.ToList())
{
_machineDbContext.Entry(brushStop).Reload();
}
_machineDbContext.Entry(segment).Reload();
}
InvokeUI(() =>
{
SelectedMachineJob.Segments = SelectedMachineJob.Segments;
});
var settings = SettingsManager.Default.GetOrCreate();
settings.DefaultJobRmlGuid = ActiveJob.RmlGuid;
settings.Save();
});
}
CanWork = true;
}
}
private void BackToJobs()
{
LogManager.Log("User request for 'back to jobs'...");
LogManager.Log("Comparing active job with selected job...");
bool jobModified = !ActiveJob.CompareUsingJson(SelectedMachineJob);
if (jobModified)
{
LogManager.Log("Selected job has been modified. Invoking confirmation dialog...");
if (_notification.ShowQuestion("This will discard the current job changes. Are you sure?"))
{
LogManager.Log("Disposing active job db context...");
_activeJobDbContext.Dispose();
_navigation.NavigateTo(DeveloperNavigationView.MachineJobSelectionView);
}
}
else
{
LogManager.Log("Disposing active job db context...");
_activeJobDbContext.Dispose();
_navigation.NavigateTo(DeveloperNavigationView.MachineJobSelectionView);
}
}
#endregion
#region Private Methods
private async void LoadMachine()
{
try
{
LogManager.Log("Loading selected machine...");
CanWork = false;
using (_notification.PushTaskItem("Loading selected machine..."))
{
await _machineDbContext.Jobs.Where(x => x.MachineGuid == SelectedMachine.Guid).Include(x => x.User).Include(x => x.User.Contact).LoadAsync();
foreach (var job in SelectedMachine.Jobs)
{
await job.Reload(_machineDbContext);
}
await _machineDbContext.ColorSpaces.LoadAsync();
await Task.Factory.StartNew(() =>
{
_machineDbContext.Adapter.GetConfiguration(x => x.Guid == SelectedMachine.ConfigurationGuid);
});
RaisePropertyChanged(nameof(SelectedMachine));
JobsCollectionView = CollectionViewSource.GetDefaultView(SelectedMachine.Jobs);
JobsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Job.LastUpdated), ListSortDirection.Descending));
}
CanWork = true;
foreach (var job in SelectedMachine.Jobs.OrderByDescending(x => x.LastUpdated))
{
if (!CanWork) break;
job.Segments.EnableCrossThreadOperations();
await _machineDbContext.Segments.Where(x => x.JobGuid == job.Guid).Include(x => x.BrushStops).OrderBy(x => x.SegmentIndex).LoadAsync();
}
}
catch (Exception ex)
{
LogManager.Log(ex);
_notification.ShowError("An error occurred while trying to load the selected machine.");
CanWork = true;
}
}
private void UpdateEstimatedDuration()
{
if (ActiveJob != null && SelectedProcessParametersTable != null && SelectedProcessParametersTable.DyeingSpeed > 0)
{
EstimatedDuration = ActiveJob.GetEstimatedDuration(SelectedProcessParametersTable);
}
}
private void SetSegmentBrushStopsLiquidVolumes(Segment segment)
{
if (!DesignMode && segment != null)
{
LogManager.Log("Setting segment brush stops liquid volumes...");
foreach (var stop in segment.BrushStops)
{
stop.SetLiquidVolumes(ActiveJob.Machine.Configuration, SelectedRML, SelectedProcessParametersTable);
}
}
}
///
/// Navigates to the Machine Designer Module in order to edit the selected machine.
///
private void EditMachine()
{
LogManager.Log(String.Format("Requesting machine designer module for machine {0} editing...", SelectedMachine.SerialNumber));
}
#endregion
#region Add / Remove / Duplicate Jobs, Segments & Brush Stops
///
/// Arranges the segments indices.
///
private void ArrangeSegmentsIndices()
{
int index = 1;
foreach (var segment in ActiveJob.Segments.OrderBy(x => x.SegmentIndex))
{
segment.SegmentIndex = index++;
}
SegmentsCollectionView.Refresh();
}
///
/// Arranges the brush stops indices.
///
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?"))
{
LogManager.Log(String.Format("Removing {0} segments...", SelectedSegments.Count));
SelectedSegments.ToList().ForEach(x =>
{
if (ActiveJob.Segments.Count == 1)
{
_notification.ShowInfo("A job must contain at least one segment.");
return;
}
ActiveJob.Segments.Remove(x);
x.DefferedDelete(_activeJobDbContext);
});
ArrangeSegmentsIndices();
}
}
}
///
/// Adds a new segment.
///
private void AddSegment()
{
if (ActiveJob != null)
{
LogManager.LogFormat("Adding new segment to job {0}...", ActiveJob.Name);
Segment seg = new Segment();
seg.Job = ActiveJob;
seg.Name = "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();
SetSegmentBrushStopsLiquidVolumes(SelectedSegment);
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?"))
{
LogManager.Log(String.Format("Removing {0} jobs...", SelectedJobs.Count));
SelectedJobs.ToList().ForEach(x =>
{
SelectedMachine.Jobs.Remove(x);
x.DefferedDelete(_machineDbContext);
});
using (_notification.PushTaskItem("Removing selected jobs..."))
{
LogManager.Log("Saving selected machine to database...");
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))
{
LogManager.Log(String.Format("Adding new job {0}...", jobName));
var settings = SettingsManager.Default.GetOrCreate();
Job newJob = new Job();
newJob.Name = jobName;
newJob.CreationDate = DateTime.UtcNow;
newJob.UserGuid = AuthenticationProvider.CurrentUser.Guid;
if (String.IsNullOrWhiteSpace(settings.DefaultJobRmlGuid))
{
newJob.Rml = _machineDbContext.Rmls.FirstOrDefault();
}
else
{
var rml = _machineDbContext.Rmls.SingleOrDefault(x => x.Guid == settings.DefaultJobRmlGuid);
if (rml != null)
{
newJob.Rml = rml;
}
else
{
newJob.Rml = _machineDbContext.Rmls.FirstOrDefault();
}
}
newJob.WindingMethod = _machineDbContext.WindingMethods.FirstOrDefault();
newJob.SpoolType = _machineDbContext.SpoolTypes.FirstOrDefault();
newJob.ColorSpace = _machineDbContext.ColorSpaces.FirstOrDefault();
newJob.Machine = SelectedMachine;
SelectedMachine.Jobs.Add(newJob);
var segment = newJob.AddSolidSegment();
segment.BrushStops[0].SetAllDispensingStepDivisions(BL.Dispensing.DispenserStepDivisions.D8);
LogManager.Log("Saving selected machine to database...");
await SelectedMachine.SaveAsync(_machineDbContext);
SelectedMachineJob = newJob;
LoadSelectedJob();
}
}
}
///
/// 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 brush stops?"))
{
LogManager.Log(String.Format("Removing {0} brush stops...", SelectedBrushStops.Count));
SelectedBrushStops.ToList().ForEach(x =>
{
if (SelectedSegment.BrushStops.Count == 1)
{
_notification.ShowInfo("A job segment must contain at least one brush stop.");
return;
}
SelectedSegment.BrushStops.Remove(x);
x.DefferedDelete(_activeJobDbContext);
});
ArrangeBrushStopsIndices();
}
}
}
///
/// Adds a new brush stop to the selected segment.
///
private void AddBrushStop()
{
if (SelectedSegment != null)
{
LogManager.LogFormat("Adding new brush stop to segment...", SelectedSegment.SegmentIndex.ToString());
var stop = new BrushStop();
if (SelectedSegment.BrushStops.Count > 0)
{
stop.StopIndex = SelectedSegment.BrushStops.Max(x => x.StopIndex) + 1;
}
else
{
stop.StopIndex = 1;
}
stop.OffsetPercent = 100;
stop.Segment = SelectedSegment;
stop.ColorSpace = ColorSpaces.FirstOrDefault();
stop.Color = Colors.Black;
stop.SetAllDispensingStepDivisions(BL.Dispensing.DispenserStepDivisions.D8);
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()
{
LogManager.LogFormat("Duplicating {0} brush stops...", SelectedBrushStops.Count);
foreach (var stop in SelectedBrushStops.OrderBy(x => x.StopIndex))
{
var cloned = stop.Clone();
cloned.StopIndex = SelectedSegment.BrushStops.Max(x => x.StopIndex) + 1;
cloned.SetLiquidVolumes(ActiveJob.Machine.Configuration, SelectedRML, SelectedProcessParametersTable);
SelectedSegment.BrushStops.Add(cloned);
}
ArrangeBrushStopsIndices();
}
///
/// Duplicates the selected segments.
///
private void DuplicateSelectedSegments()
{
LogManager.LogFormat("Duplicating {0} segments...", SelectedSegments.Count);
int start_index = SelectedSegments.Max(x => x.SegmentIndex);
ActiveJob.Segments.Where(x => x.SegmentIndex > start_index).ToList().ForEach(x => x.SegmentIndex = x.SegmentIndex + SelectedSegments.Count);
foreach (var segment in SelectedSegments.OrderBy(x => x.SegmentIndex))
{
var cloned = segment.Clone();
cloned.SegmentIndex = start_index++;
ActiveJob.Segments.Add(cloned);
SelectedSegment = cloned;
}
ArrangeSegmentsIndices();
}
///
/// Duplicates the selected jobs.
///
private async void DuplicateSelectedJobs()
{
if (SelectedMachineJob != null)
{
using (_notification.PushTaskItem("Cloning selected jobs..."))
{
CanWork = false;
LogManager.LogFormat("Duplicating {0} jobs...", SelectedJobs.Count);
int index = SelectedMachine.Jobs.Max(x => x.JobIndex);
foreach (var job in SelectedJobs)
{
var cloned = job.Clone();
cloned.JobIndex = ++index;
SelectedMachine.Jobs.Add(cloned);
}
LogManager.Log("Saving selected machine to database...");
await SelectedMachine.SaveAsync(_machineDbContext);
CanWork = true;
}
}
}
#endregion
#region Embroidery
///
/// Imports embroidery file.
///
private void ImportEmbroideryFile()
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "Select embroidery file";
dlg.Filter = EMB_FORMATS_IMPORT;
if (dlg.ShowDialogCenter())
{
var view = new EmbroideryImportView();
_notification.ShowModalDialog(
new EmbroideryImportViewVM() { FileName = dlg.FileName }, view,
(vm) =>
{
String jobName = _notification.ShowTextInput("Please provide a job name", "Name");
if (jobName != null)
{
AddJobFromEmbroideryFile(jobName, vm, dlg.FileName, view.EmbroideryImageBytes);
}
},
() =>
{
});
}
}
private async void AddJobFromEmbroideryFile(String jobName, EmbroideryImportViewVM vm, String fileName, byte[] imageBytes)
{
LogManager.Log(String.Format("Adding new job from embroidery file {0}...", jobName));
Job job = new Job();
job.Name = jobName;
job.Name = jobName;
job.CreationDate = DateTime.UtcNow;
job.UserGuid = AuthenticationProvider.CurrentUser.Guid;
job.Rml = _machineDbContext.Rmls.FirstOrDefault();
job.WindingMethod = _machineDbContext.WindingMethods.FirstOrDefault();
job.SpoolType = _machineDbContext.SpoolTypes.FirstOrDefault();
job.Machine = SelectedMachine;
job.EmbroideryFileName = Path.GetFileName(fileName);
job.EmbroideryFileData = File.ReadAllBytes(fileName);
job.EmbroideryJpeg = imageBytes;
job.HasEmbroideryFile = true;
foreach (var path in vm.Paths.Skip(1))
{
Segment segment = new Segment();
double baseLength = path.Length / 1000d;
double embThicknessLength = (vm.EmbroideryMaterialThickness * path.StitchCount) / 1000d;
double stabilizerThicknessLength = (vm.StabilizerThickness * path.StitchCount) / 1000d;
double totalLength = (baseLength + embThicknessLength) * vm.SelectedEmbroideryMaterial.Coefficient;
if (vm.HasStabilizer)
{
totalLength += (stabilizerThicknessLength * vm.SelectedStabilizer.Coefficient);
}
segment.Length = totalLength;
segment.Name = "Embroidery Segment";
segment.SegmentIndex = vm.Paths.IndexOf(path);
if (path.Brush is SolidColorBrush)
{
var brush = (path.Brush as SolidColorBrush);
segment.BrushStops.Add(new BrushStop()
{
Red = brush.Color.R,
Green = brush.Color.G,
Blue = brush.Color.B,
ColorSpace = _machineDbContext.ColorSpaces.ToList().SingleOrDefault(x => x.Code == BL.Enumerations.ColorSpaces.RGB.ToInt32()),
});
}
else
{
var brush = (path.Brush as LinearGradientBrush);
foreach (var stop in brush.GradientStops)
{
segment.BrushStops.Add(new BrushStop()
{
StopIndex = brush.GradientStops.IndexOf(stop),
Red = stop.Color.R,
Green = stop.Color.G,
Blue = stop.Color.B,
OffsetPercent = stop.Offset * 100d,
ColorSpace = _machineDbContext.ColorSpaces.ToList().SingleOrDefault(x => x.Code == BL.Enumerations.ColorSpaces.RGB.ToInt32()),
});
}
}
job.Segments.Add(segment);
}
SelectedMachine.Jobs.Add(job);
LogManager.Log("Saving selected machine to database...");
await SelectedMachine.SaveAsync(_machineDbContext);
SelectedMachineJob = job;
LoadSelectedJob();
}
private void DisplayJobEmbroideryFile(Job job)
{
_notification.ShowModalDialog(new EmbroideryDisplayViewVM(job), (vm) =>
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.Title = "Select embroidery file location and format";
dlg.Filter = EMB_FORMATS_EXPORT;
dlg.FileName = job.EmbroideryFileName;
if (dlg.ShowDialogCenter())
{
try
{
var tempDir = TemporaryManager.CreateFolder();
String filePath = Path.Combine(tempDir.Path, job.EmbroideryFileName);
File.WriteAllBytes(filePath, job.EmbroideryFileData);
EmbroideryFileConverter.ConvertEmbroideryFile(filePath, dlg.FileName);
_notification.ShowInfo("Embroidery file exported successfully.");
}
catch (Exception ex)
{
LogManager.Log(ex, "An error has occurred while trying to export the attached embroidery file.");
_notification.ShowError("An error has occurred while trying to export the attached embroidery file.");
}
}
}, () => { });
}
#endregion
#region Override Methods
protected override void RaisePropertyChangedAuto([CallerMemberName] string caller = null)
{
base.RaisePropertyChangedAuto(caller);
if (!_blockInvalidateCommands)
{
InvalidateRelayCommands();
}
}
#endregion
#region IStudioViewModel
public override Task OnShutdownRequest()
{
if (IsJobRunning)
{
InvokeUI(() =>
{
_notification.ShowWarning("Please stop the currently running job before closing the developer module.");
});
return Task.FromResult(false);
}
return Task.FromResult(true);
}
public override void OnShuttingDown()
{
}
#endregion
}
}