aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.CodeGeneration/CustomResolver.cs
blob: ee1acccae7b28756ddde504c7d17d7ca3435e205 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
using RazorEngine.Compilation;
using RazorEngine.Compilation.ReferenceResolver;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tango.CodeGeneration
{
    internal class CustomResolver : IReferenceResolver
    {
        public IEnumerable<CompilerReference> GetReferences(TypeContext context, IEnumerable<CompilerReference> includeAssemblies)
        {
            return new UseCurrentAssembliesReferenceResolver()
                        .GetReferences(context, includeAssemblies)
                        .Where(f => !f.GetFile().EndsWith(".winmd"));
        }
    }
}
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 Tango.BL.Catalogs;
using System.Runtime.InteropServices;
using System.Threading;
using Tango.BL.ColorConversion;
using Tango.SharedUI.Helpers;
using Tango.PPC.Common.Navigation;

namespace Tango.PPC.Jobs.ViewModels
{
    /// <summary>
    /// Represents the selected job view model.
    /// </summary>
    /// <seealso cref="Tango.PPC.Common.PPCViewModel" />
    public class JobViewVM : PPCViewModel, INavigationObjectReceiver<Job>
    {
        private ObservablesContext _db;
        private bool _can_navigate_back;
        private Thread _check_gamut_thread;
        private Job _job_to_load;

        #region Properties

        private Job _job;
        /// <summary>
        /// Gets or sets the selected job.
        /// </summary>
        public Job Job
        {
            get { return _job; }
            set { _job = value; RaisePropertyChangedAuto(); }
        }

        private ICollectionView _segmentsCollectionView;
        /// <summary>
        /// Gets or sets the job segments collection view.
        /// </summary>
        public ICollectionView SegmentsCollectionView
        {
            get { return _segmentsCollectionView; }
            set
            {
                _segmentsCollectionView = value;
                RaisePropertyChangedAuto();
            }
        }

        private List<ColorSpace> _colorSpaces;
        /// <summary>
        /// Gets or sets the available color spaces.
        /// </summary>
        public List<ColorSpace> ColorSpaces
        {
            get { return _colorSpaces; }
            set { _colorSpaces = value; RaisePropertyChangedAuto(); }
        }

        private List<Rml> _rmls;
        /// <summary>
        /// Gets or sets the available RMLS.
        /// </summary>
        public List<Rml> Rmls
        {
            get { return _rmls; }
            set { _rmls = value; RaisePropertyChangedAuto(); }
        }

        private List<SpoolType> _spoolTypes;
        /// <summary>
        /// Gets or sets the available spool types.
        /// </summary>
        public List<SpoolType> SpoolTypes
        {
            get { return _spoolTypes; }
            set { _spoolTypes = value; RaisePropertyChangedAuto(); }
        }

        private List<Customer> _customers;
        /// <summary>
        /// Gets or sets the available customers.
        /// </summary>
        public List<Customer> Customers
        {
            get { return _customers; }
            set { _customers = value; RaisePropertyChangedAuto(); }
        }

        private String _customersFilter;
        /// <summary>
        /// Gets or sets the customers filter.
        /// </summary>
        public String CustomersFilter
        {
            get { return _customersFilter; }
            set { _customersFilter = value; RaisePropertyChangedAuto(); }
        }

        /// <summary>
        /// Gets or sets the customers automatic complete provider.
        /// </summary>
        public AutoCompleteProvider<Customer> CustomersAutoCompleteProvider { get; set; }

        #endregion

        #region Commands

        /// <summary>
        /// Gets or sets the add solid segment command.
        /// </summary>
        public RelayCommand AddSolidSegmentCommand { get; set; }

        /// <summary>
        /// Gets or sets the add gradient segment command.
        /// </summary>
        public RelayCommand AddGradientSegmentCommand { get; set; }

        /// <summary>
        /// Gets or sets the add brush stop command.
        /// </summary>
        public RelayCommand<Segment> AddBrushStopCommand { get; set; }

        /// <summary>
        /// Gets or sets the segment dropped command.
        /// </summary>
        public RelayCommand<DropEventArgs> SegmentDroppedCommand { get; set; }

        /// <summary>
        /// Gets or sets the remove segment command.
        /// </summary>
        public RelayCommand<Segment> RemoveSegmentCommand { get; set; }

        /// <summary>
        /// Gets or sets the remove brush stop command.
        /// </summary>
        public RelayCommand<BrushStop> RemoveBrushStopCommand { get; set; }

        /// <summary>
        /// Gets or sets the remove job command.
        /// </summary>
        public RelayCommand RemoveJobCommand { get; set; }

        /// <summary>
        /// Gets or sets the save job command.
        /// </summary>
        public RelayCommand SaveJobCommand { get; set; }

        /// <summary>
        /// Gets or sets the replace brush stop command.
        /// </summary>
        public RelayCommand<BrushStop> ReplaceBrushStopCommand { get; set; }

        /// <summary>
        /// Gets or sets the twine catalog field tap command.
        /// </summary>
        public RelayCommand<BrushStop> TwineCatalogFieldTapCommand { get; set; }

        /// <summary>
        /// Gets or sets the increase decrease samples to dye command.
        /// </summary>
        public RelayCommand<String> IncreaseDecreaseSamplesToDyeCommand { get; set; }

        /// <summary>
        /// Gets or sets the start sample dye command.
        /// </summary>
        public RelayCommand StartSampleDyeCommand { get; set; }

        /// <summary>
        /// Gets or sets the dye command.
        /// </summary>
        public RelayCommand DyeCommand { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="JobViewVM"/> class.
        /// </summary>
        public JobViewVM()
        {
            RegisterForMessage<JobSelectedMessage>(HandleJobSelectedMessage);

            CustomersAutoCompleteProvider = new AutoCompleteProvider<Customer>((customer, filter) =>
            {
                return customer.Name.ToLower().StartsWith(filter != null ? filter.ToLower() : String.Empty);
            });

            //Initialize Commands
            AddSolidSegmentCommand = new RelayCommand(() => AddSolidSegment());
            AddBrushStopCommand = new RelayCommand<Segment>(AddBrushStop);
            AddGradientSegmentCommand = new RelayCommand(() => AddGradientSegment());
            SegmentDroppedCommand = new RelayCommand<DropEventArgs>((e) =>
            {
                DragAndDropSegment(
                    (e.Draggable as FrameworkElement).DataContext as Segment,
                    (e.Droppable as FrameworkElement).DataContext as Segment);
            });

            RemoveSegmentCommand = new RelayCommand<Segment>(RemoveSegment);
            RemoveBrushStopCommand = new RelayCommand<BrushStop>(RemoveBrushStop);
            RemoveJobCommand = new RelayCommand(RemoveJob);
            SaveJobCommand = new RelayCommand(SaveJob);
            ReplaceBrushStopCommand = new RelayCommand<BrushStop>(InvokeColorAdjustmentForBrushStop);
            TwineCatalogFieldTapCommand = new RelayCommand<BrushStop>(InvokeTwineCatalogForBrushStop);
            IncreaseDecreaseSamplesToDyeCommand = new RelayCommand<string>((x) =>
            {
                if (x == "+")
                {
                    Job.SampleUnitsOrMeters++;
                }
                else
                {
                    Job.SampleUnitsOrMeters--;
                }
            });

            _check_gamut_thread = new Thread(CheckGamutThreadMethod);
            _check_gamut_thread.IsBackground = true;

            StartSampleDyeCommand = new RelayCommand(StartSampleDye);
            DyeCommand = new RelayCommand(StartJob, CanStartJob);
        }

        #endregion

        #region Job Management

        /// <summary>
        /// Saves the job.
        /// </summary>
        private async void SaveJob()
        {
            if (Job.Validate(_db))
            {
                await _db.SaveChangesAsync();
                RaiseMessage(new JobSavedMessage() { Job = Job });
                await NotificationProvider.ShowInfo(String.Format("Job '{0}' saved successfully.", Job.Name));
            }
        }

        /// <summary>
        /// Removes the job.
        /// </summary>
        private async void RemoveJob()
        {
            if (await NotificationProvider.ShowQuestion("Are you sure you want to delete the this job?"))
            {
                await Job.DeleteCascadeAsync(_db);
                RaiseMessage(new JobRemovedMessage() { Job = Job });
                _can_navigate_back = true;
                await NavigationManager.NavigateBack();
            }
        }

        private void StartJob()
        {
            MachineProvider.MachineOperator.Print(Job);
            NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView));
        }

        private bool CanStartJob()
        {
            return
                Job != null &&
                !Job.Segments.SelectMany(x => x.BrushStops).ToList().Exists(x => x.IsOutOfGamut);
        }

        #endregion

        #region Segments Management

        /// <summary>
        /// Adds a new solid segment.
        /// </summary>
        private Segment AddSolidSegment()
        {
            return Job.AddSolidSegment();
        }

        /// <summary>
        /// Adds a new gradient segment.
        /// </summary>
        private Segment AddGradientSegment()
        {
            return Job.AddGradientSegment();
        }

        /// <summary>
        /// Called when a segment has been dragged and dropped into another segment.
        /// </summary>
        /// <param name="draggedJob">The dragged job.</param>
        /// <param name="droppedJob">The dropped job.</param>
        private void DragAndDropSegment(Segment draggedSegment, Segment droppedSegment)
        {
            if (draggedSegment.SegmentIndex > droppedSegment.SegmentIndex)
            {
                draggedSegment.SegmentIndex = droppedSegment.SegmentIndex - 1;
            }
            else
            {
                draggedSegment.SegmentIndex = droppedSegment.SegmentIndex + 1;
            }

            int index = 1;

            foreach (var segment in Job.Segments.OrderBy(x => x.SegmentIndex))
            {
                segment.SegmentIndex = index++;
            }

            SegmentsCollectionView.Refresh();
        }

        /// <summary>
        /// Removes the segment.
        /// </summary>
        /// <param name="segment">The segment.</param>
        private async void RemoveSegment(Segment segment)
        {
            if (await NotificationProvider.ShowQuestion("Are you sure you want to remove the selected segment?"))
            {
                Job.Segments.Remove(segment);
            }
        }

        #endregion

        #region Brush Stops Management

        /// <summary>
        /// Adds a new brush stop to the specified segment.
        /// </summary>
        /// <param name="segment">The segment.</param>
        private void AddBrushStop(Segment segment)
        {
            segment.AddBrushStop();
        }

        /// <summary>
        /// Removes the brush stop.
        /// </summary>
        /// <param name="brushStop">The brush stop.</param>
        private void RemoveBrushStop(BrushStop brushStop)
        {
            if (brushStop.Segment.BrushStops.Count > 2)
            {
                brushStop.Segment.BrushStops.Remove(brushStop);
            }
            else
            {
                NotificationProvider.ShowInfo("Gradient segments must contain at least two colors.");
            }
        }

        /// <summary>
        /// Invokes the color adjustment for the specified brush stop.
        /// </summary>
        /// <param name="brushStop">The brush stop.</param>
        private async void InvokeColorAdjustmentForBrushStop(BrushStop brushStop)
        {
            var conversionOutput = TangoColorConverter.GetSuggestions(brushStop);

            BasicColorCorrectionViewVM vm = null;

            vm = await NotificationProvider.ShowDialog<BasicColorCorrectionViewVM>(new BasicColorCorrectionViewVM()
            {
                InvalidBrushStop = brushStop,
                Suggestions = TangoColorConverter.CreateTrippletSuggestions(conversionOutput),
            });

            if (vm.Result == BasicColorCorrectionViewVM.ColorCorrectionDialogResult.MoreOptions)
            {
                vm = await NotificationProvider.ShowDialog<AdvancedColorCorrectionViewVM>(new AdvancedColorCorrectionViewVM()
                {
                    InvalidBrushStop = brushStop,
                    Suggestions = TangoColorConverter.CreateHiveSuggestions(conversionOutput),
                });
            }

            if (vm.Result == BasicColorCorrectionViewVM.ColorCorrectionDialogResult.Confirmed)
            {
                brushStop.Color = vm.SelectedSuggestion.Color;
            }
        }

        private async void InvokeTwineCatalogForBrushStop(BrushStop brushStop)
        {
            _can_navigate_back = true;
            var catalogItem = await NavigationManager.NavigateForResult<JobsModule, TwineCatalogView, CatalogItem, BrushStop>(brushStop);
            _can_navigate_back = false;

            if (catalogItem != null)
            {
                brushStop.ColorCatalog = _db.ColorCatalogs.Single(x => x.Guid == catalogItem.Entity.Guid);
                brushStop.Color = catalogItem.Color;
            }
        }

        public void OnBrushStopFieldValueChanged(BrushStop brushStop)
        {
            brushStop.Corrected = false;
            brushStop.OutOfGamutChecked = false;
        }

        #endregion

        #region Job Selection Message

        /// <summary>
        /// Handles the job selected message.
        /// </summary>
        /// <param name="message">The message.</param>
        private void HandleJobSelectedMessage(JobSelectedMessage message)
        {
            _job_to_load = message.Job;
        }

        #endregion

        #region Sample Dye

        /// <summary>
        /// Starts a sample dye.
        /// </summary>
        private void StartSampleDye()
        {
            Job sampleDyeJob = Job.Clone();
            sampleDyeJob.Name = Job.Name + " (sample)";

            if (Job.JobType == BL.Enumerations.JobTypes.Embroidery)
            {
                sampleDyeJob.NumberOfUnits = Job.SampleUnitsOrMeters;
            }
            else
            {
                sampleDyeJob.NumberOfUnits = 1;

                foreach (var segment in sampleDyeJob.Segments)
                {
                    segment.Length = Job.SampleUnitsOrMeters;
                }
            }

            MachineProvider.MachineOperator.Print(sampleDyeJob);

            NavigationManager.NavigateTo<JobsModule>(nameof(JobProgressView));
        }

        #endregion

        #region Out Of Gamut Check Thread

        private void CheckGamutThreadMethod()
        {
            while (true)
            {
                Thread.Sleep(500);

                if (Job != null && IsVisible && (Job.ColorSpace != null && Job.ColorSpace.Code == BL.Enumerations.ColorSpaces.RGB.ToInt32()))
                {
                    var brushStops = Job.Segments.SelectMany(x => x.BrushStops).Where(x => !x.Corrected && !x.OutOfGamutChecked).ToList();

                    foreach (var stop in brushStops)
                    {
                        stop.IsOutOfGamut = TangoColorConverter.IsOutOfGamut(stop);
                        stop.OutOfGamutChecked = true;
                    }

                    if (brushStops.Count > 0)
                    {
                        InvokeUI(() =>
                        {
                            DyeCommand.RaiseCanExecuteChanged();
                        });
                    }
                }
            }
        }

        #endregion

        #region IPPC ViewModel Overrides

        /// <summary>
        /// Called when the application has been started.
        /// </summary>
        public override void OnApplicationStarted()
        {

        }

        /// <summary>
        /// Called when the navigation system has navigated to this VM view.
        /// </summary>
        public async override void OnNavigatedTo()
        {
            if (_job_to_load == null || (_job_to_load != null && Job != null && _job_to_load.Guid == Job.Guid)) return;

            NotificationProvider.SetGlobalBusyMessage("Loading job details...");

            _can_navigate_back = false;
            base.OnNavigatedTo();

            if (_db != null)
            {
                _db.Dispose();
            }

            _db = ObservablesContext.CreateDefault();
            Job = await _db.Jobs.SingleOrDefaultAsync(x => x.Guid == _job_to_load.Guid);
            Job.ValidateOnPropertyChanged = true;
            Rmls = await _db.Rmls.ToListAsync();
            ColorSpaces = await _db.ColorSpaces.ToListAsync();
            SpoolTypes = await _db.SpoolTypes.ToListAsync();
            Customers = await _db.Customers.Where(x => x.OrganizationGuid == MachineProvider.Machine.OrganizationGuid).ToListAsync();

            if (!_check_gamut_thread.IsAlive)
            {
                _check_gamut_thread.Start();
            }

            SegmentsCollectionView = CollectionViewSource.GetDefaultView(Job.Segments);
            SegmentsCollectionView.SortDescriptions.Add(new SortDescription(nameof(Segment.SegmentIndex), ListSortDirection.Ascending));

            InvokeUIOnIdle(() =>
            {
                NotificationProvider.ReleaseGlobalBusyMessage();
            });

            _job_to_load = null;
        }

        /// <summary>
        /// Called before the navigation system navigates back from this object.
        /// Return false to abort the navigation.
        /// </summary>
        /// <returns></returns>
        public async override Task<bool> OnNavigateBackRequest()
        {
            bool result = true;

            if (!_can_navigate_back)
            {
                if (await NotificationProvider.ShowQuestion("Are you sure you want to exit this job?"))
                {
                    Job = null;
                    SegmentsCollectionView = null;
                }
                else
                {
                    result = false;
                }
            }

            return result;
        }

        #endregion

        #region INavigationObjectReceiver

        public void OnNavigatedToWithObject(Job job)
        {
            _job_to_load = job;
        }

        #endregion
    }
}