diff options
Diffstat (limited to 'Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels')
5 files changed, 400 insertions, 146 deletions
diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs index 103a10b28..8d5bd284d 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobProgressViewVM.cs @@ -6,8 +6,10 @@ using System.Threading.Tasks; using Tango.BL.Entities; using Tango.Core.Commands; using Tango.Integration.Operation; +using Tango.PMR.Printing; using Tango.PPC.Common; using Tango.PPC.Common.Navigation; +using Tango.PPC.Common.Notifications; using Tango.PPC.Jobs.AppBarItems; using Tango.PPC.Jobs.AppButtons; using Tango.PPC.Jobs.Dialogs; @@ -47,6 +49,26 @@ namespace Tango.PPC.Jobs.ViewModels set { _runningJobStatus = value; RaisePropertyChangedAuto(); } } + private bool _isDisplayJobOutline; + /// <summary> + /// Gets or sets a value indicating whether to display the job outline. + /// </summary> + public bool IsDisplayJobOutline + { + get { return _isDisplayJobOutline; } + set { _isDisplayJobOutline = value; RaisePropertyChangedAuto(); } + } + + private JobTicket _jobOutlineTicket; + /// <summary> + /// Gets or sets the job outline ticket. + /// </summary> + public JobTicket JobOutlineTicket + { + get { return _jobOutlineTicket; } + set { _jobOutlineTicket = value; RaisePropertyChangedAuto(); } + } + #endregion #region Commands @@ -59,6 +81,16 @@ namespace Tango.PPC.Jobs.ViewModels /// </value> public RelayCommand GoToJobCommand { get; set; } + /// <summary> + /// Gets or sets the display job outline command. + /// </summary> + public RelayCommand DisplayJobOutlineCommand { get; set; } + + /// <summary> + /// Gets or sets the hide job outline command. + /// </summary> + public RelayCommand HideJobOutlineCommand { get; set; } + #endregion public JobProgressViewVM() @@ -67,14 +99,21 @@ namespace Tango.PPC.Jobs.ViewModels _stop_job_btn.Pressed += _stop_job_btn_Pressed; GoToJobCommand = new RelayCommand(GoToJob); + DisplayJobOutlineCommand = new RelayCommand(DisplayJobOutline); + HideJobOutlineCommand = new RelayCommand(HideJobOutline); } - private void _stop_job_btn_Pressed() + #region Private Methods + + private void HideJobOutline() { - if (_handler != null) - { - _handler.Cancel(); - } + IsDisplayJobOutline = false; + } + + private void DisplayJobOutline() + { + JobOutlineTicket = _handler.JobTicket; + IsDisplayJobOutline = true; } private void GoToJob() @@ -83,6 +122,8 @@ namespace Tango.PPC.Jobs.ViewModels NavigationManager.ClearHistoryExcept<JobsView>(); } + #endregion + #region Override Methods /// <summary> @@ -94,41 +135,32 @@ namespace Tango.PPC.Jobs.ViewModels } /// <summary> - /// Called when the navigation system has navigated from this VM view. - /// </summary> - public override void OnNavigatedFrom() - { - base.OnNavigatedFrom(); - - if (MachineProvider.MachineOperator.IsPrinting && _handler != null && !_handler.IsCanceled) - { - NotificationProvider.PushAppBarItem<JobProgressAppBarItem>().Pressed += (_, __) => - { - NotificationProvider.CurrentAppBarItem.Close(); - NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView)); - }; - } - } - - /// <summary> /// Called when the navigation system has navigated to this VM view. /// </summary> public override void OnNavigatedTo() { base.OnNavigatedTo(); - if (NotificationProvider.HasAppBarItem && NotificationProvider.CurrentAppBarItem is JobProgressAppBarItem) + IsDisplayJobOutline = false; + + if (_handler != null && !_handler.Status.IsFailed) { - NotificationProvider.CurrentAppBarItem.Close(); + _stop_job_btn.Push(); } - - _stop_job_btn.Push(); } #endregion #region Event Handlers + private void _stop_job_btn_Pressed() + { + if (_handler != null) + { + _handler.Cancel(); + } + } + /// <summary> /// Handles the PrintingStarted event of the MachineOperator. /// </summary> @@ -141,8 +173,10 @@ namespace Tango.PPC.Jobs.ViewModels e.JobHandler.StatusChanged += JobHandler_StatusChanged; e.JobHandler.SpoolChangeRequired += JobHandler_SpoolChangeRequired; e.JobHandler.Stopped += JobHandler_Stopped; + e.JobHandler.CanCancelChanged += JobHandler_CanCancelChanged; _stop_job_btn.Push(); + _stop_job_btn.IsEnabled = true; } /// <summary> @@ -172,12 +206,18 @@ namespace Tango.PPC.Jobs.ViewModels /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> private void JobHandler_Stopped(object sender, EventArgs e) { - if (NotificationProvider.HasAppBarItem && NotificationProvider.CurrentAppBarItem is JobProgressAppBarItem) + if (_stop_job_btn != null) { - NotificationProvider.CurrentAppBarItem.Close(); + _stop_job_btn.Pop(); } - _stop_job_btn.Pop(); + if (_handler != null) + { + _handler.StatusChanged -= JobHandler_StatusChanged; + _handler.SpoolChangeRequired -= JobHandler_SpoolChangeRequired; + _handler.Stopped -= JobHandler_Stopped; + _handler.CanCancelChanged -= JobHandler_CanCancelChanged; + } } /// <summary> @@ -193,6 +233,16 @@ namespace Tango.PPC.Jobs.ViewModels }); } + /// <summary> + /// Handles the CanCancelChanged event of the JobHandler control. + /// </summary> + /// <param name="sender">The source of the event.</param> + /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> + private void JobHandler_CanCancelChanged(object sender, EventArgs e) + { + _stop_job_btn.IsEnabled = _handler.CanCancel; + } + #endregion } } diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs index bff6beff5..a2acf5893 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobSummeryViewVM.cs @@ -26,6 +26,7 @@ namespace Tango.PPC.Jobs.ViewModels { private ObservablesContext _context; private bool _canStartJob; + private bool _startingJob; private bool _isPreparingJob; /// <summary> @@ -59,7 +60,6 @@ namespace Tango.PPC.Jobs.ViewModels set { _estimatedDuration = value; RaisePropertyChangedAuto(); } } - /// <summary> /// Gets or sets the dye command. /// </summary> @@ -96,12 +96,20 @@ namespace Tango.PPC.Jobs.ViewModels /// </summary> private async void StartJob() { + if (_startingJob) return; + + _startingJob = true; + _canStartJob = false; + InvalidateRelayCommands(); + NavigationManager.IsBackEnabled = false; + try { LogManager.Log("Start job command pressed. Starting job and navigating to job progress view..."); await PrintingManager.Print(Job, _context); await NavigationManager.NavigateTo<JobsModule>(false, nameof(JobProgressView)); + _startingJob = false; } catch (InsufficientLiquidQuantityException) { @@ -112,6 +120,13 @@ namespace Tango.PPC.Jobs.ViewModels LogManager.Log(ex, "Could not start the current job."); await NotificationProvider.ShowError($"{ex.Message}"); } + finally + { + _startingJob = false; + _canStartJob = true; + NavigationManager.IsBackEnabled = true; + InvalidateRelayCommands(); + } } /// <summary> @@ -130,16 +145,6 @@ namespace Tango.PPC.Jobs.ViewModels _context = obj.Context; Job = obj.Job; - if (Job.ColorSpace.Space == BL.Enumerations.ColorSpaces.Catalog) - { - if (_context.ColorCatalogs.SingleOrDefault(x => x.Guid == Job.ColorCatalogGuid) == null) - { - await NotificationProvider.ShowError("The selected color catalog for this job could not be found.\nCannot load job."); - await NavigationManager.NavigateBack(); - return; - } - } - IsPreparingJob = true; Job = await new JobBuilder(_context).Set(Job.Guid) @@ -150,7 +155,15 @@ namespace Tango.PPC.Jobs.ViewModels .WithBrushStops() .BuildAsync(); - await Task.Delay(2000); + if (Job.ColorSpace.Space == BL.Enumerations.ColorSpaces.Catalog) + { + if (_context.ColorCatalogs.SingleOrDefault(x => x.Guid == Job.ColorCatalogGuid) == null) + { + await NotificationProvider.ShowError("The selected color catalog for this job could not be found.\nCannot load job."); + await NavigationManager.NavigateBack(); + return; + } + } await Task.Factory.StartNew(() => { diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs index 4e1e58dba..5e90d3b5b 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobViewVM.cs @@ -56,6 +56,7 @@ namespace Tango.PPC.Jobs.ViewModels private ActionTimer _volumeConversionTimer; private IColorConverter _converter; private string _current_job_string; + private bool startingJob = false; #region Properties @@ -412,7 +413,7 @@ namespace Tango.PPC.Jobs.ViewModels RepeatSampleDyeCommand = new RelayCommand(RepeatSampleDye); AnotherSampleCommand = new RelayCommand(DyeAnotherSample); InvokeFineTuningPaletteCommand = new RelayCommand<FineTuneItem>(InvokeFineTuningPalette); - ResetFineTuningCommand = new RelayCommand(ResetFineTuning); + ResetFineTuningCommand = new RelayCommand(() => ResetFineTuning(true)); StartFineTuningCommand = new RelayCommand(StartFineTuning, () => FineTuneItems.Any(x => x.IsSelected) && CanStartJob()); RepeatFineTuningCommand = new RelayCommand(RepeatFineTuning); ApproveFineTuningCommand = new RelayCommand(ApproveFineTuning); @@ -468,7 +469,7 @@ namespace Tango.PPC.Jobs.ViewModels Job.ValidateOnPropertyChanged = true; LogManager.Log("Loading RMLS..."); - Rmls = (await new RmlsCollectionBuilder(_db).SetAll().WithActiveParametersGroup().WithCAT(Job.MachineGuid).WithCCT().WithLiquidFactors().BuildAsync()).ToList(); + Rmls = (await new RmlsCollectionBuilder(_db).SetAll().WithActiveParametersGroup().WithCAT(Job.MachineGuid).WithCCT().WithLiquidFactors().WithSpools().ForHeadType(MachineProvider.Machine.MachineHeadType).ForSite(MachineProvider.Machine.SiteGuid).BuildAsync()).ToList(); LogManager.Log("Loading Color Spaces..."); ColorSpaces = await _db.ColorSpaces.ToListAsync(); LogManager.Log("Loading Spool Types..."); @@ -478,7 +479,7 @@ namespace Tango.PPC.Jobs.ViewModels if (Job.ColorSpace.Space == BL.Enumerations.ColorSpaces.Catalog) { - SelectedCatalog = await new ColorCatalogBuilder(_db).Set(Job.ColorCatalogGuid).WithGroups().WithItems().BuildAsync(); + SelectedCatalog = await new CatalogBuilder(_db).Set(Job.ColorCatalogGuid).WithGroups().WithItems().BuildAsync(); if (SelectedCatalog != null) { @@ -545,18 +546,15 @@ namespace Tango.PPC.Jobs.ViewModels } catch (Exception ex) { - LogManager.Log(ex, $"Error loading job '{_job_to_load.Name}'"); + 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 { - InvokeUI(() => - { - IsFree = true; - //NotificationProvider.ReleaseGlobalBusyMessage(); - }); + IsFree = true; } } @@ -593,7 +591,9 @@ namespace Tango.PPC.Jobs.ViewModels } Job.LastUpdated = DateTime.UtcNow; + Job.IsSynchronized = false; Job.JobStatus = BL.Enumerations.JobStatuses.Draft; + Job.MarkModified(_db); await _db.SaveChangesAsync(); _current_job_string = Job.ToJobFileWhenLoaded().ToString(); @@ -645,11 +645,16 @@ namespace Tango.PPC.Jobs.ViewModels /// </summary> 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 PrintingManager.Print(Job, _db); + var handler = await PrintingManager.Print(Job, _db); await NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView)); + startingJob = false; } catch (InsufficientLiquidQuantityException) { @@ -660,6 +665,10 @@ namespace Tango.PPC.Jobs.ViewModels LogManager.Log(ex, "Could not start the current job."); await NotificationProvider.ShowError($"{ex.Message}."); } + finally + { + startingJob = false; + } } /// <summary> @@ -668,8 +677,7 @@ namespace Tango.PPC.Jobs.ViewModels private bool CanStartJob() { return - Job != null && Job.Validate(_db) && - !Job.Segments.SelectMany(x => x.BrushStops).ToList().Exists(x => x.IsOutOfGamut); + Job != null && Job.Validate(_db) && !Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.IsTransparent && !x.IsWhite).ToList().Exists(x => x.IsOutOfGamut || x.IsLiquidVolumesOutOfRange); } #endregion @@ -709,7 +717,7 @@ namespace Tango.PPC.Jobs.ViewModels try { LogManager.Log("Adding new solid segment..."); - var s = Job.AddSolidSegment(MachineProvider.Machine.DefaultSegmentLength > 0 ? MachineProvider.Machine.DefaultSegmentLength : 10); + var s = Job.AddSolidSegment(Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 10); SetSegmentLiquidVolumesIfVolume(s); return s; } @@ -729,7 +737,7 @@ namespace Tango.PPC.Jobs.ViewModels try { LogManager.Log("Adding new gradient segment..."); - var s = Job.AddGradientSegment(MachineProvider.Machine.DefaultSegmentLength > 0 ? MachineProvider.Machine.DefaultSegmentLength : 10); + var s = Job.AddGradientSegment(Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 10); SetSegmentLiquidVolumesIfVolume(s); return s; } @@ -759,14 +767,7 @@ namespace Tango.PPC.Jobs.ViewModels draggedSegment.SegmentIndex = droppedSegment.SegmentIndex + 1; } - int index = 1; - - foreach (var segment in Job.Segments.OrderBy(x => x.SegmentIndex)) - { - segment.SegmentIndex = index++; - } - - SegmentsCollectionView.Refresh(); + ArrangeSegmentsIndices(); } /// <summary> @@ -829,10 +830,14 @@ namespace Tango.PPC.Jobs.ViewModels private void ArrangeSegmentsIndices() { - for (int i = 0; i < Job.Segments.Count; i++) + int index = 1; + + foreach (var segment in Job.Segments.OrderBy(x => x.SegmentIndex)) { - Job.Segments[i].SegmentIndex = i + 1; + segment.SegmentIndex = index++; } + + SegmentsCollectionView.Refresh(); } #endregion @@ -880,23 +885,55 @@ namespace Tango.PPC.Jobs.ViewModels LogManager.Log($"Invoking triplet color adjustment dialog for brush stop {brushStop.StopIndex} at segment {brushStop.Segment.SegmentIndex}."); LogManager.Log("Retrieving color conversion suggestions for brush stop..."); - var conversionOutput = _converter.Convert(brushStop, true); + PMR.ColorLab.ConversionOutput conversionOutput = null; + + if (brushStop.IsOutOfGamut) + { + conversionOutput = _converter.Convert(brushStop, false); + } BasicColorCorrectionViewVM vm = null; + List<ColorConversionSuggestion> suggestions = null; - vm = await NotificationProvider.ShowDialog<BasicColorCorrectionViewVM>(new BasicColorCorrectionViewVM() + if (brushStop.IsOutOfGamut) { - InvalidBrushStop = brushStop, - Suggestions = conversionOutput.CreateTrippletSuggestions(), - }); + vm = await NotificationProvider.ShowDialog<BasicColorCorrectionViewVM>(new BasicColorCorrectionViewVM() + { + InvalidBrushStop = brushStop, + Suggestions = new List<ColorConversionSuggestion>() { new ColorConversionSuggestion(conversionOutput.SingleCoordinates, 0, 0) }, + }); + } - if (vm.Result == BasicColorCorrectionViewVM.ColorCorrectionDialogResult.MoreOptions) + if (vm == null || vm.Result == BasicColorCorrectionViewVM.ColorCorrectionDialogResult.MoreOptions) { + NotificationProvider.SetGlobalBusyMessage("Generating color hive..."); + + await Task.Factory.StartNew(() => + { + conversionOutput = _converter.Convert(brushStop, true); + + suggestions = conversionOutput.CreateHiveSuggestions(); + + if (vm == null) + { + var center = suggestions.GetCenterSuggestion(); + center.Coordinates.Red = brushStop.Red; + center.Coordinates.Green = brushStop.Green; + center.Coordinates.Blue = brushStop.Blue; + + center.Coordinates.L = brushStop.L; + center.Coordinates.A = brushStop.A; + center.Coordinates.B = brushStop.B; + } + }); + + NotificationProvider.ReleaseGlobalBusyMessage(); LogManager.Log("Invoking hive color conversion dialog..."); vm = await NotificationProvider.ShowDialog<AdvancedColorCorrectionViewVM>(new AdvancedColorCorrectionViewVM() { InvalidBrushStop = brushStop, - Suggestions = conversionOutput.CreateHiveSuggestions(), + Suggestions = suggestions, + IsOutOfGamut = brushStop.IsOutOfGamut, }); } @@ -916,6 +953,13 @@ namespace Tango.PPC.Jobs.ViewModels brushStop.A = vm.SelectedSuggestion.Coordinates.A; brushStop.B = vm.SelectedSuggestion.Coordinates.B; } + else if (brushStop.BrushColorSpace == BL.Enumerations.ColorSpaces.Volume) + { + if (vm.SelectedSuggestion != suggestions.GetCenterSuggestion()) + { + vm.SelectedSuggestion.ApplyOnBrushStop(brushStop); + } + } brushStop.Corrected = true; brushStop.IsOutOfGamut = false; @@ -927,6 +971,11 @@ namespace Tango.PPC.Jobs.ViewModels LogManager.Log(ex, "Error while invoking color adjustment dialog."); await NotificationProvider.ShowError("An error occurred while trying to convert the selected color."); } + finally + { + NotificationProvider.ReleaseGlobalBusyMessage(); + DyeCommand.RaiseCanExecuteChanged(); + } } /// <summary> @@ -936,7 +985,7 @@ namespace Tango.PPC.Jobs.ViewModels [HandleProcessCorruptedStateExceptions] public void OnBrushStopFieldValueChanged(BrushStop stop) { - if (stop != null) + if (stop != null && stop.ColorSpace != null) { stop.Corrected = false; stop.OutOfGamutChecked = false; @@ -954,6 +1003,11 @@ namespace Tango.PPC.Jobs.ViewModels stop.Blue = output.SingleCoordinates.Blue; stop.Corrected = true; stop.IsOutOfGamut = false; + + InvokeUI(() => + { + DyeCommand.RaiseCanExecuteChanged(); + }); } catch (Exception ex) { @@ -1074,7 +1128,7 @@ namespace Tango.PPC.Jobs.ViewModels /// <summary> /// Synchronizes the fine tune items to brush stops. /// </summary> - private void SyncFineTuneItemsToBrushStops() + private async void SyncFineTuneItemsToBrushStops(bool displayBusy = false) { try { @@ -1086,18 +1140,27 @@ namespace Tango.PPC.Jobs.ViewModels } else { + if (displayBusy) + { + NotificationProvider.SetGlobalBusyMessage("Generating suggestions..."); + } + FineTuneItems.Clear(); - foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).Where(x => x.ColorSpace.Space == BL.Enumerations.ColorSpaces.RGB || x.ColorSpace.Space == BL.Enumerations.ColorSpaces.LAB).DistinctBy(x => x.Color)) + foreach (var stop in Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.IsTransparent).Where(x => x.ColorSpace.Space == BL.Enumerations.ColorSpaces.RGB || x.ColorSpace.Space == BL.Enumerations.ColorSpaces.LAB).DistinctBy(x => x.Color)) { - FineTuneItem item = new FineTuneItem(_converter.Convert(stop, true)); + var conversionoutput = await _converter.ConvertAsync(stop, true); + FineTuneItem item = new FineTuneItem(conversionoutput); + item.BrushStop = stop; item.BrushStops = Job.Segments.SelectMany(x => x.BrushStops).Where(x => x.Color == stop.Color).ToList(); - item.SelectedSuggestion = item.Suggestions[item.Suggestions.Count / 2]; + item.SelectedSuggestion = item.Suggestions.GetCenterSuggestion(); item.SelectedChanged += () => StartFineTuningCommand.RaiseCanExecuteChanged(); FineTuneItems.Add(item); } _jobs_fine_tune_items[Job.Guid] = FineTuneItems.ToList(); + + NotificationProvider.ReleaseGlobalBusyMessage(); } ApprovalFineTuneItems = FineTuneItems.Where(x => x.IsSelected).ToObservableCollection(); @@ -1109,6 +1172,10 @@ namespace Tango.PPC.Jobs.ViewModels { LogManager.Log(ex, "Error while trying to synchronize fine tuning items with brush stops."); } + finally + { + NotificationProvider.ReleaseGlobalBusyMessage(); + } } /// <summary> @@ -1135,19 +1202,23 @@ namespace Tango.PPC.Jobs.ViewModels LogManager.Log(ex, "Error invoking the fine tunning palette"); await NotificationProvider.ShowError("An error occurred while trying to display the fine tunning palette."); } + finally + { + NotificationProvider.ReleaseGlobalBusyMessage(); + } } /// <summary> /// Resets the fine tuning. /// </summary> - private void ResetFineTuning() + private void ResetFineTuning(bool displayBusy = false) { if (Job != null && _jobs_fine_tune_items.ContainsKey(Job.Guid)) { _jobs_fine_tune_items.Remove(Job.Guid); } - SyncFineTuneItemsToBrushStops(); + SyncFineTuneItemsToBrushStops(displayBusy); } /// <summary> @@ -1357,6 +1428,8 @@ namespace Tango.PPC.Jobs.ViewModels { bool result = true; + if (!IsFree) return false; + if (!_can_navigate_back) { bool jobChainged = false; diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs index a7b06f6eb..64931cbe3 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs @@ -36,6 +36,9 @@ using System.Windows.Media.Imaging; using Tango.Touch.Components; using Tango.PPC.Jobs.ViewContracts; using Tango.Core.ExtensionMethods; +using Tango.PPC.Common.Synchronization; +using Tango.PPC.Jobs.NotificationItems; +using Tango.PPC.Storage.Models; namespace Tango.PPC.Jobs.ViewModels { @@ -46,7 +49,10 @@ namespace Tango.PPC.Jobs.ViewModels public class JobsViewVM : PPCViewModel<IJobsView> { private ObservablesContext _db; //Holds the db context for the job list. - private ObservableCollection<ColorCatalog> _catalogs; //Holds the available color catalogs. + private ObservableCollection<ColorCatalog> _catalogs; //Holds the available color catalogs for the site. + private ObservableCollection<Rml> _rmls; //Holds the available RML for the site. + private List<ColorSpace> _colorSpaces; //Holds the available color spaces. + private bool _isJobsSynchronizationNotificationActive; public enum JobsCategory { @@ -318,7 +324,7 @@ namespace Tango.PPC.Jobs.ViewModels RaiseMessage(new JobSelectedMessage() { Job = job, Context = _db }); - if (!directlyToEdit && MachineProvider.MachineOperator.Status == Integration.Operation.MachineStatuses.ReadyToDye) + if (!directlyToEdit && MachineProvider.MachineOperator.CanPrint) { await NavigationManager.NavigateWithObject<JobsModule, JobSummeryView, JobSummeryNavigationObject>(new JobSummeryNavigationObject() { @@ -349,6 +355,8 @@ namespace Tango.PPC.Jobs.ViewModels _db = ObservablesContext.CreateDefault(); + _colorSpaces = _db.ColorSpaces.ToList(); + var jobs = new JobsCollectionBuilder(_db).Set(x => x.MachineGuid == MachineProvider.Machine.Guid).WithSegments().WithBrushStops().WithCustomer().WithColorSpace().Build(); InvokeUI(() => @@ -407,10 +415,15 @@ namespace Tango.PPC.Jobs.ViewModels var machine = MachineProvider.Machine; JobCreationViewVM vm = new JobCreationViewVM( - machine.SupportedJobTypes.Count > 0 ? machine.SupportedJobTypes : Enum.GetValues(typeof(JobTypes)).Cast<JobTypes>().ToList(), - machine.SupportedColorSpaces.Count > 0 ? machine.SupportedColorSpaces : Enum.GetValues(typeof(ColorSpaces)).Cast<ColorSpaces>().Where(x => x.IsUserSpace() || (ApplicationManager.IsInTechnicianMode && x == ColorSpaces.Volume)).ToList() + Settings.SupportedJobTypes.Count > 0 ? Settings.SupportedJobTypes : Enum.GetValues(typeof(JobTypes)).Cast<JobTypes>().ToList(), + Settings.SupportedColorSpaces.Count > 0 ? Settings.SupportedColorSpaces : Enum.GetValues(typeof(ColorSpaces)).Cast<ColorSpaces>().Where(x => x.IsUserSpace() || (ApplicationManager.IsInTechnicianMode && x == ColorSpaces.Volume)).ToList() ); + if (_catalogs.Count == 0) + { + vm.SupportedColorSpaces.Remove(ColorSpaces.Catalog); + } + CatalogSelectionViewVM catalogVM = new CatalogSelectionViewVM(_catalogs.ToList(), _catalogs.ToList().SingleOrDefault(x => x.Guid == settings.LastSelectedCatalogGuid)); if (settings.LastJobType != null) @@ -419,7 +432,7 @@ namespace Tango.PPC.Jobs.ViewModels } else { - vm.SelectedJobType = machine.SupportedJobTypes.FirstOrDefault(); + vm.SelectedJobType = Settings.SupportedJobTypes.FirstOrDefault(); } if (settings.LastJobColorSpace != null) @@ -428,7 +441,7 @@ namespace Tango.PPC.Jobs.ViewModels } else { - var space = machine.SupportedColorSpaces.FirstOrDefault(); + var space = Settings.SupportedColorSpaces.FirstOrDefault(); vm.SelectedColorSpace = space.IsUserSpace() ? space : ColorSpaces.Catalog; } @@ -446,7 +459,7 @@ namespace Tango.PPC.Jobs.ViewModels if (twnFile == null) { - if (machine.SupportedJobTypes.Count != 1 || machine.SupportedColorSpaces.Count != 1) + if (Settings.SupportedJobTypes.Count != 1 || Settings.SupportedColorSpaces.Count != 1) { vm = await NotificationProvider.ShowDialog<JobCreationViewVM>(vm); if (!vm.DialogResult) return; @@ -476,14 +489,14 @@ namespace Tango.PPC.Jobs.ViewModels } else { - vm.SelectedJobType = machine.SupportedJobTypes.First(); - vm.SelectedColorSpace = machine.SupportedColorSpaces.First(); + vm.SelectedJobType = Settings.SupportedJobTypes.First(); + vm.SelectedColorSpace = Settings.SupportedColorSpaces.First(); } } settings.LastJobType = vm.SelectedJobType; settings.LastJobColorSpace = vm.SelectedColorSpace; - + if (vm.SelectedColorSpace == ColorSpaces.Catalog) { settings.LastSelectedCatalogGuid = catalogVM.SelectedCatalog.Guid; @@ -492,6 +505,8 @@ namespace Tango.PPC.Jobs.ViewModels settings.Save(); Job job = new Job(); + job.LastUpdated = DateTime.UtcNow; + job.JobSource = JobSource.Local; job.Name = "untitled"; job.NumberOfHeads = 1; job.NumberOfUnits = 1; @@ -501,11 +516,12 @@ namespace Tango.PPC.Jobs.ViewModels job.JobType = vm.SelectedJobType; job.EnableLubrication = true; job.ColorSpaceGuid = Adapter.ColorSpaces.FirstOrDefault(x => x.Code == vm.SelectedColorSpace.ToInt32()).Guid; + job.ColorSpace = _colorSpaces.SingleOrDefault(x => x.Guid == job.ColorSpaceGuid); job.MachineGuid = MachineProvider.Machine.Guid; - job.UserGuid = AuthenticationProvider.CurrentUser.Guid; - job.RmlGuid = machine.DefaultRml != null ? machine.DefaultRmlGuid : Adapter.Rmls.FirstOrDefault().Guid; + job.UserGuid = null; + job.RmlGuid = (Settings.DefaultRmlGuid != null && _rmls.Select(x => x.Guid).Contains(Settings.DefaultRmlGuid)) ? Settings.DefaultRmlGuid : _rmls.FirstOrDefault().Guid; job.WindingMethodGuid = Adapter.WindingMethods.FirstOrDefault().Guid; - job.SpoolTypeGuid = machine.DefaultSpoolType != null ? machine.DefaultSpoolTypeGuid : Adapter.SpoolTypes.FirstOrDefault().Guid; + job.SpoolTypeGuid = Settings.DefaultSpoolTypeGuid != null ? Settings.DefaultSpoolTypeGuid : Adapter.SpoolTypes.FirstOrDefault().Guid; if (vm.SelectedColorSpace == ColorSpaces.Catalog) { @@ -519,11 +535,11 @@ namespace Tango.PPC.Jobs.ViewModels if (colorProfile == null) { - job.AddSolidSegment(machine.DefaultSegmentLength > 0 ? machine.DefaultSegmentLength : 100); + job.AddSolidSegment(Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 100); } else { - job.AddSolidSegment(colorProfile.Value, machine.DefaultSegmentLength > 0 ? machine.DefaultSegmentLength : 100); + job.AddSolidSegment(colorProfile.Value, Settings.DefaultSegmentLength > 0 ? Settings.DefaultSegmentLength : 100); job.Name = $"SnapMatch {colorProfile.Value.R}, {colorProfile.Value.G}, {colorProfile.Value.B}"; } @@ -724,10 +740,13 @@ namespace Tango.PPC.Jobs.ViewModels StorageProvider.RegisterFileHandler(ExplorerFileDefinition.Pulse.Extension, HandlePulseFileLoaded); //Load catalogs. - using (ObservablesContext c = ObservablesContext.CreateDefault()) + using (ObservablesContext db = ObservablesContext.CreateDefault()) { - _catalogs = (await c.ColorCatalogs.ToListAsync()).ToObservableCollection(); + _catalogs = await new CatalogsCollectionBuilder(db).SetAll().ForSite(MachineProvider.Machine.SiteGuid).BuildAsync(); + _rmls = await new RmlsCollectionBuilder(db).SetAll().ForHeadType(MachineProvider.Machine.MachineHeadType).ForSite(MachineProvider.Machine.SiteGuid).BuildAsync(); } + + MachineDataSynchronizer.SynchronizationEnded += MachineDataSynchronizer_SynchronizationEnded; } public override void OnNavigatedTo() @@ -745,37 +764,64 @@ namespace Tango.PPC.Jobs.ViewModels var selected_job = SelectedJobs.FirstOrDefault(); if (selected_job == null) return; + var selectedJobs = SelectedJobs.ToList(); + ClearSelection(); var result = await NavigationManager. NavigateForResult<StorageModule, Storage.Views.MainView, ExplorerFileItem, - Storage.Models.StorageNavigationRequest>( - new Storage.Models.StorageNavigationRequest() + StorageNavigationRequest>( + new StorageNavigationRequest() { - Intent = Storage.Models.StorageNavigationIntent.SaveFile, + Intent = selectedJobs.Count == 1 ? StorageNavigationIntent.SaveFile : StorageNavigationIntent.SaveFiles, DefaultFileName = selected_job.Name, Filter = ExplorerFileDefinition.Job.Extension, - Title = "Save Job File", + Title = selectedJobs.Count == 1 ? "Save Job File" : "Save Job Files", }); if (result != null) { - try + if (selectedJobs.Count == 1) { - var jobFile = await selected_job.ToJobFile(); + try + { + var jobFile = await selected_job.ToJobFile(); - using (FileStream fs = new FileStream(result.Path + ExplorerFileDefinition.Job.Extension, FileMode.Create)) + using (FileStream fs = new FileStream(result.Path + ExplorerFileDefinition.Job.Extension, FileMode.Create)) + { + jobFile.WriteTo(fs); + } + + await NotificationProvider.ShowSuccess("Job saved successfully."); + } + catch (Exception ex) { - jobFile.WriteTo(fs); + LogManager.Log(ex, $"Error saving job {selected_job.Name} to file."); + await NotificationProvider.ShowError($"An error occurred while trying to save the job.\n{ex.Message}"); } - - await NotificationProvider.ShowSuccess("Job saved successfully."); } - catch (Exception ex) + else { - LogManager.Log(ex, $"Error saving job {selected_job.Name} to file."); - await NotificationProvider.ShowError($"An error occurred while trying to save the job.\n{ex.Message}"); + foreach (var job in selectedJobs) + { + try + { + var jobFile = await job.ToJobFile(); + + using (FileStream fs = new FileStream(Path.Combine(result.Path, jobFile.Name.ToValidFileName()) + ExplorerFileDefinition.Job.Extension, FileMode.Create)) + { + jobFile.WriteTo(fs); + } + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error saving job {job.Name} to file."); + await NotificationProvider.ShowError($"An error occurred while trying to save the job.\n{ex.Message}"); + } + } + + await NotificationProvider.ShowSuccess("Jobs saved successfully."); } } } @@ -784,7 +830,7 @@ namespace Tango.PPC.Jobs.ViewModels #region Handle Job File Loading From Storage - private async void HandleJobFileLoaded(ExplorerFileItem jobFile) + private async void HandleJobFileLoaded(List<ExplorerFileItem> jobFiles) { var vm = await NotificationProvider.ShowDialog<ImportJobViewVM>(); @@ -792,29 +838,35 @@ namespace Tango.PPC.Jobs.ViewModels { using (ObservablesContext jobContext = ObservablesContext.CreateDefault()) { - try + foreach (var jobFile in jobFiles) { - JobFile jFile = JobFile.Parser.ParseFrom(File.ReadAllBytes(jobFile.Path)); - var job = await Job.FromJobFile(jFile, MachineProvider.Machine.Guid, AuthenticationProvider.CurrentUser.Guid); - jobContext.Jobs.Add(job); - await jobContext.SaveChangesAsync(); - LoadJobs(() => + try { - if (vm.ImportAndEdit) - { - var postJob = Jobs.SingleOrDefault(x => x.Guid == job.Guid); - if (postJob != null) - { - SelectJob(postJob, true); - } - } - }); + JobFile jFile = JobFile.Parser.ParseFrom(File.ReadAllBytes(jobFile.Path)); + var job = await Job.FromJobFile(jFile, MachineProvider.Machine.Guid, null); + job.JobSource = JobSource.Local; + jobContext.Jobs.Add(job); + await jobContext.SaveChangesAsync(); + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error occurred while trying to import job from file {jobFile.Path}."); + await NotificationProvider.ShowError($"An error occurred while trying to import the selected job file.\n{ex.Message}"); + } } - catch (Exception ex) + + LoadJobs(() => { - LogManager.Log(ex, $"Error occurred while trying to import job from file {jobFile.Path}."); - await NotificationProvider.ShowError($"An error occurred while trying to import the selected job file.\n{ex.Message}"); - } + //Editing of a job is currently deprecated due to enabling multiple job imports. + //if (vm.ImportAndEdit) + //{ + // var postJob = Jobs.SingleOrDefault(x => x.Guid == job.Guid); + // if (postJob != null) + // { + // SelectJob(postJob, true); + // } + //} + }); } } } @@ -823,8 +875,10 @@ namespace Tango.PPC.Jobs.ViewModels #region Handle TCC File Loading From Storage - private async void HandleColorProfileFileLoaded(ExplorerFileItem tccFile) + private async void HandleColorProfileFileLoaded(List<ExplorerFileItem> tccFiles) { + var tccFile = tccFiles.FirstOrDefault(); + try { DetectionColorFile tcc = DetectionColorFile.Parser.ParseFrom(File.ReadAllBytes(tccFile.Path)); @@ -853,8 +907,10 @@ namespace Tango.PPC.Jobs.ViewModels #region Handle Pulse TWN Loading From Storage - private async void HandlePulseFileLoaded(ExplorerFileItem twnFile) + private async void HandlePulseFileLoaded(List<ExplorerFileItem> twnFiles) { + var twnFile = twnFiles.FirstOrDefault(); + TwnFile twn = TwnFile.FromFile(twnFile.Path); BitmapSource preview = twn.Thumbnail.ToBitmapSource(); @@ -871,6 +927,32 @@ namespace Tango.PPC.Jobs.ViewModels #endregion + #region Handle New Synchronized Jobs + + private void MachineDataSynchronizer_SynchronizationEnded(object sender, SynchronizationEndedEventArgs e) + { + if (e.NewChangedJobs > 0 && !_isJobsSynchronizationNotificationActive) + { + _isJobsSynchronizationNotificationActive = true; + + var item = NotificationProvider.PushNotification<NewSynchronizardJobsNotificationItem>(); + item.Pressed += (_, __) => + { + _isJobsSynchronizationNotificationActive = false; + LoadJobs(() => + { + NotificationProvider.ShowSuccess("Your job list is now synchronized."); + }); + }; + item.Closed += (_, __) => + { + _isJobsSynchronizationNotificationActive = false; + }; + } + } + + #endregion + #region Color Profile Request private void ExternalBridgeService_ColorProfileRequest(object sender, ColorProfileRequestEventArgs e) diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs index ed1e28f55..579e1e2f7 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/MainViewVM.cs @@ -11,6 +11,7 @@ using Tango.Integration.Operation; using Tango.PPC.Common; using Tango.PPC.Common.Notifications; using Tango.PPC.Common.Notifications.NotificationItems; +using Tango.PPC.Jobs.AppBarItems; using Tango.PPC.Jobs.Messages; using Tango.PPC.Jobs.NavigationObjects; using Tango.PPC.Jobs.Views; @@ -24,6 +25,9 @@ namespace Tango.PPC.Jobs.ViewModels public class MainViewVM : PPCViewModel { private NotificationItem _last_failed_job_notification; + private JobHandler _handler; + private bool resuming; + private JobProgressAppBarItem _appBarItem; /// <summary> /// Called when the application has been started. @@ -33,23 +37,42 @@ namespace Tango.PPC.Jobs.ViewModels MachineProvider.MachineOperator.PrintingCompleted += MachineOperator_PrintingCompleted; MachineProvider.MachineOperator.PrintingFailed += MachineOperator_PrintingFailed; MachineProvider.MachineOperator.ResumingJob += MachineOperator_ResumingJob; + MachineProvider.MachineOperator.PrintingStarted += MachineOperator_PrintingStarted; + MachineProvider.MachineOperator.PrintingEnded += MachineOperator_PrintingEnded; + NavigationManager.CurrentVMChanged += NavigationManager_CurrentVMChanged; } - private async void MachineOperator_ResumingJob(object sender, ResumingJobEventArgs e) + private void MachineOperator_PrintingEnded(object sender, PrintingEventArgs e) { - LogManager.Log($"Trying to resume job '{e.JobGuid}'..."); + _appBarItem?.Close(); + _appBarItem = null; + } - try + private void NavigationManager_CurrentVMChanged(object sender, PPCViewModel vm) + { + if (vm.GetType() == typeof(JobProgressViewVM)) { - var job = await new JobBuilder(ObservablesContext.CreateDefault()).Set(e.JobGuid) - .WithConfiguration() - .WithRML() - .WithUser() - .WithSegments() - .WithBrushStops() - .BuildAsync(); + _appBarItem?.Close(); + _appBarItem = null; + } + else if (vm.GetType() != typeof(JobSummeryViewVM) && _appBarItem == null && MachineProvider.MachineOperator.IsPrinting && _handler != null && !_handler.IsCanceled) + { + _appBarItem = NotificationProvider.PushAppBarItem<JobProgressAppBarItem>(); + _appBarItem.Pressed += (_, __) => + { + _appBarItem?.Close(); + NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView)); + }; + } + } - e.Approve(job); + private void MachineOperator_PrintingStarted(object sender, PrintingEventArgs e) + { + _handler = e.JobHandler; + + if (resuming) + { + resuming = false; InvokeUI(() => { @@ -62,6 +85,17 @@ namespace Tango.PPC.Jobs.ViewModels } }); } + } + + private void MachineOperator_ResumingJob(object sender, ResumingJobEventArgs e) + { + LogManager.Log($"Job resume request '{e.JobGuid}' approving..."); + + try + { + e.Approve(); + resuming = true; + } catch (Exception ex) { LogManager.Log(ex, "An error occurred while trying to resume the job."); @@ -79,13 +113,15 @@ namespace Tango.PPC.Jobs.ViewModels /// <param name="e">The <see cref="Integration.Operation.PrintingFailedEventArgs"/> instance containing the event data.</param> private void MachineOperator_PrintingFailed(object sender, PrintingFailedEventArgs e) { + String message = $"{e.Exception.FlattenMessage()}"; + _last_failed_job_notification = NotificationProvider.PushNotification(new MessageNotificationItem( - String.Format("'{0}' failed.", e.Job.Name), - String.Format("The job '{1}' has failed due to unexpected error.{0}{2}{0}{0}Tap to view this job details.", Environment.NewLine, e.Job.Name, e.Exception), MessageNotificationItem.MessageNotificationItemTypes.Error, () => + $"'{e.Job.Name}' failed at position {e.JobHandler.Status.ProgressMinusSettingUp.ToString("0.0")} out of {e.JobHandler.Status.TotalProgressMinusSettingUp.ToString("0.0")} meters.", + message, MessageNotificationItem.MessageNotificationItemTypes.Error, () => { NavigationManager.NavigateWithObject<JobsModule, JobView, Job>(e.Job); NavigationManager.ClearHistoryExcept<JobsView>(); - })); + }, NotificationItem.NotificationPriority.VeryHigh)); } /// <summary> @@ -119,7 +155,7 @@ namespace Tango.PPC.Jobs.ViewModels { NavigationManager.NavigateWithObject<JobsModule, JobView, JobNavigationObject>(new JobNavigationObject() { Job = e.Job }); NavigationManager.ClearHistoryExcept<JobsView>(); - })); + }, NotificationItem.NotificationPriority.VeryHigh)); } } |
