aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/Views/JobsView.xaml.cs
blob: 23785881db64597f27fafd14d2094d8aa4ba4536 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Tango.Core.DI;
using Tango.PPC.Jobs.ViewContracts;

namespace Tango.PPC.Jobs.Views
{
    /// <summary>
    /// Interaction logic for JobsView.xaml
    /// </summary>
    public partial class JobsView : UserControl, IJobsView
    {
        public JobsView()
        {
            InitializeComponent();
            TangoIOC.Default.Register<IJobsView>(this);
        }

        private async void TouchNavigationLinks_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (dataGridJobs != null)
            {
                await Task.Delay(200);

                if (navigationLinks.SelectedIndex == 0)
                {
                    dataGridJobs.LayoutRows(false);
                    dataGridJobs.ScrollViewer.ScrollToTop();
                }
                else
                {
                    dataGridJobsHistory.LayoutRows(false);
                    dataGridJobsHistory.ScrollViewer.ScrollToTop();
                }
            }
        }

        public void ScrollToTop()
        {
            if (dataGridJobs != null && dataGridJobs.ScrollViewer != null)
            {
                dataGridJobs.ScrollViewer.ScrollToTop();
            }

            if (dataGridJobsHistory != null && dataGridJobsHistory.ScrollViewer != null)
            {
                dataGridJobsHistory.ScrollViewer.ScrollToTop();
            }
        }
    }
}
using ColorMine.ColorSpaces;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Media;
using Tango.BL.Dispensing;
using Tango.BL.Entities;
using Tango.BL.Enumerations;
using Tango.ColorConversion;
using Tango.Core.DI;
using Tango.Core.Threading;
using Tango.PMR.ColorLab;
using Tango.PPC.Common;
using Tango.PPC.Common.Connection;
using Tango.Settings;
using Tango.SharedUI;

namespace Tango.PPC.Jobs.Models
{
    public class BrushStopModel : ViewModel
    {
        public enum PositionStatus
        {
            First = 1,
            FirstColor = 2,
            Middle = 3,
            SecondColor = 4,
            Last = 5
        }

        private ActionTimer _volumeConversionTimer;
        private IColorConverter _converter;
        public const double MAX_INK_UPTAKE = 400;
        public event EventHandler ColorCatalogsItemChanged;
        public event EventHandler LiquidVolumesOutOfRangeChanged;
        public event EventHandler ColorChanged;

        [TangoInject]
        public IMachineProvider MachineProvider { get; set; }

        #region Property

        public String Guid { get; set; }

        [JsonIgnore]
        public bool PreventPropertyUpdate { get; set; }

        protected Int32 _red;

        /// <summary>
        /// Gets or sets the BrushStopModel red.
        /// </summary>
        public Int32 Red
        {
            get
            {
                return _red;
            }
            set
            {
                if (_red != value)
                {
                    _red = value;
                    RaisePropertyChangedAuto();
                    OnRGBChanged();
                }
            }
        }

        protected Int32 _green;

        /// <summary>
        /// Gets or sets the BrushStopModel green.
        /// </summary>
        public Int32 Green
        {
            get
            {
                return _green;
            }
            set
            {
                if (_green != value)
                {
                    _green = value;
                    RaisePropertyChangedAuto();
                    OnRGBChanged();
                }
            }
        }

        protected Int32 _blue;

        /// <summary>
        /// Gets or sets the BrushStopModel blue.
        /// </summary>
        public Int32 Blue
        {
            get
            {
                return _blue;
            }
            set
            {
                if (_blue != value)
                {
                    _blue = value;
                    RaisePropertyChangedAuto();
                    OnRGBChanged();
                }
            }
        }

        protected Double _l;

        /// <summary>
        /// Gets or sets the BrushStopModel l.
        /// </summary>

        public Double L
        {
            get
            {
                return _l;
            }

            set
            {
                if (_l != value)
                {
                    _l = value;
                    RaisePropertyChangedAuto();
                    OnLABChanged();
                }
            }
        }

        protected Double _a;

        /// <summary>
        /// Gets or sets the BrushStopModel a.
        /// </summary>
        public Double A
        {
            get
            {
                return _a;
            }
            set
            {
                if (_a != value)
                {
                    _a = value;
                    RaisePropertyChangedAuto();
                    OnLABChanged();
                }
            }
        }

        protected Double _b;

        /// <summary>
        /// Gets or sets the BrushStopModel b.
        /// </summary>
        public Double B
        {
            get
            {
                return _b;
            }
            set
            {
                if (_b != value)
                {
                    _b = value;
                    RaisePropertyChangedAuto();
                    OnLABChanged();
                }
            }
        }

        //HSB???
        private double _hue;

        public double Hue
        {
            get { return _hue; }
            set
            {
                if (_hue != value)
                {
                    _hue = value;
                    OnHSBChanged();
                    RaisePropertyChangedAuto();
                }

            }
        }

        private double _saturation;

        public double Saturation
        {
            get { return _saturation; }
            set
            {
                if (_saturation != value)
                {
                    _saturation = value;
                    OnHSBChanged();
                    RaisePropertyChangedAuto();
                }
            }
        }

        private double _brightness;

        public double Brightness
        {
            get { return _brightness; }
            set
            {
                if (_brightness != value)
                {
                    _brightness = value;
                    OnHSBChanged();
                    RaisePropertyChangedAuto();
                }

            }
        }

        private double _bestMatchL;
        public double BestMatchL
        {
            get
            {
                return _bestMatchL;
            }
            set
            {
                if (_bestMatchL != value)
                {
                    _bestMatchL = value;
                    RaisePropertyChangedAuto();
                }
            }
        }

        private double _bestMatchA;
        public double BestMatchA
        {
            get
            {
                return _bestMatchA;
            }
            set
            {
                if (_bestMatchA != value)
                {
                    _bestMatchA = value;
                    RaisePropertyChangedAuto();
                }
            }
        }

        private double _bestMatchB;
        public double BestMatchB
        {
            get
            {
                return _bestMatchB;
            }
            set
            {
                if (_bestMatchB != value)
                {
                    _bestMatchB = value;
                    RaisePropertyChangedAuto();
                }
            }
        }

        public int BestMatchRed { get; set; }
        public int BestMatchGreen { get; set; }
        public int BestMatchBlue { get; set; }

        protected Double _offsetpercent;

        /// <summary>
        /// Gets or sets the brushstopbase offset percent.
        /// </summary>
        public Double OffsetPercent
        {
            get
            {
                return _offsetpercent;
            }
            set
            {
                if (_offsetpercent != value)
                {
                    _offsetpercent = value;
                    RaisePropertyChangedAuto();
                    OnOffsetPercentChanged();
                }
            }
        }

        public double OffsetMeters
        {
            get
            {
                if (SegmentModel != null)
                {
                    var a = SegmentModel.Length * (OffsetPercent / 100d);
                    return a;
                }
                else
                {
                    return 0;
                }
            }
            set
            {
                if (SegmentModel != null)
                {
                    OffsetPercent = (value / SegmentModel.Length) * 100d;
                    RaisePropertyChangedAuto();
                }
            }
        }

        protected Int32 _stopindex;

        /// <summary>
        /// Gets or sets the brushstopbase stop index.
        /// </summary>
        public Int32 StopIndex
        {
            get
            {
                return _stopindex;
            }

            set
            {
                if (_stopindex != value)
                {
                    _stopindex = value;
                    RaisePropertyChangedAuto();
                    OnStopIndexChanged();

                }
            }
        }

        private PositionStatus _position;

        public PositionStatus Position
        {
            get { return _position; }
            set
            {
                _position = value;
                RaisePropertyChangedAuto();
            }
        }

        protected ColorSpaces _colorspace;

        public virtual ColorSpaces ColorSpace
        {
            get
            {
                return _colorspace;
            }

            set
            {
                if (_colorspace != value)
                {
                    _colorspace = value;
                }
                RaisePropertyChangedAuto();
            }
        }

        protected ColorCatalogsItem _colorcatalogsitem;
        [JsonIgnore]
        public virtual ColorCatalogsItem ColorCatalogsItem
        {
            get
            {
                return _colorcatalogsitem;
            }

            set
            {
                if (_colorcatalogsitem != value)
                {
                    _colorcatalogsitem = value;
                    OnColorCatalogsItemChanged();
                    RaisePropertyChangedAuto();
                    RaisePropertyChanged(nameof(ColorCatalog));

                }
            }
        }

        public string ColorCatalogsItemGuid
        {
            get
            {
                return ColorCatalogsItem == null ? "" : ColorCatalogsItem.Guid;
            }
        }

        /// <summary>
        /// Gets or sets the color catalog.
        /// </summary>
        /// <value>
        /// The color catalog.
        /// </value>
        [JsonIgnore]
        public virtual ColorCatalog ColorCatalog
        {
            get
            {
                if (ColorCatalogsItem != null && ColorCatalogsItem.ColorCatalogsGroup != null)
                {
                    return ColorCatalogsItem.ColorCatalogsGroup.ColorCatalog;
                }
                return null;
            }
        }

        private System.Windows.Media.Color _color;
        [JsonIgnore]
        public System.Windows.Media.Color Color
        {
            get
            {
                return _color;
            }
            set
            {
                if (_color != value)
                {
                    _color = value;
                    RaisePropertyChangedAuto();
                    ColorChanged?.Invoke(this, new EventArgs());
                }
            }
        }

        private System.Windows.Media.Color _bestMatchColor;
        [JsonIgnore]
        public System.Windows.Media.Color BestMatchColor
        {
            get { return _bestMatchColor; }
            set
            {
                _bestMatchColor = value;
                RaisePropertyChangedAuto();
                RaisePropertyChanged(nameof(BestMatchA));
                RaisePropertyChanged(nameof(BestMatchB));
                RaisePropertyChanged(nameof(BestMatchL));
                RaisePropertyChanged(nameof(ShownBestMatchColor));
            }
        }

        [JsonIgnore]
        public System.Windows.Media.Color ShownBestMatchColor
        {
            get
            {
                if (IsOutOfGamut)
                    return _bestMatchColor;
                return System.Windows.Media.Colors.Transparent;
            }
        }

        [JsonIgnore]
        public SolidColorBrush ColorBrush
        {
            get
            {
                if (Color == null)
                {
                    InitColor();
                }
                return new SolidColorBrush(Color);
            }
        }

        private SegmentModel _segmentmodel;
        [JsonIgnore]
        public SegmentModel SegmentModel
        {
            get { return _segmentmodel; }
            set { _segmentmodel = value; }
        }

        private bool _outOfGamutChecked;
        /// <summary>
        /// Gets or sets a value indicating whether out of gamut has been checked.
        /// </summary>
        [JsonIgnore]
        public bool OutOfGamutChecked
        {
            get { return _outOfGamutChecked; }
            set { _outOfGamutChecked = value; RaisePropertyChangedAuto(); }
        }

        private bool _isOutOfGamut;
        /// <summary>
        /// Gets or sets a value indicating whether this instance is out of gamut.
        /// </summary>
        public bool IsOutOfGamut
        {
            get { return _isOutOfGamut && ColorSpace != ColorSpaces.Volume && ColorSpace != ColorSpaces.Catalog; }
            set
            {
                if (_isOutOfGamut != value)
                {
                    _isOutOfGamut = value;
                    RaisePropertyChangedAuto();
                }
            }
        }

        [JsonIgnore]
        protected bool RequiredMaxLiquidTest { get; set; }

        [JsonIgnore]
        public bool IsLiquidVolumesOutOfRange
        {
            get
            {
                if (RequiredMaxLiquidTest && (ColorSpace == ColorSpaces.Volume || ColorSpace == ColorSpaces.CMYK))
                {
                    var sum = LiquidVolumes.GetMaxNanoliterPerCM();
                    var maxLiq = GetTotalMaximumLiquidNlPerCMLimit();
                    LiquidVolumesOutOfRange = sum > GetTotalMaximumLiquidNlPerCMLimit();

                    return LiquidVolumesOutOfRange;
                }
                else return false;
            }
        }

        private bool _liquidVolumesOutOfRange;
        [JsonIgnore]
        public bool LiquidVolumesOutOfRange
        {
            get { return _liquidVolumesOutOfRange; }
            set
            {
                if (_liquidVolumesOutOfRange != value)
                {
                    _liquidVolumesOutOfRange = value;
                    LiquidVolumesOutOfRangeChanged?.Invoke(this, new EventArgs());
                }
            }
        }

        [JsonIgnore]
        public bool IsLiquidVolumeBelowMinLimit
        {
            get
            {
                if (ColorSpace == ColorSpaces.Volume || ColorSpace == ColorSpaces.CMYK)
                {
                    foreach (var liquidVolume in LiquidVolumes)
                    {
                        var min = liquidVolume.GetMinLimit();
                        if (liquidVolume.Volume > 0 && liquidVolume.Volume < min)
                        {
                            LiquidVolumeBelowMinLimit = true;
                            LiquidVolumeBelowMinLimitmessage = $"{liquidVolume.IdsPack.LiquidType.Name} should be > {min.ToString("N3")}";
                            return LiquidVolumeBelowMinLimit;
                        }
                    }

                    LiquidVolumeBelowMinLimit = false;
                    LiquidVolumeBelowMinLimitmessage = "";
                    return false;
                }
                else return false;
            }
        }

        private string _liquidVolumeBelowMinLimitmessage;
        [JsonIgnore]
        public string LiquidVolumeBelowMinLimitmessage
        {
            get { return _liquidVolumeBelowMinLimitmessage; }
            set
            {
                _liquidVolumeBelowMinLimitmessage = value;
                RaisePropertyChangedAuto();
            }
        }

        private bool _liquidVolumeBelowMinLimit;
        [JsonIgnore]
        public bool LiquidVolumeBelowMinLimit
        {
            get { return _liquidVolumeBelowMinLimit; }
            set
            {
                if (_liquidVolumeBelowMinLimit != value)
                {
                    _liquidVolumeBelowMinLimit = value;
                    LiquidVolumesOutOfRangeChanged?.Invoke(this, new EventArgs());
                }
            }
        }

        [JsonIgnore]
        public ColorSpaces LastChangedColorSpace { get; set; }

        //Fine Tuning
        [JsonIgnore]
        public Double LBeforeChange { get; set; }
        [JsonIgnore]
        public Double ABeforeChange { get; set; }
        [JsonIgnore]
        public Double BBeforeChange { get; set; }

        [JsonIgnore]
        public BrushStop BrushStop { get; set; }

        public bool FineTuningChanged { get; set; }

        private LiquidVolumesCollection _liquidVolums;
        public LiquidVolumesCollection LiquidVolumes
        {
            get { return _liquidVolums; }
            set { _liquidVolums = value; RaisePropertyChangedAuto(); }
        }

        #endregion

        #region constructors

        public BrushStopModel(BrushStop stop)
        {
            Guid = System.Guid.NewGuid().ToString();

            TangoIOC.Default.Inject(this);

            BrushStop = stop;

            LiquidVolumes = new LiquidVolumesCollection();
        }

        public BrushStopModel(SegmentModel segmentModel, BrushStop stop) : this(stop)
        {
            SegmentModel = segmentModel;

            InitLiquidVolumes();

            InitDefaultValues();

            Color = Colors.White;
            var settings = SettingsManager.Default.GetOrCreate<PPCSettings>();
            ColorSpace = settings.DefaultTabColorSpace == null ? ColorSpaces.Volume : (ColorSpaces)settings.DefaultTabColorSpace;
            if (ColorSpace == ColorSpaces.CMYK)
                ColorSpace = ColorSpaces.Volume;
            LastChangedColorSpace = ColorSpace;
            ColorCatalogsItem = null;
            PreventPropertyUpdate = false;
            LiquidVolumesOutOfRange = false;
            RequiredMaxLiquidTest = false;
        }

        public BrushStopModel(BrushStop brushStop, SegmentModel segmentModel, int version) : this(brushStop)
        {
            SegmentModel = segmentModel;
            BrushStop = brushStop;

            InitLiquidVolumes();

            InitDefaultValues();
            Guid = brushStop.Guid;
            OffsetPercent = brushStop.OffsetPercent;
            Color = brushStop.Color;
            BestMatchColor = brushStop.Color;
            ColorSpace = brushStop.ColorSpace.Space;
            LastChangedColorSpace = ColorSpace;
            if (ColorSpace == ColorSpaces.CMYK)
                ColorSpace = ColorSpaces.Volume;
            _colorcatalogsitem = brushStop.ColorCatalogsItem;
            _stopindex = brushStop.StopIndex;

            PreventPropertyUpdate = true;

            LiquidVolumes.SetVolumesFromBrushStop(brushStop);

            Red = brushStop.Red;
            Green = brushStop.Green;
            Blue = brushStop.Blue;
            L = brushStop.L;
            A = brushStop.A;
            B = brushStop.B;
            BestMatchL = brushStop.L;
            BestMatchA = brushStop.A;
            BestMatchB = brushStop.B;
            PreventPropertyUpdate = false;
            LiquidVolumesOutOfRange = false;
        }

        public void InitLiquidVolumes()
        {
            LiquidVolumes.Clear();

            var supportedIdsPacks = SegmentModel.Job.Machine.Configuration.GetSupportedIdsPacks(SegmentModel.Job.Rml).Where(x => x.LiquidType.HasPigment && x.LiquidType.AvailableForStandardUser).OrderBy(x => x.LiquidType.PreferredIndex).ToList();

            foreach (var idsPack in supportedIdsPacks)
            {
                var liquidVolume = new LiquidVolumeModel(this, idsPack);
                liquidVolume.VolumeChanged += (x, e) => OnVolumeChanged();
                LiquidVolumes.Add(liquidVolume);
            }

            if (BrushStop != null)
            {
                LiquidVolumes.SetVolumesFromBrushStopSilent(BrushStop);
            }
        }

        private void InitDefaultValues()
        {
            _hue = 0;
            _saturation = 0;
            _brightness = 100;
            _l = 100;
            _a = 0;
            _b = 0;
            _bestMatchL = 100;
            _bestMatchA = _bestMatchB = 0;
            _red = _green = _blue = 255;
            LiquidVolumes.ResetVolumeSilent();
            StopIndex = 1;
            Position = PositionStatus.FirstColor;
            IsOutOfGamut = false;
            _volumeConversionTimer = new ActionTimer(TimeSpan.FromMilliseconds(50));
            _converter = new DefaultColorConverter();
            _bestMatchColor = Color.FromRgb((byte)Red, (byte)Green, (byte)Blue);
        }

        #endregion

        #region Methods        
        /// <summary>
        /// Initializes the color.
        /// </summary>
        public void InitColor()
        {
            if (ColorSpace == ColorSpaces.Catalog && ColorCatalogsItem != null)
            {
                Color = Color.FromRgb((byte)ColorCatalogsItem.Red, (byte)ColorCatalogsItem.Green, (byte)ColorCatalogsItem.Blue);
            }
            else
            {
                Color = Color.FromRgb((byte)_red, (byte)_green, (byte)_blue);
            }
        }

        /// <summary>
        /// Sets the new color from MyColors.
        /// </summary>
        public void SetNewColor(BrushStopModel newBrushStop)
        {
            ColorSpace = newBrushStop.ColorSpace;
            PreventPropertyUpdate = true;

            Red = newBrushStop.Red;
            Green = newBrushStop.Green;
            Blue = newBrushStop.Blue;
            L = newBrushStop.L;
            A = newBrushStop.A;
            B = newBrushStop.B;
            BestMatchL = newBrushStop.BestMatchL;
            BestMatchA = newBrushStop.BestMatchA;
            BestMatchB = newBrushStop.BestMatchB;

            LiquidVolumes.SetVolumesFromBrushStop(newBrushStop);

            ColorCatalogsItem = newBrushStop.ColorCatalogsItem;
            PreventPropertyUpdate = false;

            Color = newBrushStop.Color;
            BestMatchColor = newBrushStop.BestMatchColor;
        }

        /// <summary>
        /// Creates the brush stop.
        /// </summary>
        public BrushStop CreateBrushStop(ColorSpaces colorSpace)
        {
            List<Tango.BL.Entities.ColorSpace> list = SegmentModel.Job.ColorSpacesList;

            BrushStop s = new BrushStop();
            s.ColorSpace = list.FirstOrDefault(x => x.Space == colorSpace);

            Configuration configuration = SegmentModel.Job.Machine.Configuration;
            Rml rml = SegmentModel.Job.Rml;
            s.SetLiquidVolumes(configuration, rml, rml.GetActiveProcessGroup().ProcessParametersTables.FirstOrDefault());


            if (s.ColorSpace.Space == ColorSpaces.Volume)
            {
                foreach (var liquidVolume in LiquidVolumes)
                {
                    s.SetVolume(liquidVolume.IdsPack.PackIndex, liquidVolume.Volume);
                }
            }
            else if (s.ColorSpace.Space == ColorSpaces.LAB)
            {
                s.ColorSpace.Space = BL.Enumerations.ColorSpaces.LAB;
                s.L = this.L;
                s.A = this.A;
                s.B = this.B;
            }
            else if (s.ColorSpace.Space == ColorSpaces.RGB)
            {
                s.ColorSpace.Space = BL.Enumerations.ColorSpaces.RGB;
                s.Red = this.Red;
                s.Green = this.Green;
                s.Blue = this.Blue;
            }
            //else if (s.ColorSpace.Space == ColorSpaces.HSB)
            //{
            //    s.ColorSpace.Space = BL.Enumerations.ColorSpaces.RGB;
            //    s.Red = this.Red;
            //    s.Green = this.Green;
            //    s.Blue = this.Blue;
            //}

            return s;
        }

        public BrushStop CreateBrushStopForFineTuning(ColorSpaces colorSpace, double cyan, double yellow, double magenta, double black)
        {
            List<Tango.BL.Entities.ColorSpace> list = SegmentModel.Job.ColorSpacesList;

            BrushStop s = new BrushStop();
            s.ColorSpace = list.FirstOrDefault(x => x.Space == colorSpace);

            Configuration configuration = SegmentModel.Job.Machine.Configuration;
            Rml rml = SegmentModel.Job.Rml;
            s.SetLiquidVolumes(configuration, rml, rml.GetActiveProcessGroup().ProcessParametersTables.FirstOrDefault());


            s.ColorSpace.Space = BL.Enumerations.ColorSpaces.LAB;
            s.L = this.L;
            s.A = this.A;
            s.B = this.B;
            s.Cyan = cyan;
            s.Yellow = yellow;
            s.Magenta = magenta;
            s.Black = black;

            return s;
        }

        public BrushStopModel Clone()
        {
            var cloned = new BrushStopModel(SegmentModel, BrushStop);
            cloned.StopIndex = StopIndex;
            cloned.PreventPropertyUpdate = true;
            cloned.Red = Red;
            cloned.Green = Green;
            cloned.Blue = Blue;
            cloned.L = L;
            cloned.A = A;
            cloned.B = B;
            cloned.BestMatchL = BestMatchL;
            cloned.BestMatchA = BestMatchA;
            cloned.BestMatchB = BestMatchB;
            cloned.LiquidVolumes.SetVolumesFromBrushStop(this);
            cloned.Hue = Hue;
            cloned.Saturation = Saturation;
            cloned.Brightness = Brightness;
            cloned.Color = Color;
            cloned.BrushStop = BrushStop;
            cloned.ColorCatalogsItem = ColorCatalogsItem;
            cloned.ColorSpace = ColorSpace;
            cloned.BestMatchColor = BestMatchColor;
            cloned.OffsetMeters = OffsetMeters;
            cloned.OffsetPercent = OffsetPercent;
            cloned.Position = Position;
            cloned.IsOutOfGamut = IsOutOfGamut;
            cloned.OutOfGamutChecked = OutOfGamutChecked;
            cloned.LiquidVolumesOutOfRange = LiquidVolumesOutOfRange;
            //this.MapPropertiesTo(cloned, MappingFlags.NoReferenceTypes);
            cloned.PreventPropertyUpdate = false;
            cloned.RequiredMaxLiquidTest = false;
            cloned.LastChangedColorSpace = ColorSpace;
            return cloned;
        }

        public static Color GetRelativeRGB(Color first, Color second, double firstOffset, double secondOffset, double offset)
        {
            var color = new Color();
            var range = (secondOffset - firstOffset);
            var realoffset = offset - firstOffset;

            color.ScA = (float)(realoffset * (second.ScA - first.ScA) / range + first.ScA);
            color.ScR = (float)(realoffset * (second.ScR - first.ScR) / range + first.ScR);
            color.ScG = (float)(realoffset * (second.ScG - first.ScG) / range + first.ScG);
            color.ScB = (float)(realoffset * (second.ScB - first.ScB) / range + first.ScB);

            return color;
        }

        public void SetMyColor(FavoriteColor favoriteColor)
        {
            Color = favoriteColor.Color;
            BestMatchColor = favoriteColor.Color;
            ColorSpace = favoriteColor.ColorSpace;
            // _colorcatalogsitem = favoriteColor.ColorCatalogsItem;

            PreventPropertyUpdate = true;


            //LiquidVolumes.ResetVolume();

            foreach (var liquidVolume in LiquidVolumes.Where(x => x.IdsPack.LiquidType.AvailableForStandardUser))
            {
                liquidVolume.Volume = favoriteColor.GetVolume(liquidVolume.IdsPack.LiquidType.Type);
            }

            RaisePropertyChanged(nameof(LiquidVolumes));

            //LiquidVolumes.GetLiquidVolume(LiquidTypes.Cyan).Volume = favoriteColor.Cyan;
            //LiquidVolumes.GetLiquidVolume(LiquidTypes.Magenta).Volume = favoriteColor.Magenta;
            //LiquidVolumes.GetLiquidVolume(LiquidTypes.Yellow).Volume = favoriteColor.Yellow;
            //LiquidVolumes.GetLiquidVolume(LiquidTypes.Black).Volume = favoriteColor.Black;


            Red = favoriteColor.Red;
            Green = favoriteColor.Green;
            Blue = favoriteColor.Blue;
            L = favoriteColor.L;
            A = favoriteColor.A;
            B = favoriteColor.B;
            BestMatchL = favoriteColor.L;
            BestMatchA = favoriteColor.A;
            BestMatchB = favoriteColor.B;
            PreventPropertyUpdate = false;
            LiquidVolumesOutOfRange = false;
        }


        /// <summary>
        /// Creates the brush stop.
        /// </summary>
        public BrushStop CreateBrushStop()
        {
            List<Tango.BL.Entities.ColorSpace> list = SegmentModel.Job.ColorSpacesList;

            BrushStop s = new BrushStop();

            if (ColorSpace == ColorSpaces.CMYK)
                ColorSpace = ColorSpaces.Volume;
            s.ColorSpace = list.FirstOrDefault(x => x.Space == ColorSpace);

            Configuration configuration = SegmentModel.Job.Machine.Configuration;
            Rml rml = SegmentModel.Job.Rml;

            s.Segment = BrushStop.Segment;
            s.SetLiquidVolumes(configuration, rml, rml.GetActiveProcessGroup().ProcessParametersTables.FirstOrDefault());

            s.OffsetPercent = OffsetPercent;
            s.StopIndex = StopIndex;
            s.IsOutOfGamut = IsOutOfGamut;

            s.ColorCatalog = ColorCatalog;
            s.ColorCatalogsItem = ColorCatalogsItem;

            LiquidVolumes.SetVolumesOnBrushStop(s);

            s.L = this.L;
            s.A = this.A;
            s.B = this.B;

            s.Red = this.Red;
            s.Green = this.Green;
            s.Blue = this.Blue;

            return s;
        }

        //Fine Tuning
        public void UndoColorChanges()
        {
            if (ColorSpace == ColorSpaces.LAB)
            {
                PreventPropertyUpdate = true;
                L = LBeforeChange;
                A = ABeforeChange;
                PreventPropertyUpdate = false;
                B = BBeforeChange;
            }
            else if (ColorSpace == ColorSpaces.Volume)
            {
                PreventPropertyUpdate = true;
                LiquidVolumes.Undo();
                PreventPropertyUpdate = false;
            }
        }

        //Fine Tuning
        public void SaveColorBeforeChanges()
        {
            if (ColorSpace == ColorSpaces.LAB)
            {
                LBeforeChange = L;
                ABeforeChange = A;
                BBeforeChange = B;
            }
            else if (ColorSpace == ColorSpaces.Volume)
            {
                LiquidVolumes.SaveState();
            }
        }

        #endregion

        #region changes

        private void OnVolumeChanged()
        {
            if (PreventPropertyUpdate)
                return;
            ColorSpace = ColorSpaces.Volume;
            RequiredMaxLiquidTest = true;
            RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
            RaisePropertyChanged(nameof(IsLiquidVolumeBelowMinLimit));
            LastChangedColorSpace = ColorSpace;
            OnBrushStopFieldValueChanged();

        }
        private void OnRGBChanged()
        {
            if (PreventPropertyUpdate)
                return;
            ColorSpace = ColorSpaces.RGB;
            InitColor();
            LastChangedColorSpace = ColorSpace;
            OnBrushStopFieldValueChanged();
        }

        private void OnHSBChanged()
        {
            if (PreventPropertyUpdate)
                return;
            //  ColorSpace = ColorSpaces.HSB;
            Rgb rgb = GetRGBColor();
            _red = (int)rgb.R;
            _green = (int)rgb.G;
            _blue = (int)rgb.B;
            InitColor();
            LastChangedColorSpace = ColorSpace;
            OnBrushStopFieldValueChanged();
        }

        private void OnLABChanged()
        {
            if (PreventPropertyUpdate)
                return;
            ColorSpace = ColorSpaces.LAB;
            Rgb rgb = GetRGBColor();
            _red = (int)rgb.R;
            _green = (int)rgb.G;
            _blue = (int)rgb.B;
            InitColor();
            OnBrushStopFieldValueChanged();
            LastChangedColorSpace = ColorSpace;
        }

        private void OnColorCatalogsItemChanged()
        {
            if (PreventPropertyUpdate)
                return;
            ColorSpace = ColorSpaces.Catalog;
            if (_colorcatalogsitem != null)
            {
                _red = (int)_colorcatalogsitem.Red;
                _green = (int)_colorcatalogsitem.Green;
                _blue = (int)_colorcatalogsitem.Blue;
                InitColor();
                LastChangedColorSpace = ColorSpace;
                BestMatchColor = Color;
            }

            if (ColorCatalogsItemChanged != null)
            {
                ColorCatalogsItemChanged.Invoke(this, new EventArgs());
            }
        }
        private void OnOffsetPercentChanged()
        {
            //lenth?
        }

        private void OnStopIndexChanged()
        {
            //throw new NotImplementedException();
        }

        public Rgb GetRGBColor()
        {
            if (ColorSpace == ColorSpaces.LAB)
            {
                Lab lab = new Lab(L, A, B);
                Rgb rgb = new Rgb(lab.ToRgb());
                return rgb;
            }
            //if (ColorSpace == ColorSpaces.HSB)
            //{
            //    Hsb hsb = new Hsb(Hue, Saturation / 100, Brightness / 100);
            //    Rgb rgb = new Rgb(hsb.ToRgb());
            //    return rgb;
            //}
            if (ColorSpace == ColorSpaces.Catalog && ColorCatalogsItem != null)
            {
                return new Rgb(ColorCatalogsItem.Red, ColorCatalogsItem.Green, ColorCatalogsItem.Blue);
            }
            return new Rgb(Red, Green, Blue);
        }

        public void ConvertColorToHSB()
        {
            //if (ColorSpace != ColorSpaces.HSB)
            //{
            //    if ( LastChangedColorSpace != ColorSpaces.HSB)
            //    {
            //        Hsb hsb = null;
            //        if (LastChangedColorSpace == ColorSpaces.Volume)
            //        {
            //            BrushStop stop = CreateBrushStop(ColorSpaces.Volume);
            //            try
            //            {
            //                IsBusy = true;
            //                var output = _converter.Convert(stop, SegmentModel.Job.Machine.Configuration, SegmentModel.Job.Rml, false, false, false);
            //                _red = output.SingleCoordinates.Red;
            //                _green = output.SingleCoordinates.Green;
            //                _blue = output.SingleCoordinates.Blue;
            //                IsOutOfGamut = false;//output.OutOfGamut;
            //                Rgb rgb = new Rgb(Red, Green, Blue);
            //                hsb = new Hsb(rgb.To<Hsb>());
            //            }
            //            catch (Exception ex)
            //            {
            //                LogManager.Log(ex, "An error occurred while trying to get volume => RGB from conversion engine.");
            //            }
            //            finally
            //            {
            //                IsBusy = false;
            //            }
            //        }
            //        else if (LastChangedColorSpace == ColorSpaces.LAB)
            //    {
            //        Lab lab = new Lab(L, A, B);
            //        hsb = new Hsb(lab.To<Hsb>());
            //    }
            //    else if (LastChangedColorSpace == ColorSpaces.RGB)
            //    {
            //        Rgb rgb = new Rgb(Red, Green, Blue);
            //        hsb = new Hsb(rgb.To<Hsb>());
            //    }
            //    else if (LastChangedColorSpace == ColorSpaces.Catalog && ColorCatalogsItem != null)
            //    {
            //        Rgb rgb = new Rgb(ColorCatalogsItem.Red, ColorCatalogsItem.Green, ColorCatalogsItem.Blue);
            //        hsb = new Hsb(rgb.To<Hsb>());
            //    }
            //    if (hsb != null)
            //    {
            //        _hue = hsb.H;
            //        _saturation = hsb.S * 100; ;
            //        _brightness = hsb.B * 100; ;
            //        RaisePropertyChanged(nameof(Hue));
            //        RaisePropertyChanged(nameof(Saturation));
            //        RaisePropertyChanged(nameof(Brightness));
            //    }
            //    }
            //    ColorSpace = ColorSpaces.HSB;
            //    RequiredMaxLiquidTest = false;
            //    RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
            //}
        }

        public void ConvertColorToRGB()
        {
            if (ColorSpace != ColorSpaces.RGB)
            {

                if (LastChangedColorSpace != ColorSpaces.RGB)
                {
                    if (LastChangedColorSpace == ColorSpaces.Catalog && ColorCatalogsItem != null)
                    {
                        _red = ColorCatalogsItem.Red;
                        _green = ColorCatalogsItem.Green;
                        _blue = ColorCatalogsItem.Blue;
                    }
                    else if (LastChangedColorSpace == ColorSpaces.Volume)
                    {
                        BrushStop stop = CreateBrushStop(ColorSpaces.Volume);
                        try
                        {
                            IsBusy = true;
                            var output = _converter.Convert(stop, SegmentModel.Job.Machine.Configuration, SegmentModel.Job.Rml, false, false, false);
                            _red = output.SingleCoordinates.Red;
                            _green = output.SingleCoordinates.Green;
                            _blue = output.SingleCoordinates.Blue;
                            IsOutOfGamut = false;//output.OutOfGamut;
                            if (IsLiquidVolumesOutOfRange)
                            {
                                BestMatchColor = Color.FromRgb((byte)output.SingleCoordinates.Red, (byte)output.SingleCoordinates.Green, (byte)output.SingleCoordinates.Blue);
                                InitColor();
                            }
                        }
                        catch (Exception ex)
                        {
                            LogManager.Log(ex, "An error occurred while trying to get volume => RGB from conversion engine.");
                        }
                        finally
                        {
                            IsBusy = false;
                        }
                    }
                    else
                    {
                        Rgb rgb = GetRGBColor();
                        _red = (int)rgb.R;
                        _green = (int)rgb.G;
                        _blue = (int)rgb.B;
                        ColorSpace = ColorSpaces.RGB;
                        ConvertColor();
                    }

                }
                ColorSpace = ColorSpaces.RGB;

                RaisePropertyChanged(nameof(Red));
                RaisePropertyChanged(nameof(Green));
                RaisePropertyChanged(nameof(Blue));
                RequiredMaxLiquidTest = false;
                RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
                RaisePropertyChanged(nameof(IsLiquidVolumeBelowMinLimit));
            }
        }

        public void ConvertColorToLAB()
        {
            if (ColorSpace != ColorSpaces.LAB)
            {
                if (LastChangedColorSpace != ColorSpaces.LAB)
                {
                    Lab lab = null;
                    if (LastChangedColorSpace == ColorSpaces.Catalog && ColorCatalogsItem != null)
                    {
                        _l = ColorCatalogsItem.L;
                        _a = ColorCatalogsItem.A;
                        _b = ColorCatalogsItem.B;
                        BestMatchL = _l;
                        BestMatchA = _a;
                        BestMatchB = _b;
                    }
                    else if (LastChangedColorSpace == ColorSpaces.Volume)
                    {
                        BrushStop stop = CreateBrushStop(ColorSpaces.Volume);
                        try
                        {
                            IsBusy = true;
                            var output = _converter.Convert(stop, SegmentModel.Job.Machine.Configuration, SegmentModel.Job.Rml, false, false, false);
                            _l = output.SingleCoordinates.L;
                            _a = output.SingleCoordinates.A;
                            _b = output.SingleCoordinates.B;
                            BestMatchL = _l;
                            BestMatchA = _a;
                            BestMatchB = _b;
                            IsOutOfGamut = false;//output.OutOfGamut;

                            if (IsLiquidVolumesOutOfRange)
                            {
                                _red = output.SingleCoordinates.Red;
                                _green = output.SingleCoordinates.Green;
                                _blue = output.SingleCoordinates.Blue;
                                BestMatchColor = Color.FromRgb((byte)_red, (byte)_green, (byte)_blue);
                                InitColor();
                            }
                        }
                        catch (Exception ex)
                        {
                            LogManager.Log(ex, "An error occurred while trying to convert volume to LAB.");
                        }
                        finally
                        {
                            IsBusy = false;
                        }
                    }
                    //else if (LastChangedColorSpace == ColorSpaces.HSB)
                    //{
                    //    Hsb hsb = new Hsb(Hue, Saturation / 100, Brightness / 100);
                    //    lab = new Lab(hsb.To<Lab>());
                    //}
                    else if (LastChangedColorSpace == ColorSpaces.RGB)
                    {
                        Rgb rgb = new Rgb(Red, Green, Blue);
                        lab = new Lab(rgb.To<Lab>());
                    }
                    if (lab != null)
                    {
                        _l = lab.L;
                        _a = lab.A;
                        _b = lab.B;
                        BestMatchL = _l;
                        BestMatchA = _a;
                        BestMatchB = _b;
                        ColorSpace = ColorSpaces.LAB;
                        ConvertColor();
                    }
                }

                ColorSpace = ColorSpaces.LAB;
                RaisePropertyChanged(nameof(L));
                RaisePropertyChanged(nameof(A));
                RaisePropertyChanged(nameof(B));
                RequiredMaxLiquidTest = false;
                RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
                RaisePropertyChanged(nameof(IsLiquidVolumeBelowMinLimit));
            }
        }

        public void ConvertColorToVolume()
        {
            RequiredMaxLiquidTest = true;
            if (ColorSpace != ColorSpaces.Volume)
            {
                if (LastChangedColorSpace != ColorSpaces.Volume)
                {
                    if (LastChangedColorSpace == ColorSpaces.Catalog)
                    {
                        if (ColorCatalogsItem != null)
                        {
                            LiquidVolumes.ResetVolumeSilent();
                            LiquidVolumes.GetLiquidVolume(LiquidTypes.Cyan).SetVolumeSilent(ColorCatalogsItem.Cyan);
                            LiquidVolumes.GetLiquidVolume(LiquidTypes.Magenta).SetVolumeSilent(ColorCatalogsItem.Magenta);
                            LiquidVolumes.GetLiquidVolume(LiquidTypes.Yellow).SetVolumeSilent(ColorCatalogsItem.Yellow);
                            LiquidVolumes.GetLiquidVolume(LiquidTypes.Black).SetVolumeSilent(ColorCatalogsItem.Black);
                            LiquidVolumes.RaiseVolume();
                            IsOutOfGamut = false;
                            // RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
                            // RaisePropertyChanged(nameof(IsLiquidVolumeBelowMinLimit));
                        }
                        ColorSpace = ColorSpaces.Volume;
                        RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
                        RaisePropertyChanged(nameof(IsLiquidVolumeBelowMinLimit));
                        return;
                    }
                    ColorSpaces colorSpace = LastChangedColorSpace;
                    //if (colorSpace == ColorSpaces.HSB)
                    //{
                    //    colorSpace = ColorSpaces.RGB;
                    //}
                    //else 
                    if (colorSpace == ColorSpaces.CMYK)
                    {
                        colorSpace = ColorSpaces.Volume;
                    }

                    BrushStop stop = CreateBrushStop(colorSpace);
                    try
                    {
                        IsBusy = true;
                        var output = _converter.Convert(stop, SegmentModel.Job.Machine.Configuration, SegmentModel.Job.Rml, false, false, false);

                        foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids)
                        {
                            LiquidVolumes.GetLiquidVolume(outputLiquid.LiquidType)?.SetVolumeSilent(outputLiquid.Volume);
                        }

                        IsOutOfGamut = false;
                        //if ( LastChangedColorSpace != ColorSpaces.RGB)
                        //{
                        //    _red = output.SingleCoordinates.Red;
                        //    _green = output.SingleCoordinates.Green;
                        //    _blue = output.SingleCoordinates.Blue;
                        //    InitColor();
                        //    BestMatchColor = Color.FromRgb((byte)output.SingleCoordinates.Red, (byte)output.SingleCoordinates.Green, (byte)output.SingleCoordinates.Blue);
                        //}
                        LiquidVolumes.RaiseVolume();
                        RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
                        RaisePropertyChanged(nameof(IsLiquidVolumeBelowMinLimit));
                    }
                    catch (Exception ex)
                    {
                        LogManager.Log(ex, "An error occurred while trying to get volume => RGB from conversion engine." + ex);
                        //convertedString = Regex.Replace(ex,@"\xEF\xBF\xBD"," ");
                    }
                    finally
                    {
                        ColorSpace = ColorSpaces.Volume;
                        IsBusy = false;
                    }
                }
                ColorSpace = ColorSpaces.Volume;
                RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
                RaisePropertyChanged(nameof(IsLiquidVolumeBelowMinLimit));
            }
        }

        public void ConvertColorToCatalogs(List<ColorCatalog> catalogs)
        {
            if (ColorSpace != ColorSpaces.Catalog)
            {
                if (LastChangedColorSpace != ColorSpaces.Catalog)
                {
                    if (BestMatchColor == null)
                        BestMatchColor = Color;
                    var closestItem = catalogs.SelectMany(x => x.AllItemsOrdered).GetClosestItem(BestMatchColor);

                    _colorcatalogsitem = closestItem;
                    if (ColorCatalogsItemChanged != null)
                    {
                        ColorCatalogsItemChanged.Invoke(this, new EventArgs());
                    }
                    RaisePropertyChangedAuto(nameof(ColorCatalogsItem));
                }
                ColorSpace = ColorSpaces.Catalog;
                RaisePropertyChanged(nameof(ColorCatalog));
            }
        }

        public void FineTuningConverter(double cyan, double yellow, double magenta, double black)
        {
            RequiredMaxLiquidTest = true;

            ColorSpaces colorSpace = ColorSpaces.LAB;
            BrushStop stop = CreateBrushStopForFineTuning(colorSpace, cyan, yellow, magenta, black);

            try
            {
                IsBusy = true;
                var output = _converter.Convert(stop, SegmentModel.Job.Machine.Configuration, SegmentModel.Job.Rml, false, false, false, ConversionType.FineTuning);

                var b = output.SingleCoordinates.OutputLiquids.FirstOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.Black);

                if (b != null)
                {
                    if (b.Volume > 0 && b.Volume < 0.5)//bug 7959 0.001 < K% < 0.5 ==> reset the K to 0.
                    {
                        b.Volume = 0;
                    }
                }

                foreach (var outputLiquid in output.SingleCoordinates.OutputLiquids)
                {
                    LiquidVolumes.GetLiquidVolume(outputLiquid.LiquidType)?.SetVolumeSilent(outputLiquid.Volume);
                }

                IsOutOfGamut = output.OutOfGamut;
                if (IsOutOfGamut)
                {
                    BrushStop stopLAB = CreateBrushStop(ColorSpaces.Volume);

                    IsBusy = true;
                    var outputLAB = _converter.Convert(stopLAB, SegmentModel.Job.Machine.Configuration, SegmentModel.Job.Rml, false, false, false);
                    _l = output.SingleCoordinates.L;
                    _a = output.SingleCoordinates.A;
                    _b = output.SingleCoordinates.B;
                }

                BestMatchRed = output.SingleCoordinates.Red;
                BestMatchGreen = output.SingleCoordinates.Green;
                BestMatchBlue = output.SingleCoordinates.Blue;
            }
            catch (Exception ex)
            {
                LogManager.Log(ex, "An error occurred while trying to get volume => RGB from conversion engine." + ex);
            }
            finally
            {
                IsBusy = false;
            }
        }

        public void RaiseOffsetChanged()
        {
            RaisePropertyChanged(nameof(OffsetPercent));
            RaisePropertyChanged(nameof(OffsetMeters));
        }

        public void RaiseColorCatalogsItemChanged()
        {
            RaisePropertyChanged(nameof(ColorCatalogsItem));
        }

        public void UpdateColorOnAccept()
        {
            if (ColorSpace == ColorSpaces.Catalog)
            {
                if (_colorcatalogsitem != null)
                {
                    _red = (int)_colorcatalogsitem.Red;
                    _green = (int)_colorcatalogsitem.Green;
                    _blue = (int)_colorcatalogsitem.Blue;
                    InitColor();
                    BestMatchColor = Color;
                }
            }
            InitColorsFromBestmatch();
        }

        public void UpdateColorFromFineTuningDlg()
        {
            Rgb rgb = GetRGBColor();
            _red = (int)rgb.R;
            _green = (int)rgb.G;
            _blue = (int)rgb.B;
            InitColor();
        }
        #endregion

        #region color converters

        public void InitColorsFromBestmatch()
        {
            if (BestMatchColor == null || BestMatchColor == Color)
                return;

            _red = BestMatchColor.R;
            _green = BestMatchColor.G;
            _blue = BestMatchColor.B;
            if (ColorSpace == BL.Enumerations.ColorSpaces.LAB)
            {
                _l = _bestMatchL;
                _a = _bestMatchA;
                _b = _bestMatchB;
            }
            IsOutOfGamut = false;
            InitColor();
        }

        private double GetTotalMaximumLiquidNlPerCMLimit()
        {
            try
            {
                var tables = SegmentModel.Job.Rml.GetActiveProcessGroup().ProcessParametersTables.OrderBy(x => x.TableIndex).ToList();

                if (tables.Count > 0)
                {
                    return tables.Max(x => x.MaxInkUptake);
                }
                else
                {
                    return MAX_INK_UPTAKE;
                }
            }
            catch
            {
                return MAX_INK_UPTAKE;
            }
        }

        private double GetMinLimitLiquid(LiquidTypes type)
        {
            try
            {
                var tables = SegmentModel.Job.Rml.GetActiveProcessGroup().ProcessParametersTables.OrderBy(x => x.TableIndex).ToList();

                LiquidTypesRml liquidType = SegmentModel.Job.Rml.LiquidTypesRmls.FirstOrDefault(x => x.LiquidType.Type == type);

                if (tables.Count > 0 && liquidType != null && liquidType.MaxNlPerCm != 0)
                {
                    var vmax = Math.Max(SegmentModel.Job.Rml.VMax / 10d, 0);

                    if (type == LiquidTypes.Black)
                    {
                        vmax = Math.Max(SegmentModel.Job.Rml.VMax, 0);
                    }

                    return (vmax * tables[0].MinInkUptake) / liquidType.MaxNlPerCm;
                }
                else
                {
                    return 0;
                }
            }
            catch
            {
                return 0;
            }
        }

        public double GetColorNLPerCm(double color, LiquidTypes type)
        {
            StandardColorDispensingCalc calc = new StandardColorDispensingCalc();

            Rml rml = SegmentModel.Job.Rml;
            LiquidTypesRml liquidType = rml.LiquidTypesRmls.FirstOrDefault(x => x.LiquidType.Type == type);
            if (liquidType != null)
            {
                double maxNlPerCm = liquidType.MaxNlPerCm;
                return calc.CalculateNanoliterPerCentimeter(color, maxNlPerCm);
            }
            return 0.0;
        }

        public void OnBrushStopFieldValueChanged()
        {
            IsBusy = true;

            _volumeConversionTimer.ResetReplace(() =>
            {
                if (ColorSpace == BL.Enumerations.ColorSpaces.Volume)
                {
                    //RaisePropertyChanged(nameof(IsLiquidVolumesOutOfRange));
                    if (IsLiquidVolumesOutOfRange || IsLiquidVolumeBelowMinLimit)
                    {
                        IsBusy = false;
                        return;
                    }
                }
                ConvertColor();
            });
        }

        public void ConvertColor()
        {
            try
            {
                ColorSpaces colorSpace = ColorSpace;

                BrushStop stop = CreateBrushStop(colorSpace);

                Configuration configuration = SegmentModel.Job.Machine.Configuration;
                Rml rml = SegmentModel.Job.Rml;
                bool bChangedVersion = false;
                if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.Volume && rml.ColorConversionVersion == 6)
                {
                    rml.ColorConversionVersion = 5;
                    bChangedVersion = true;
                }
                var output = _converter.Convert(stop, configuration, rml, false, false, false);
                if (bChangedVersion)
                {
                    rml.ColorConversionVersion = 6;
                }
                //output.SingleCoordinates.OutputLiquids.SingleOrDefault(x => x.LiquidType == PMR.ColorLab.LiquidType.Cyan).Volume;

                if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.Volume)
                {
                    IsOutOfGamut = false;
                    _red = output.SingleCoordinates.Red;
                    _green = output.SingleCoordinates.Green;
                    _blue = output.SingleCoordinates.Blue;
                    InitColor();
                    BestMatchColor = Color.FromRgb((byte)output.SingleCoordinates.Red, (byte)output.SingleCoordinates.Green, (byte)output.SingleCoordinates.Blue);

                }
                else if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.LAB)
                {
                    IsOutOfGamut = _converter.IsOutOfGamut(stop, configuration, rml);
                    if (IsOutOfGamut)
                    {
                        BestMatchL = (double)output.SingleCoordinates.L;
                        BestMatchA = (double)output.SingleCoordinates.A;
                        BestMatchB = (double)output.SingleCoordinates.B;
                        Lab lab = new Lab(output.SingleCoordinates.L, output.SingleCoordinates.A, output.SingleCoordinates.B);
                        Rgb rgb = new Rgb(lab.ToRgb());
                        BestMatchColor = Color.FromRgb((byte)(int)rgb.R, (byte)(int)rgb.G, (byte)(int)rgb.B);
                    }
                    else
                    {
                        BestMatchL = L;
                        BestMatchA = A;
                        BestMatchB = B;
                        Lab lab1 = new Lab(L, A, B);
                        Rgb rgb1 = new Rgb(lab1.ToRgb());
                        BestMatchColor = Color.FromRgb((byte)(int)rgb1.R, (byte)(int)rgb1.G, (byte)(int)rgb1.B);
                    }
                }
                else if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.RGB)
                {
                    IsOutOfGamut = _converter.IsOutOfGamut(stop, configuration, rml);
                    if (IsOutOfGamut)
                    {
                        BestMatchColor = Color.FromRgb((byte)output.SingleCoordinates.Red, (byte)output.SingleCoordinates.Green, (byte)output.SingleCoordinates.Blue);
                    }
                    else
                    {
                        BestMatchColor = Color.FromRgb((byte)Red, (byte)Green, (byte)Blue);
                    }
                    if (IsOutOfGamut != output.OutOfGamut)
                    {

                    }
                }
                //else if (stop.BrushColorSpace == BL.Enumerations.ColorSpaces.HSB)
                //{
                //    IsOutOfGamut = _converter.IsOutOfGamut(stop, configuration, rml);
                //    BestMatchColor = Color.FromRgb((byte)output.SingleCoordinates.Red, (byte)output.SingleCoordinates.Green, (byte)output.SingleCoordinates.Blue);
                //}
            }
            catch (Exception ex)
            {
                LogManager.Log(ex, "An error occurred while trying to get volume => RGB from conversion engine." + ex);
                BestMatchColor = Color.FromRgb((byte)Red, (byte)Green, (byte)Blue);
            }
            finally
            {
                IsBusy = false;
            }
        }

        public void IsOutputOfGamut(ColorSpaces colorSpace)
        {
            try
            {
                BrushStop stop = CreateBrushStop(colorSpace);
                Configuration configuration = SegmentModel.Job.Machine.Configuration;
                Rml rml = SegmentModel.Job.Rml;
                IsOutOfGamut = _converter.IsOutOfGamut(stop, configuration, rml);
            }
            catch (Exception ex)
            {
                LogManager.Log(ex, "An error occurred while trying to test IsOutputOfGammut from conversion engine." + ex);
                BestMatchColor = Color.FromRgb((byte)Red, (byte)Green, (byte)Blue);
            }
            finally
            {
                IsBusy = false;
            }
        }
        #endregion
    }
}