using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Tango.BL; using Tango.BL.Entities; using Tango.PPC.Common; using Tango.PPC.Jobs.Messages; using System.Data.Entity; using Tango.Core.Commands; using System.Windows; using Tango.Touch.Controls; using System.Windows.Media; using Tango.DragAndDrop; using System.ComponentModel; using System.Windows.Data; using Tango.PPC.Jobs.Dialogs; using Tango.PPC.Jobs.Views; using System.Runtime.InteropServices; using System.Threading; using Tango.SharedUI.Helpers; using Tango.PPC.Common.Navigation; using Tango.PPC.Jobs.NavigationObjects; using Tango.PPC.Jobs.ViewContracts; using System.Collections.ObjectModel; using Tango.PPC.Common.Models; using Tango.Logging; using Tango.PPC.Common.Messages; using Tango.BL.Builders; using Tango.PPC.Jobs.AppButtons; using Tango.Core.Threading; using System.Diagnostics; using System.Runtime.ExceptionServices; using Tango.Explorer; using Tango.PPC.Storage; using System.IO; using Tango.ColorConversion; using Tango.Integration.Operation; using Tango.BL.Enumerations; using Tango.PPC.Common.Lubrication; using Tango.PPC.Jobs.Models; using Tango.Core; using Tango.PPC.Jobs.UndoRedoCommands; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Tango.PPC.Jobs.ColorCorrectionTool; using Tango.PPC.Common.Printing; using Tango.Core.ExtensionMethods; using Tango.PPC.Common.Resume; namespace Tango.PPC.Jobs.ViewModels { /// /// Represents the selected job view model. /// /// public class JobViewVM : PPCViewModel, INavigationObjectReceiver, INavigationBlocker { private ObservablesContext _db; private bool _can_navigate_back; private bool _not_show_warning; //private Thread _check_gamut_thread; private Job _job_to_load; private JobNavigationIntent _job_to_load_intent; private static Dictionary> _jobs_fine_tune_items; public static StartPrintingButton _start_printing_btn; private ActionTimer _volumeConversionTimer; private IColorConverter _converter; private string _current_job_string; private bool startingJob = false; private List _catalogs; private string _jsonJobModelLoaded; #region Properties public int CopiesStep { get { return BuildProvider.MachineType == MachineTypes.Eureka ? 4 : 1; } } private Job _job; /// /// Gets or sets the selected job. /// public Job Job { get { return _job; } set { _job = value; RaisePropertyChangedAuto(); } } private JobModel _jobModel; public JobModel JobModel { get { return _jobModel; } set { _jobModel = value; RaisePropertyChangedAuto(); } } public bool CanEdit { get { return Job != null && (!MachineProvider.MachineOperator.IsPrinting || MachineProvider.MachineOperator.RunningJob == null || MachineProvider.MachineOperator.RunningJob.Guid != Job.Guid) && !HasResumeModel; } } public bool CanDropResume { get { return Job != null && HasResumeModel && (!MachineProvider.MachineOperator.IsPrinting || (MachineProvider.MachineOperator.RunningJob != null && MachineProvider.MachineOperator.RunningJob.Guid != Job.Guid)); } } private ICollectionView _segmentsCollectionView; /// /// Gets or sets the job segments collection view. /// public ICollectionView SegmentsCollectionView { get { return _segmentsCollectionView; } set { _segmentsCollectionView = value; RaisePropertyChangedAuto(); } } private List _colorSpaces; /// /// Gets or sets the available color spaces. /// public List ColorSpaces { get { return _colorSpaces; } set { _colorSpaces = value; RaisePropertyChangedAuto(); } } private List _rmls; /// /// Gets or sets the available RMLS. /// public List Rmls { get { return _rmls; } set { _rmls = value; RaisePropertyChangedAuto(); } } private Rml _selectedRML; /// /// Gets or sets the selected RML. /// public Rml SelectedRML { get { return _selectedRML; } set { _selectedRML = value; RaisePropertyChangedAuto(); OnSelectedRmlChanged(); } } private List _spoolTypes; /// /// Gets or sets the available spool types. /// public List SpoolTypes { get { return _spoolTypes; } set { _spoolTypes = value; RaisePropertyChangedAuto(); } } private List _customers; /// /// Gets or sets the available customers. /// public List Customers { get { return _customers; } set { _customers = value; RaisePropertyChangedAuto(); } } private String _customersFilter; /// /// Gets or sets the customers filter. /// public String CustomersFilter { get { return _customersFilter; } set { _customersFilter = value; RaisePropertyChangedAuto(); } } /// /// Gets or sets the customers automatic complete provider. /// public AutoCompleteProvider CustomersAutoCompleteProvider { get; set; } private ObservableCollection _fineTuneItems; /// /// Gets or sets the fine tune items. /// public ObservableCollection FineTuneItems { get { return _fineTuneItems; } set { _fineTuneItems = value; RaisePropertyChangedAuto(); } } private ObservableCollection _approvalFineTuneItems; /// /// Gets or sets the fine tune items. /// public ObservableCollection ApprovalFineTuneItems { get { return _approvalFineTuneItems; } set { _approvalFineTuneItems = value; RaisePropertyChangedAuto(); } } private List _availableCatalogs; public List AvailableCatalogs { get { return _availableCatalogs; } set { _availableCatalogs = value; RaisePropertyChangedAuto(); } } private bool _isFullMode; public bool IsFullMode { get { return _isFullMode; } set { _isFullMode = value; RaisePropertyChangedAuto(); } } private bool _isBasicMode; public bool IsBasicMode { get { return _isBasicMode; } set { if (_isBasicMode != value) { if (value == true && JobModel != null && JobModel.Segments.Count > 0) { var firstSegment = JobModel.Segments.Where(x => x.SegmentIndex == 1).FirstOrDefault(); if (JobModel.Segments.Count > 1 || firstSegment.IsGradient) { SetOrDiscardAll(); return; } JobModel.EnableInterSegment = false; } _isBasicMode = value; RaisePropertyChangedAuto(); } } } private bool _isSummaryOpened; public bool IsSummaryOpened { get { return _isSummaryOpened; } set { _isSummaryOpened = value; RaisePropertyChangedAuto(); } } private bool _isWeigthView; public bool IsWeightView { get { return _isWeigthView; } set { if (_isWeigthView != value) { _isWeigthView = value; RaisePropertyChangedAuto(); } } } private JobResumeModel _resumeModel; public JobResumeModel ResumeModel { get { return _resumeModel; } set { _resumeModel = value; RaisePropertyChangedAuto(); RaisePropertyChanged(nameof(HasResumeModel)); RaisePropertyChanged(nameof(CanEdit)); } } public bool HasResumeModel { get { return ResumeModel != null; } } #endregion #region Commands /// /// Gets or sets the add solid segment command. /// public RelayCommand AddNewSegmentCommand { get; set; } /// /// Gets or sets the remove segment command. /// public RelayCommand RemoveSegmentCommand { get; set; } /// /// Gets or sets the copy segment command. /// public RelayCommand DuplicateSegmentCommand { get; set; } /// /// Gets or sets the remove job command. /// public RelayCommand AddColorCommand { get; set; } /// /// Gets or sets the remove job command. /// public RelayCommand EditColorCommand { get; set; } /// /// Gets or sets the replace brush stop command. /// public RelayCommand ReplaceBrushStopCommand { get; set; } /// /// Gets or sets the dye command. /// public RelayCommand DyeCommand { get; set; } /// /// Gets or sets the export embroidery command. /// public RelayCommand ExportEmbroideryCommand { get; set; } public RelayCommand EditJobDetailsCommand { get; set; } public RelayCommand RepeatUnitsCommand { get; set; } public RelayCommand JobModeSwitchCommand { get; set; } public RelayCommand UngroupSegmentsCommand { get; set; } public RelayCommand DeleteSegmentsGroupCommand { get; set; } public RelayCommand RepeatSegmentsGroupCommand { get; set; } public RelayCommand NavigateBackToJobs { get; set; } public RelayCommand DropResumeCommand { get; set; } #endregion #region collapsed mode commands public RelayCommand InsertWhiteGapCommand { get; set; } public RelayCommand ReverseCommand { get; set; } public RelayCommand DeleteSegmentCommand { get; set; } public RelayCommand RepeateSegmentCommand { get; set; } public RelayCommand PasteCommand { get; set; } public RelayCommand CopyCommand { get; set; } public RelayCommand UndoCommand { get; set; } public RelayCommand RedoCommand { get; set; } #endregion #region Constructors /// /// Initializes the class. /// static JobViewVM() { _jobs_fine_tune_items = new Dictionary>(); } /// /// Initializes a new instance of the class. /// public JobViewVM() { _converter = new DefaultColorConverter(); _volumeConversionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50)); RegisterForMessage(HandleJobSelectedMessage); FineTuneItems = new ObservableCollection(); ApprovalFineTuneItems = new ObservableCollection(); CustomersAutoCompleteProvider = new AutoCompleteProvider((customer, filter) => { return customer.Name.ToLower().StartsWith(filter != null ? filter.ToLower() : String.Empty); }); //Initialize Commands AddNewSegmentCommand = new RelayCommand(AddNewSegment); RemoveSegmentCommand = new RelayCommand(RemoveSegment); DuplicateSegmentCommand = new RelayCommand(DuplicateSegment); AddColorCommand = new RelayCommand(AddColor); EditColorCommand = new RelayCommand(EditColor); DyeCommand = new RelayCommand(StartJob, CanStartJob); ExportEmbroideryCommand = new RelayCommand(ExportEmbroidery); RepeatUnitsCommand = new RelayCommand(RepeatUnits); EditJobDetailsCommand = new RelayCommand(EditJobDetails); JobModeSwitchCommand = new RelayCommand(JobModeSwitch); InsertWhiteGapCommand = new RelayCommand(InsertWhiteGap); ReverseCommand = new RelayCommand(Reverse); DeleteSegmentCommand = new RelayCommand(DeleteSegments); DeleteSegmentsGroupCommand = new RelayCommand(DeleteSegmentsGroup); RepeateSegmentCommand = new RelayCommand(RepeateSegments); UngroupSegmentsCommand = new RelayCommand(UngroupSegments); RepeatSegmentsGroupCommand = new RelayCommand(RepeatSegmentsGroup); PasteCommand = new RelayCommand(Paste); CopyCommand = new RelayCommand(Copy); UndoCommand = new RelayCommand(Undo);//(x) => { return UndoRedoManager.Instance.IsEnableUndoOperation(); } RedoCommand = new RelayCommand(Redo);//(x) => { return UndoRedoManager.Instance.IsEnableRedoOperation();} DropResumeCommand = new RelayCommand(DropResume, (x) => CanDropResume); NavigateBackToJobs = new RelayCommand(NavigateBack); IsFullMode = true; IsSummaryOpened = true; _not_show_warning = false; } #endregion #region Job Management /// /// Loads the job. /// private async void LoadJob() { try { if (!(_job_to_load == null || (_job_to_load != null && Job != null && _job_to_load.Guid == Job.Guid))) { //View.ScrollToTop(); LogManager.Log($"Loading selected job '{_job_to_load.Name}'..."); IsFree = false; _can_navigate_back = false; if (_db != null) { if (Job != null) { //Job.RmlChanged -= OnRmlChanged; Job.NameChanged -= Job_NameChanged; } if (Rmls != null) { Rmls.Where(x => x.Cct != null && x.Cct.Data != null).ToList().ForEach(x => x.Cct.Data = null); Rmls.ForEach(x => x.Cct = null); if (SelectedRML != null) { SelectedRML.Cct = null; SelectedRML = null; } Rmls = null; } _db.Dispose(); GC.Collect(); } _db = ObservablesContext.CreateDefault(); _catalogs = await new CatalogsCollectionBuilder(_db) .SetAll() .WithGroups() .WithItems() .ForSite(MachineProvider.Machine.SiteGuid) .BuildListAsync(); Job = await new JobBuilder(_db).Set(_job_to_load.Guid) .WithConfiguration() .WithUser() .WithSegments() .WithBrushStops() .WithSegmentsGroups() .BuildAsync(); try { ResumeModel = JobResumeManager.GetJobResumeModel(Job.Guid); if (ResumeModel != null) { LogManager.Log($"Job resume info found:\n{ResumeModel.ToJsonString()}"); } } catch (Exception ex) { LogManager.Log(ex, "Error retrieving job resume info from db."); } RaisePropertyChanged(nameof(CanEdit)); DropResumeCommand.RaiseCanExecuteChanged(); Job.NameChanged -= Job_NameChanged; Job.NameChanged += Job_NameChanged; Job.ValidateOnPropertyChanged = true; //GetLubricationLevel(); //await SetSpoolTension(Job.Rml); LogManager.Log("Loading RMLS..."); Rmls = (await new RmlsCollectionBuilder(_db).SetAll().WithSpools().ForHeadType(MachineProvider.Machine.MachineHeadType).ForSite(MachineProvider.Machine.SiteGuid).BuildAsync()).OrderBy(x => x.FinalName).ToList(); //Rmls = (await new RmlsCollectionBuilder(_db).SetAll().WithSpools().BuildAsync()).OrderBy(x => x.FinalName).ToList(); LogManager.Log("Loading Color Spaces..."); ColorSpaces = await _db.ColorSpaces.Where(x => x.Code != (int)BL.Enumerations.ColorSpaces.CMYK).ToListAsync(); LogManager.Log("Loading Spool Types..."); SpoolTypes = await _db.SpoolTypes.ToListAsync(); LogManager.Log("Loading Customers..."); Customers = await _db.Customers.Where(x => x.OrganizationGuid == MachineProvider.Machine.OrganizationGuid).ToListAsync(); AvailableCatalogs = await new CatalogsCollectionBuilder(_db).SetAll().WithGroups().WithItems().ForSite(MachineProvider.Machine.SiteGuid).BuildListAsync(); _selectedRML = Job.Rml; RaisePropertyChanged(nameof(SelectedRML)); await LoadRML(_selectedRML); if (BuildProvider.MachineType.IsXMachine() && Job.Segments.Count == 1 && Job.Segments[0].BrushStops.Count <= 1) { IsBasicMode = true; } else IsBasicMode = false; IsWeightView = false; LoadJobModel(); _job_to_load = null; _current_job_string = Job.ToJobFileWhenLoaded().ToString(); } if (!_jobs_fine_tune_items.ContainsKey(Job.Guid) && Job.JobFineTuningStatus == BL.Enumerations.FineTuningStatuses.PendingApproval) { Job.JobFineTuningStatus = BL.Enumerations.FineTuningStatuses.Unspecified; } LogManager.Log($"Job editing state = '{Job.JobEditingState}'."); //if (Job.JobEditingState == BL.Enumerations.EditingStates.SampleDye && Job.JobSampleDyeStatus == BL.Enumerations.SampleDyeStatuses.PendingApproval) //{ // LogManager.Log("Directing view to display sample dye region."); // View.DisplaySampleDye(); //} //else if (Job.JobEditingState == BL.Enumerations.EditingStates.FineTuning && Job.JobFineTuningStatus == BL.Enumerations.FineTuningStatuses.PendingApproval) //{ // LogManager.Log("Directing view to display fine tuning region."); // View.DisplayFineTuning(); //} IsFullMode = true; DyeCommand.RaiseCanExecuteChanged(); } catch (Exception ex) { IsFree = true; LogManager.Log(ex, $"Error loading job '{(_job_to_load != null ? _job_to_load.Name : "null")}'"); await NotificationProvider.ShowError("An error occurred while trying to load the selected job."); _can_navigate_back = true; await NavigationManager.NavigateBack(); } finally { IsFree = true; } } private void LoadJobModel() { SpoolType PPCSpoolType = null; if (Settings.SpoolTypeGuid.IsNotNullOrEmpty()) { PPCSpoolType = _spoolTypes.FirstOrDefault(x => x.Guid == Settings.SpoolTypeGuid); } else { PPCSpoolType = _spoolTypes.FirstOrDefault(x => x.Type == BL.Enumerations.SpoolTypes.StandardSpool); } if (Job.SpoolType.Type == BL.Enumerations.SpoolTypes.FlatSpool) { PPCSpoolType = _spoolTypes.FirstOrDefault(x => x.Type == BL.Enumerations.SpoolTypes.FlatSpool); } var jobModel = new JobModel(ColorSpaces, BuildProvider.MachineType == MachineTypes.Eureka) { Name = Job.Name, Guid = Job.Guid, ID = Job.ID, CreationDate = Job.CreationDate, LengthPercentageFactor = Job.LengthPercentageFactor, NumberOfUnits = Job.NumberOfUnits, IsAllSegmentsPerSpool = Job.IsAllSegmentsPerSpool, Rml = Job.Rml, Job = Job, ColorSpace = Job.ColorSpace, SpoolType = Job.SpoolType, SpoolTypeName = PPCSpoolType.Name, User = Job.User, Machine = Job.Machine, JobType = Job.JobType, InterSegmentLength = Job.InterSegmentLength, EnableInterSegment = Job.EnableInterSegment, NumberSpools = Job.NumberOfSpools, Copies = (BuildProvider.MachineType == MachineTypes.Eureka ? Job.NumberOfUnits * Job.NumberOfSpools : Job.NumberOfUnits) }; Dictionary guidToGroup = new Dictionary(); if (Job.Version < 2) { int segmentindex = 1; foreach (var segm in Job.OrderedSegments) { if (segm.BrushStops.Count > 1) { var brushes = segm.BrushStops; Segment currentSegment = segm; double lengthOfOldSegment = segm.Length; for (int index = 0; index < (brushes.Count - 1); index++) { SegmentModel csegmentModel = new SegmentModel(jobModel, segm.Guid) { Name = segm.Name, Length = segm.Length, SegmentIndex = segm.SegmentIndex, IsInterSegment = segm.IsInterSegment, Job = jobModel }; csegmentModel.SegmentIndex = segmentindex++; brushes[index].Segment = currentSegment; brushes[index + 1].Segment = currentSegment; csegmentModel.Length = (lengthOfOldSegment * (brushes[index + 1].OffsetPercent - brushes[index].OffsetPercent) / 100d); BrushStopModel brushStopModelFirst = new BrushStopModel(brushes[index], csegmentModel, 1); BrushStopModel brushStopModelSecond = new BrushStopModel(brushes[index + 1], csegmentModel, 1); csegmentModel.CreateGradientBrushes(brushStopModelFirst, brushStopModelSecond); jobModel.Segments.Add(csegmentModel); } } else { SegmentModel segmentModel = LoadSegmentModel(segm, jobModel); segmentModel.SegmentIndex = segmentindex++; jobModel.Segments.Add(segmentModel); } } } else { var segments = Job.OrderedSegmentsWithGroups; foreach (var segment in segments) { if (segment is Segment simpleSegment) { SegmentModel segmentModel = LoadSegmentModel(simpleSegment, jobModel); jobModel.Segments.Add(segmentModel); } else if (segment is SegmentsGroup group) { SegmentsGroupModel segmentsGroupModel = new SegmentsGroupModel(jobModel) { SegmentIndex = group.SegmentIndex, Repeats = group.Repeats }; foreach (var innerSegment in group.OrderedSegments) { SegmentModel segmentModel = LoadSegmentModel(innerSegment, jobModel); jobModel.Segments.Add(segmentModel); segmentsGroupModel.Segments.Add(segmentModel); segmentModel.SegmentsGroupModel = segmentsGroupModel; } jobModel.SegmentsGroups.Add(segmentsGroupModel); } } } jobModel.InterSegmentLength = Job.EnableInterSegment ? Job.InterSegmentLength : 0; jobModel.LoadGroupingSegments(); JobModel = jobModel; //create grouping SegmentsCollectionView = CollectionViewSource.GetDefaultView(JobModel.GroupingSegments); SegmentsCollectionView.SortDescriptions.Add(new SortDescription(nameof(SegmentModel.SegmentIndex), ListSortDirection.Ascending)); UndoRedoManager.Instance.ClearAll(); ArrangeSegmentsIndixes(); JsonSerializerSettings settings = new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore, PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects }; _jsonJobModelLoaded = JsonConvert.SerializeObject(JobModel, Formatting.Indented, settings); } /// /// Loads the segment model. /// /// The segm. /// The job model. /// private SegmentModel LoadSegmentModel(Segment segm, JobModel jobModel) { SegmentModel segmentModel = new SegmentModel(jobModel, segm.Guid) { Name = segm.Name, Length = segm.Length, SegmentIndex = segm.SegmentIndex, IsInterSegment = segm.IsInterSegment, Job = jobModel, }; foreach (var brushStop in segm.BrushStops) { BrushStopModel brushStopModel = new BrushStopModel(brushStop, segmentModel, Job.Version); segmentModel.BrushStops.Add(brushStopModel); } segmentModel.ArrangeBrushStopsPosition(); segmentModel.UpdateMiddleColorBrush(); return segmentModel; } private void Job_NameChanged(object sender, string e) { DyeCommand.RaiseCanExecuteChanged(); } /// /// Starts the job. /// private async void StartJob() { if (startingJob) return; try { Debug.WriteLine("Job Starting..."); startingJob = true; LogManager.Log("Start job command pressed. Starting job and navigating to job progress view..."); await Save(); var printConfig = new PrintingConfiguration(); if (HasResumeModel) { printConfig.FirstUnitStartPosition = ResumeModel.FirstUnitStartPosition; printConfig.GlobalStartPosition = ResumeModel.GlobalStartPosition; printConfig.RemainingUnits = ResumeModel.RemainingUnits; printConfig.ResumeProgress = ResumeModel.ResumeProgress; //LogManager.Log($"!!!!! Start Job resume : FirstUnitStartPosition = {ResumeModel.FirstUnitStartPosition} GlobalStartPosition = {ResumeModel.GlobalStartPosition} RemainingUnits = {ResumeModel.RemainingUnits}", LogCategory.Debug); } var handler = await PrintingManager.Print(Job, _db, printConfig); RaisePropertyChanged(nameof(CanEdit)); DropResumeCommand.RaiseCanExecuteChanged(); if (!BuildProvider.MachineType.IsXMachine()) { await NavigationManager.NavigateTo(nameof(JobProgressView)); } startingJob = false; } catch (InsufficientLiquidQuantityException) { //Ignore.. } catch (OperationCanceledException) { //Ignore.. } catch (Exception ex) { LogManager.Log(ex, "Could not start the current job."); await NotificationProvider.ShowError($"{ex.Message}."); } finally { startingJob = false; } } /// /// Determines whether this instance [can start job]. /// private bool CanStartJob() { try { //var test = JobModel != null && !JobModel.Segments.SelectMany(x => x.BrushStops).Where(x => x.Position == BrushStopModel.PositionStatus.FirstColor || x.Position == BrushStopModel.PositionStatus.SecondColor).ToList().Exists(x => x.IsOutOfGamut); //return Job != null && Job.Validate(_db) && !Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.IsTransparent && !x.IsWhite).ToList().Exists(x => x.IsOutOfGamut || (x.BrushColorSpace == BL.Enumerations.ColorSpaces.Volume && x.IsLiquidVolumesOutOfRange)); return JobModel != null && !JobModel.Segments.ToList().Exists(x => x.BrushStops.Count == 0); } catch (Exception ex) { Debug.WriteLine(ex); return false; } } private async void EditJobDetails() { try { LogManager.Log("Editing the job details."); JobCreationViewVM vm = new JobCreationViewVM(_spoolTypes.ToList(), _rmls, JobModel.Rml.Guid, JobModel.InterSegmentLength, true); vm.UseFlatSpool = Job.SpoolType.Type == BL.Enumerations.SpoolTypes.FlatSpool; vm.JobName = JobModel.Name; vm.SelectedSpoolType = JobModel.SpoolType; vm = await NotificationProvider.ShowDialog(vm); if (!vm.DialogResult) return; Job.Name = vm.JobName; JobModel.Name = vm.JobName; if (vm.UseFlatSpool) { Job.SpoolType = _spoolTypes.FirstOrDefault(x => x.Type == BL.Enumerations.SpoolTypes.FlatSpool); } else { if (Settings.SpoolTypeGuid.IsNotNullOrEmpty()) { Job.SpoolType = _spoolTypes.FirstOrDefault(x => x.Guid == Settings.SpoolTypeGuid); } else { Job.SpoolType = _spoolTypes.FirstOrDefault(x => x.Type == BL.Enumerations.SpoolTypes.StandardSpool); } } JobModel.SpoolType = Job.SpoolType; JobModel.SpoolTypeName = Job.SpoolType.Name; Job.InterSegmentLength = vm.WhiteGap; Job.EnableInterSegment = vm.WhiteGap > 0; JobModel.InterSegmentLength = vm.WhiteGap; JobModel.EnableInterSegment = vm.WhiteGap > 0; // Job.SpoolType = vm.SelectedSpoolType; // JobModel.SpoolType = vm.SelectedSpoolType;//update length!!!! if (vm.SelectedRML.Guid != SelectedRML.Guid) { SelectedRML = _rmls.FirstOrDefault(x => x.Guid == vm.SelectedRML.Guid); // for LAB color remove all available tests foreach (var segment in JobModel.OrderedSegmentsWithGroups) { if (segment is SegmentModel innerSegment) { foreach (var stop in innerSegment.BrushStops.OrderBy(x => x.StopIndex).ToList()) { if (stop.ColorSpace == Tango.BL.Enumerations.ColorSpaces.LAB) { var testColor = TrialsLogEngine.Default.GetByBrushStopGuid(stop.Guid); if (testColor != null && testColor.TrialslogList.Count > 0) { TrialsLogEngine.Default.Delete(testColor); } } } } else if (segment is SegmentsGroupModel group) { foreach (var segm_group in group.Segments.OrderBy(x => x.SegmentIndex)) { foreach (var stop in segm_group.BrushStops.OrderBy(x => x.StopIndex).ToList()) { if (stop.ColorSpace == Tango.BL.Enumerations.ColorSpaces.LAB) { var testColor = TrialsLogEngine.Default.GetByBrushStopGuid(stop.Guid); if (testColor != null && testColor.TrialslogList.Count > 0) { TrialsLogEngine.Default.Delete(testColor); } } } } } } } if (vm.IsDuplicate) { try { await Save(); //Duplicate new job var cloned = Job.Clone(); cloned.JobIndex = (_db.Jobs.Max(x => x.JobIndex) + 1); _db.Jobs.Add(cloned); await _db.SaveChangesAsync(); _job_to_load = cloned; LoadJob(); } catch (Exception ex) { LogManager.Log(ex, "Error duplicate job."); } } } catch (Exception ex) { LogManager.Log(ex, "Error editing the job."); } } private async void RepeatUnits() { var maxLength = Job.SpoolType.Length; var maxRep = (maxLength == 0 ? 999 : (maxLength / JobModel.Length)); var vm = await NotificationProvider.ShowDialog(new RepeatJobViewVM("Repeat All", JobModel.NumberOfUnits) { MaxRepeations = (int)maxRep }); if (vm.DialogResult) { JobModel.NumberOfUnits = vm.Repeats; } } #endregion #region RML Changed private async void OnSelectedRmlChanged() { await LoadRML(SelectedRML); } private async Task LoadRML(Rml rml) { if (rml != null) { if (Job.Rml != rml || rml.Cct == null) { bool updateRML = Job.Rml != rml; Job.Rml = await new RmlBuilder(_db) .Set(rml.Guid) .WithActiveParametersGroup() .WithCCT() .WithGbdAndLub() .WithCAT(MachineProvider.Machine.Guid) .WithLiquidFactors() .WithSpools() .BuildAsync(); if (JobModel != null) { JobModel.Rml = Job.Rml; } if (updateRML && JobModel != null) { NotificationProvider.SetGlobalBusyMessage("Updating IsOutOfGammut due to the change RML..."); foreach (var segment in JobModel.OrderedSegmentsWithGroups) { if (segment is SegmentModel innerSegment) { innerSegment.UpdateWeightOnRMLChange(IsWeightView); innerSegment.UpdateBrushStops(); } else if (segment is SegmentsGroupModel group) { foreach (var segm in group.Segments) { segm.UpdateWeightOnRMLChange(IsWeightView); segm.UpdateBrushStops(); } } } DyeCommand.RaiseCanExecuteChanged(); NotificationProvider.ReleaseGlobalBusyMessage(); } //if (updateVolumes) //{ // NotificationProvider.SetGlobalBusyMessage("Updating job liquid volumes..."); // foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).Where(x => x.BrushColorSpace == BL.Enumerations.ColorSpaces.RGB || x.BrushColorSpace == BL.Enumerations.ColorSpaces.LAB).ToList()) // { // try // { // var output = await _converter.ConvertAsync(stop, false, false); // output.ApplyOnBrushStopVolumesOnly(stop); // } // catch (Exception ex) // { // LogManager.Log(ex, $"Error updating stop volumes after changing thread on segment {stop.Segment.SegmentIndex}, stop {stop.StopIndex}."); // } // } // NotificationProvider.ReleaseGlobalBusyMessage(); //} } } } #endregion #region Segments Management /// /// Adds a new segment. /// private void AddNewSegment(ISegmentModel segment) { try { LogManager.Log("Adding new segment..."); UndoRedoManager.Instance.InsertAndExecuteCommand(new AddNewSegmentCommand(JobModel, segment, Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 10)); ArrangeSegmentsIndixes(); DyeCommand.RaiseCanExecuteChanged(); if (segment.SegmentIndex >= (JobModel.GroupingSegments.Count() - 1)) { View.ScrollToEnd(); } } catch (Exception ex) { LogManager.Log(ex, "Could not add a new segment."); NotificationProvider.ShowError("An error occurred while trying to add a new segment."); } } private async void RepeatSegmentsGroup(SegmentsGroupModel group) { var maxLength = Job.SpoolType.Length == 0 ? 999 : Job.SpoolType.Length; var maxRep = (maxLength - JobModel.Length) / group.Length; var vm = await NotificationProvider.ShowDialog(new RepeatJobViewVM($"Edit \"Group {group.SegmentIndex}\" Repeat", group.Repeats) { MaxRepeations = (int)maxRep }); if (vm.DialogResult) { group.Repeats = vm.Repeats; } } /// /// Removes the segment. /// private async void RemoveSegment(SegmentModel segment) { if (JobModel.Segments.Count > 1) { try { if (await NotificationProvider.ShowQuestion("Are you sure you want to remove the selected segment?")) { UndoRedoManager.Instance.InsertAndExecuteCommand(new RemoveSegmentCommand(JobModel, segment)); ArrangeSegmentsIndixes(); DyeCommand.RaiseCanExecuteChanged(); } } catch (Exception ex) { LogManager.Log(ex, "Could not remove segment."); await NotificationProvider.ShowError("An error occurred while trying to delete segment."); } } else { await NotificationProvider.ShowInfo("A job must contain at least one color segment."); } } private async void DeleteSegmentsGroup(SegmentsGroupModel segmentsGroup) { if (JobModel.GroupingSegments.Count > 1) { try { if (await NotificationProvider.ShowQuestion("Are you sure you want to remove the selected group of segments?")) { UndoRedoManager.Instance.InsertAndExecuteCommand(new DeleteSegmentsGroupCommand(JobModel, segmentsGroup)); ArrangeSegmentsIndixes(); DyeCommand.RaiseCanExecuteChanged(); } } catch (Exception ex) { LogManager.Log(ex, "Could not remove group of segments."); await NotificationProvider.ShowError("An error occurred while trying to delete group of segments."); } } else { await NotificationProvider.ShowInfo("A job must contain at least one color segment."); } } /// /// Duplicates the segment. /// private void DuplicateSegment(SegmentModel segment) { UndoRedoManager.Instance.InsertAndExecuteCommand(new DuplicateSegmentCommand(JobModel, segment)); ArrangeSegmentsIndixes(); DyeCommand.RaiseCanExecuteChanged(); if (segment.SegmentIndex >= (JobModel.GroupingSegments.Count() - 1)) { View.ScrollToEnd(); } } private void ArrangeSegmentsIndixes() { JobModel.ArrangeSegmentsIndixes(); SegmentsCollectionView.Refresh(); } #endregion #region Brush Stops Management /// /// Click on AddColor button. Add newBrush; /// private async void AddColor(SegmentModel segment) { LogManager.Log($"Adding new color to segment {segment.SegmentIndex}."); if ((segment.IsGradient && segment.Length < 10) || (segment.HasColors && segment.Length < 5)) { await NotificationProvider.ShowInfo("Color transitions are best visible with segment length of 5 meters and above."); } var vm = await NotificationProvider.ShowDialog(new ColorSelectionViewVM() { DialogEditObject = new ColorSelectionViewVM.DialogObject() { SelectedSegment = segment, BrushStopForEdit = new BrushStopModel(segment, null), IsEditingMode = false, Catalogs = _catalogs } }); if (vm.DialogResult) { AddBrushStop(segment, vm.SelectedBrushStop); DyeCommand.RaiseCanExecuteChanged(); } // SetSegmentLiquidVolumes(segment); } /// /// Click on Edit Color button. Add newBrush; /// private async void EditColor(BrushStopModel brushStop) { if (brushStop == null) { await NotificationProvider.ShowError("The edit brush is null!"); return; } SegmentModel segment = brushStop.SegmentModel; LogManager.Log($"Edit brush stop."); var vm = await NotificationProvider.ShowDialog(new ColorSelectionViewVM() { DialogEditObject = new ColorSelectionViewVM.DialogObject() { SelectedSegment = segment, BrushStopForEdit = brushStop, IsEditingMode = true, Catalogs = _catalogs } }); if (vm.DialogResult) { UndoRedoManager.Instance.InsertAndExecuteCommand(new EditBrushStopColorCommand(segment, brushStop, vm.SelectedBrushStop)); DyeCommand.RaiseCanExecuteChanged(); } } /// /// Adds the brush stop. /// public async void AddBrushStop(SegmentModel segment, BrushStopModel newBrushStop) { if (newBrushStop == null || segment == null) return; if (segment.IsGradient) { if (false == _not_show_warning) { var vm = await NotificationProvider.ShowDialog(new AddSegmentWarningDialogVM()); if (vm.NotShow) { _not_show_warning = true; } } } UndoRedoManager.Instance.InsertAndExecuteCommand(new AddBrushStopCommand(JobModel, segment, newBrushStop)); ArrangeSegmentsIndixes(); } #endregion #region Job Selection Message /// /// Handles the job selected message. /// /// The message. private void HandleJobSelectedMessage(JobSelectedMessage message) { _job_to_load = message.Job; } #endregion #region Sample Dye /// /// Starts a sample dye. /// //private async void StartSampleDye() //{ // try // { // LogManager.Log("Sample dye command pressed..."); // await PrintingManager.PrintSample(Job, _db); // await NavigationManager.NavigateTo(nameof(JobProgressView)); // } // catch (Exception ex) // { // LogManager.Log(ex, $"Error executing sample dye for job {Job.Name}."); // await NotificationProvider.ShowError(ex.Message); // } //} #endregion #region Export Embroidery private async void ExportEmbroidery() { try { if (!StorageProvider.IsConnected) { await NotificationProvider.ShowError("No storage device connected."); return; } var result = await NavigationManager. NavigateForResult( new Storage.Models.StorageNavigationRequest() { Intent = Storage.Models.StorageNavigationIntent.SaveFile, DefaultFileName = Job.Name + Path.GetExtension(Job.EmbroideryFileName), Filter = Path.GetExtension(Job.EmbroideryFileName), Title = "Export Embroidery File", }); if (result != null) { File.WriteAllBytes(Path.HasExtension(result.Path) ? result.Path : result.Path + Path.GetExtension(Job.EmbroideryFileName), Job.EmbroideryFileData); await NotificationProvider.ShowSuccess("Embroidery file exported successfully."); } } catch (Exception ex) { LogManager.Log(ex, "Error exporting embroidery file."); await NotificationProvider.ShowError("An error occurred while trying to save the selected embroidery file."); } } #endregion #region IPPC ViewModel Overrides /// /// Called when the application has been started. /// public override void OnApplicationStarted() { base.OnApplicationStarted(); MachineProvider.MachineOperator.PrintingEnded += MachineOperator_PrintingEnded; MachineProvider.MachineOperator.PrintingStarted += MachineOperator_PrintingStarted; JobResumeManager.JobResumeUpdated += JobResumeManager_JobResumeUpdated; JobResumeManager.JobResumeDropped += JobResumeManager_JobResumeDropped; } /// /// Called when the navigation system has navigated to this VM view. /// public override void OnNavigatedTo() { if (!MachineProvider.MachineOperator.IsPrinting) { _start_printing_btn.Push(); } base.OnNavigatedTo(); LoadJob(); } public override void OnBeforeNavigatedTo() { base.OnBeforeNavigatedTo(); } public override void OnBeforeNavigatedFrom() { base.OnBeforeNavigatedFrom(); } /// /// Called when the navigation system has navigated from this VM view. /// public override void OnNavigatedFrom() { _start_printing_btn.Pop(); base.OnNavigatedFrom(); _job_to_load_intent = JobNavigationIntent.Default; } public override void OnNavigatedTo(PPCViewModel fromVM) { base.OnNavigatedTo(fromVM); } /// /// Called before the navigation system navigates back from this object. /// Return false to abort the navigation. /// /// public async override Task OnNavigateBackRequest() { if (!IsFree) return false; try { if (!_can_navigate_back) { await Save(); Job = null; JobModel = null; SegmentsCollectionView = null; } return true; } catch (Exception ex) { LogManager.Log(ex, "Error saving job to database. " + ex.InnerException.Message); await NotificationProvider.ShowError("Error saving the current job."); return true; } } private async void NavigateBack() { if (IsFree) { if (await OnNavigateBackRequest()) { LogManager.Log("Back command to Jobs pressed."); await NavigationManager.NavigateTo(nameof(JobsView)); } } } public override void OnApplicationReady() { base.OnApplicationReady(); _start_printing_btn = new StartPrintingButton(DyeCommand, MachineProvider.MachineOperator); } #endregion #region INavigationObjectReceiver public void OnNavigatedToWithObject(JobNavigationObject e) { _job_to_load_intent = e.Intent; _job_to_load = e.Job; } #endregion #region collapsed mode private void JobModeSwitch() { IsFullMode = !IsFullMode; //UndoRedoManager.Instance.ClearAll(); According to QA! request - #6314 } private void InsertWhiteGap() { JobModel.InsertWhiteGapToSelectedSegments(); } private void Reverse() { if (false == JobModel.GroupingSegments.ToList().Any(x => x.IsSelected)) return; UndoRedoManager.Instance.InsertAndExecuteCommand(new ReverseCommand(JobModel)); ArrangeSegmentsIndixes(); } private async void DeleteSegments() { if (!JobModel.HasSelectedItems) return; if (JobModel.GroupingSegments.ToList().Where(x => x.IsSelected).ToList().Count == JobModel.GroupingSegments.Count) { await NotificationProvider.ShowInfo("A job must contain at least one segment. Please, change selection."); return; } if (JobModel.GroupingSegments.Count > 1) { try { if (await NotificationProvider.ShowQuestion("Are you sure you want to remove these selected segments?")) { UndoRedoManager.Instance.InsertAndExecuteCommand(new RemoveSegmentsCommand(JobModel)); ArrangeSegmentsIndixes(); DyeCommand.RaiseCanExecuteChanged(); } } catch (Exception ex) { LogManager.Log(ex, "Could not remove segments."); await NotificationProvider.ShowError("An error occurred while trying to delete segments."); } } else { await NotificationProvider.ShowInfo("A job must contain at least one color segment."); } } private void RepeateSegments() { if ((JobModel.GroupingSegments.ToList().Where(x => x.IsSelected).Count()) < 2) return; UndoRedoManager.Instance.InsertAndExecuteCommand(new RepeatCommand(JobModel)); ArrangeSegmentsIndixes(); } private void UngroupSegments(SegmentsGroupModel segmentsGroup) { UndoRedoManager.Instance.InsertAndExecuteCommand(new UnGroupSegmentsCommand(JobModel, segmentsGroup)); ArrangeSegmentsIndixes(); } private void Paste() { UndoRedoManager.Instance.InsertAndExecuteCommand(new PasteSegmentsCommand(JobModel)); ArrangeSegmentsIndixes(); } private void Copy() { UndoRedoManager.Instance.InsertAndExecuteCommand(new CopySegmentCommand(JobModel)); ArrangeSegmentsIndixes(); } private void Undo() { UndoRedoManager.Instance.Undo(); ArrangeSegmentsIndixes(); DyeCommand.RaiseCanExecuteChanged(); } private void Redo() { UndoRedoManager.Instance.Redo(); ArrangeSegmentsIndixes(); DyeCommand.RaiseCanExecuteChanged(); } private void SetOrDiscardAll() { InvokeUI(async () => { IsBasicMode = await MessageDiscardAllChanges(); }); } private async Task MessageDiscardAllChanges() { try { MessageDiscardAdvancedOptionsVM vm = new MessageDiscardAdvancedOptionsVM(); vm = await NotificationProvider.ShowDialog(vm); if (vm.DialogResult) { //delete all var segments = JobModel.OrderedSegmentsWithGroups; var firstSegment = JobModel.Segments.Where(x => x.SegmentIndex == 1).FirstOrDefault(); firstSegment.SegmentsGroupModel = null; JobModel.GroupingSegments.Clear(); JobModel.Segments.Clear(); JobModel.Segments.Add(firstSegment); JobModel.GroupingSegments.Add(firstSegment); JobModel.EnableInterSegment = false; JobModel.InterSegmentLength = 0; if (firstSegment.IsGradient) { BrushStopModel firstbrush = firstSegment.FirstBrushStop; firstSegment.BrushStops.Clear(); firstSegment.BrushStops.Add(firstbrush); firstSegment.ArrangeBrushStopsIndexes(); } return true; } return false; } catch { return false; } } #endregion #region Save from models to db private async Task Save() { if (JobModel == null) return; UndoRedoManager.Instance.ClearAll(); var colorSpaces = await _db.ColorSpaces.ToListAsync(); Job.ColorSpace = colorSpaces.FirstOrDefault(); Job.Version = 2; Job.Name = JobModel.Name; Job.NumberOfUnits = JobModel.NumberOfUnits; Job.EnableInterSegment = JobModel.InterSegmentLength > 0; Job.InterSegmentLength = JobModel.InterSegmentLength; if (Job.SpoolType.Type == BL.Enumerations.SpoolTypes.FlatSpool) { Job.SpoolType = _spoolTypes.FirstOrDefault(x => x.Code == (int)BL.Enumerations.SpoolTypes.FlatSpool); } else if (Settings.SpoolTypeGuid != null) { Job.SpoolType = _spoolTypes.FirstOrDefault(x => x.Guid == Settings.SpoolTypeGuid); } else { Job.SpoolType = _spoolTypes.FirstOrDefault(x => x.Code == (int)BL.Enumerations.SpoolTypes.StandardSpool); } Job.NumberOfSpools = JobModel.NumberSpools; var oldSegments = Job.Segments.ToList(); foreach (var segment in Job.OrderedSegmentsWithGroups.ToList()) { if (segment is Segment) { Segment simplesegment = segment as Segment; simplesegment.BrushStops.ToList().ForEach(x => { _db.BrushStops.Remove(x); }); _db.Segments.Remove(simplesegment); } else if (segment is SegmentsGroup) { SegmentsGroup segmentsGroup = segment as SegmentsGroup; foreach (var groupSegment in segmentsGroup.Segments.ToList()) { groupSegment.BrushStops.ToList().ForEach(x => { _db.BrushStops.Remove(x); }); _db.Segments.Remove(groupSegment); } _db.SegmentsGroups.Remove(segmentsGroup); } } Job.Segments.Clear(); Dictionary segmentIndexToGroup = new Dictionary(); //foreach (var segment in JobModel.Segments.OrderBy(x => x.SegmentIndex).ToList()) foreach (var segment in JobModel.OrderedSegmentsWithGroups) { if (segment is SegmentModel innerSegment) { var dbSegment = new Segment(); dbSegment.Guid = System.Guid.NewGuid().ToString(); dbSegment.Name = "Standard Segment"; dbSegment.Job = Job; dbSegment.SegmentIndex = segment.SegmentIndex; dbSegment.Length = segment.Length; _db.Segments.Add(dbSegment); List brushStopList = new List();//to prevent collection changed event and override offset in timer foreach (var stop in innerSegment.BrushStops.OrderBy(x => x.StopIndex).ToList()) { var dbStop = new BrushStop(); dbStop.Guid = stop.Guid; dbStop.Segment = dbSegment; //_db.BrushStops.Add(dbStop); brushStopList.Add(dbStop); dbStop.ColorSpace = colorSpaces.FirstOrDefault(x => x.Code == (int)stop.ColorSpace); dbStop.Red = stop.Red; dbStop.Green = stop.Green; dbStop.Blue = stop.Blue; dbStop.L = stop.L; dbStop.A = stop.A; dbStop.B = stop.B; dbStop.BestMatchR = stop.BestMatchColor.R; dbStop.BestMatchG = stop.BestMatchColor.G; dbStop.BestMatchB = stop.BestMatchColor.B; dbStop.OffsetPercent = stop.OffsetPercent; dbStop.StopIndex = stop.StopIndex; dbStop.IsOutOfGamut = stop.IsOutOfGamut; stop.LiquidVolumes.SetVolumesOnBrushStop(dbStop); dbStop.ColorCatalog = stop.ColorCatalog; dbStop.ColorCatalogsItem = stop.ColorCatalogsItem; } _db.BrushStops.AddRange(brushStopList); } else if (segment is SegmentsGroupModel group) { SegmentsGroup dbSegmentsGroup = new SegmentsGroup(); dbSegmentsGroup.Guid = System.Guid.NewGuid().ToString(); dbSegmentsGroup.Repeats = group.Repeats; dbSegmentsGroup.SegmentIndex = group.SegmentIndex; dbSegmentsGroup.Job = Job; _db.SegmentsGroups.Add(dbSegmentsGroup); foreach (var segm_group in group.Segments.OrderBy(x => x.SegmentIndex)) { var dbSegment = new Segment(); dbSegment.Guid = System.Guid.NewGuid().ToString(); dbSegment.Name = "Standard Segment"; dbSegment.Job = Job; dbSegment.SegmentIndex = segm_group.SegmentIndex; dbSegment.Length = segm_group.Length; dbSegment.SegmentsGroupGuid = dbSegmentsGroup.Guid; _db.Segments.Add(dbSegment); List brushStopList = new List();//to prevent collection changed event and override offset in timer foreach (var stop in segm_group.BrushStops.OrderBy(x => x.StopIndex).ToList()) { var dbStop = new BrushStop(); dbStop.Segment = dbSegment; //_db.BrushStops.Add(dbStop); brushStopList.Add(dbStop); dbStop.ColorSpace = colorSpaces.FirstOrDefault(x => x.Code == (int)stop.ColorSpace); dbStop.Red = stop.Red; dbStop.Green = stop.Green; dbStop.Blue = stop.Blue; dbStop.L = stop.L; dbStop.A = stop.A; dbStop.B = stop.B; dbStop.BestMatchR = stop.BestMatchColor.R; dbStop.BestMatchG = stop.BestMatchColor.G; dbStop.BestMatchB = stop.BestMatchColor.B; dbStop.OffsetPercent = stop.OffsetPercent; dbStop.StopIndex = stop.StopIndex; dbStop.IsOutOfGamut = stop.IsOutOfGamut; stop.LiquidVolumes.SetVolumesOnBrushStop(dbStop); dbStop.ColorCatalog = stop.ColorCatalog; dbStop.ColorCatalogsItem = stop.ColorCatalogsItem; } _db.BrushStops.AddRange(brushStopList); } } } Job.LastUpdated = DateTime.UtcNow; Job.IsSynchronized = false; if (Job.JobStatus != JobStatuses.Draft) { JsonSerializerSettings settings = new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore, PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects }; string jsonJobModelSaved = JsonConvert.SerializeObject(JobModel, Formatting.Indented, settings); var json1 = JObject.Parse(_jsonJobModelLoaded); var json2 = JObject.Parse(jsonJobModelSaved); if (false == JToken.DeepEquals(json1, json2)) Job.JobStatus = BL.Enumerations.JobStatuses.Draft; } RaiseMessage(new JobSavedMessage() { Job = Job }); await _db.SaveChangesAsync(); JsonSerializerSettings settings1 = new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore, PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects }; _jsonJobModelLoaded = JsonConvert.SerializeObject(JobModel, Formatting.Indented, settings1); } #endregion #region Machine Operator Events private void MachineOperator_PrintingStarted(object sender, PrintingEventArgs e) { RaisePropertyChanged(nameof(CanEdit)); InvokeUI(() => { DropResumeCommand.RaiseCanExecuteChanged(); }); } private void MachineOperator_PrintingEnded(object sender, Integration.Operation.PrintingEventArgs e) { if (IsVisible) { _start_printing_btn.Push(); } RaisePropertyChanged(nameof(CanEdit)); InvokeUI(() => { DropResumeCommand.RaiseCanExecuteChanged(); }); } #endregion #region Resume private void JobResumeManager_JobResumeUpdated(object sender, Common.Resume.JobResumeUpdatedEventArgs e) { if (Job.Guid == e.JobGuid) { ResumeModel = e.ResumeModel; } } private void JobResumeManager_JobResumeDropped(object sender, Common.Resume.JobResumeDroppedEventArgs e) { if (Job.Guid == e.JobGuid) { ResumeModel = null; } } private async void DropResume() { if (Job != null && HasResumeModel) { if (await NotificationProvider.ShowQuestion("Are you sure you want to Edit the Job?" + System.Environment.NewLine + "Job progress data will reset.")) { JobResumeManager.DropResume(Job.Guid); } } } #endregion } }