public Window1()
 {
     InitializeComponent();
     DataContext = this;
     SelectedPoint = new PatternPoint(Color.FromArgb(169, 104, 54), 1);
     //SelectedPoint = new PatternPoint(Color.FromArgb(100, 100, 48), 1);
     //lp.HslColor = new HslColor(30, 0.53, 0.44);
 }
 private void Button_Click(object sender, RoutedEventArgs e)
 {
     SelectedPoint = new PatternPoint(Color.FromArgb(100, 100, 48), 1);
 }
        private void MakeGradient(PatternPoint from, PatternPoint to)
        {
            HSBcolor hsb;
            //Color from = fromPoint.PointColor;
            //Color to = toPoint.PointColor;
            int stepCount = to.LedPos - from.LedPos; 
            //Console.WriteLine("From: {0}     To: {1}", from.LedPos, to.LedPos);
            double deltaHue = (to.Hue - from.Hue) / stepCount; 
            double deltaSat = (to.Saturation - from.Saturation) / stepCount; 
            double deltaBri = (to.Brightness - from.Brightness) / stepCount; 
            StripModel[from.LedPos - 1].PointColor = from.PointColor;
            StripModel[to.LedPos - 1].PointColor = to.PointColor;

            for (int i = 1; i < stepCount; i++)
            {
                hsb = new HSBcolor(from.Hue + i * deltaHue,
                                   from.Saturation + i * deltaSat,
                                   from.Brightness + i * deltaBri);
                StripModel[from.LedPos + i - 1].PointColor = hsb.RgbColor;
            }
        }
        /************************************************************************/

        #region Main Methods

        private void UpdateModel()
        {
            PatternPoint previousPoint = null;

            Stopwatch watch = new Stopwatch();
            watch.Start();


            for (int i = 0; i < StripModel.Count; i++)
                StripModel[i].PointColor = Color.Black;


            foreach (PatternPoint pp in Pattern)
            {
                if (previousPoint != null)
                {
                    if (pp.LedCount == 1)
                    {
                        // какая бы не была предыдуяя точка строим градиент
                        MakeGradient( previousPoint, pp );
                        previousPoint = pp; 
                    }
                    else
                    {
                        // диапазон
                        MakeGradient(previousPoint, pp);
                        for (int i = 0; i < pp.LedCount; i++)
                            StripModel[pp.LedPos + i].PointColor = pp.PointColor;
                        previousPoint = new PatternPoint(pp.PointColor, pp.LedPos + pp.LedCount - 1);
                    }
                }
                else
                {
                    // первая точка
                    for (int i = 0; i < pp.LedPos; i++)
                        StripModel[i].PointColor = Color.Black;
                    previousPoint = pp;
                }
            }

            watch.Stop();
            Console.WriteLine("Measured time: " + watch.Elapsed.TotalMilliseconds + " ms.");
        }
 private void UpdateGradient(PatternPoint from, PatternPoint to, List<PatternPoint> lightnessCurve)
 {
     PatternPoint tmpFrom;
     tmpFrom = from;
     foreach (PatternPoint pp in lightnessCurve)
     {
         MakeGradient(tmpFrom, pp);
         tmpFrom = pp;
     }
     MakeGradient(tmpFrom, to);
 }
        private List<PatternPoint> GetLightnessCurve(PatternPoint from, PatternPoint to)
        {
            List<PatternPoint> lightnessCurve = null;
            int fromIx = Pattern.IndexOf(from);
            int toIx = Pattern.IndexOf(to);
            int stepCount = 0;
            int baseLedPos;
            HslColor hsl;

            double deltaHue = 0.0;
            double deltaSat = 0.0;

            if ((toIx - fromIx) != 0)       // имеются яркостные точки
            {
                lightnessCurve = new List<PatternPoint>();
                for (int i = fromIx + 1; i < toIx; i++)
                    lightnessCurve.Add(Pattern[i]);


                if (from.Variant == PointVariant.Range)
                    baseLedPos = (from.LedPos + from.LedCount - 1);
                else
                    baseLedPos = from.LedPos;

                stepCount = to.LedPos - baseLedPos;

                deltaHue = (to.HslColor.Hue - from.HslColor.Hue) / stepCount;
                deltaSat = (to.HslColor.Saturation - from.HslColor.Saturation) / stepCount;

                blockOnPointColorChanged = true;
                foreach (PatternPoint pp in lightnessCurve)
                {
                    hsl = new HslColor(from.HslColor.Hue + (pp.LedPos - baseLedPos) * deltaHue,
                                       from.HslColor.Saturation + (pp.LedPos - baseLedPos) * deltaSat,
                                       pp.HslColor.Lightness);
                    pp.HslColor = hsl;
                }
                blockOnPointColorChanged = false;
            }
            return lightnessCurve;
        }
        private void MakeGradient(PatternPoint from, PatternPoint to)
        {
            HslColor hsl;
            int stepCount = 0;
            PatternPoint tmpFrom = null;

            if (to.Variant == PointVariant.Range)
                for (int i = 0; i < to.LedCount; i++)
                    StripModel[to.LedPos + i - 1].PointColor = to.PointColor;

            if (from.Variant == PointVariant.Range)
            {
                for (int i = 0; i < from.LedCount; i++)
                    StripModel[from.LedPos + i - 1].PointColor = from.PointColor;
                tmpFrom = new PatternPoint(from.PointColor, from.LedPos + from.LedCount - 1);
            }
            else
                tmpFrom = from;

            stepCount = to.LedPos - tmpFrom.LedPos;
            double deltaHue = (to.HslColor.Hue - tmpFrom.HslColor.Hue) / stepCount;
            double deltaSat = (to.HslColor.Saturation - tmpFrom.HslColor.Saturation) / stepCount;
            double deltaBri = (to.HslColor.Lightness - tmpFrom.HslColor.Lightness) / stepCount;

            StripModel[tmpFrom.LedPos - 1].PointColor = tmpFrom.PointColor;
            //Console.WriteLine("Pos: {0}  Hue: {1},  Lightness: {2}", from.LedPos, from.HslColor.Hue, from.HslColor.Lightness);
            StripModel[to.LedPos - 1].PointColor = to.PointColor;

            for (int i = 1; i < stepCount; i++)
            {
                hsl = new HslColor(from.HslColor.Hue + i * deltaHue,
                                   from.HslColor.Saturation + i * deltaSat,
                                   from.HslColor.Lightness + i * deltaBri);
                StripModel[tmpFrom.LedPos + i - 1].PointColor = hsl.ToRGB();
                //Console.WriteLine("Pos: {0}  Hue: {1},  Lightness: {2}", from.LedPos + i, hsl.Hue, hsl.Lightness);
            }
            //Console.WriteLine("Pos: {0}  Hue: {1},  Lightness: {2}", to.LedPos, to.HslColor.Hue, to.HslColor.Lightness);
        }
        private void OnSliderClick(object sender, MouseButtonEventArgs e)
        {
            PatternPoint pp1 = null;
            if (e.ClickCount == 2)      // DoubleClick
            {
                System.Windows.Point pt = e.GetPosition((UIElement)sender);
                //Console.WriteLine("X: {0} Y: {1}", pt.X, pt.Y);
                //Console.WriteLine("ActualWidth: {0}", sliderArea.ActualWidth);
                int ledPos = (int)(pt.X * Maximum / sliderArea.ActualWidth);
                if (ledPos < 1)
                    ledPos = 1;
                //Console.WriteLine("LedPos: {0}", ledPos);
                //PatternPoint leftPoint = null;
                //PatternPoint rightPoint = null;

                //foreach (PatternPoint pp in Pattern)
                //{
                //    if (ledPos > pp.LedPos)
                //        leftPoint = pp;
                //}

                //for (int i = Pattern.Count - 1; i >= 0; i--)
                //{
                //    if (ledPos < Pattern[i].LedPos)
                //        rightPoint = Pattern[i];
                //}

                // если первая точка в Pattern
                if (ledPos < sliders[0].Value)
                {
                    switch (workMode)
                    {
                        case Mode.Range:
                            if ((sliders[0].Value - ledPos) >= 2)
                            {
                                pp1 = new PatternPoint(Pattern[0].PointColor, ledPos) { LedCount = 2, Variant = PointVariant.Range };
                            }
                            else
                                return;
                            break;
                        case Mode.Lightness:
                            return;
                        default:
                            pp1 = new PatternPoint(Pattern[0].PointColor, ledPos) { LedCount = 1 };
                            break;
                    }
                    
                    Pattern.Insert(0, pp1);
                    if (selectedSliderItem != null)
                        selectedSliderItem = null;
                    InsertSliders();
                    UpdateModel();
                    SelectedPoint = pp1;
                    return;
                }

                // если последняя точка в Pattern
                if (ledPos > sliders[sliders.Count - 1].Value)
                {
                    switch (workMode)
                    {
                        case Mode.Range:
                            if ((Maximum - ledPos) >= 2)
                            {
                                pp1 = new PatternPoint(Pattern[Pattern.Count - 1].PointColor, ledPos) { LedCount = 2, Variant = PointVariant.Range };
                            }
                            else
                                return;
                            break;
                        case Mode.Lightness:
                            return;
                        default:
                            pp1 = new PatternPoint(Pattern[Pattern.Count - 1].PointColor, ledPos) { LedCount = 1 };
                            break;
                    }
                    Pattern.Add(pp1);
                    if (selectedSliderItem != null)
                        selectedSliderItem = null;
                    InsertSliders();
                    UpdateModel();
                    SelectedPoint = pp1;
                    return;
                }

                // между PatternPoint
                PatternPoint before;
                PatternPoint after;
                for ( int i = 0; i < sliders.Count - 1; i++)
                {
                    if (ledPos > sliders[i].Value && ledPos < sliders[i + 1].Value)
                    {
                        if ((sliders[i].Variant == SliderVariant.RangeLeftLimit) &&
                            (sliders[i + 1].Variant == SliderVariant.RangeRightLimit))
                            // внутри Range не может быть точек
                            return;

                        before = Pattern[sliders[i].PatternIx];
                        after = Pattern[sliders[i + 1].PatternIx];
                        switch (workMode)
                        {
                            case Mode.Range:
                                if ((sliders[i + 1].Value - ledPos) > 2)
                                {
                                    //pp1 = new PatternPoint(before.PointColor, ledPos) { LedCount = 2, Variant = PointVariant.Range };
                                    pp1 = new PatternPoint(StripModel[ledPos - 1].PointColor, ledPos) { LedCount = 2, Variant = PointVariant.Range };
                                }
                                else
                                    return;
                                break;
                            case Mode.Lightness:
                                pp1 = new PatternPoint(StripModel[ledPos - 1].PointColor, ledPos) { LedCount = 1, Variant = PointVariant.Lightness };
                                break;
                            default:
                                pp1 = new PatternPoint(StripModel[ledPos - 1].PointColor, ledPos) { LedCount = 1 };
                                break;
                        }
                        Pattern.Insert(Pattern.IndexOf(after), pp1);
                        if (selectedSliderItem != null)
                            selectedSliderItem = null;
                        InsertSliders();
                        UpdateModel();
                        SelectedPoint = pp1;
                        return;
                    }
                }
                

                // между точками
                //Color c = (display.Items[ledPos] as PatternPoint).PointColor;
                //int ix = Pattern.IndexOf(rightPoint);
                //pp1 = new PatternPoint(c, ledPos) { LedCount = 1 };
                //Pattern.Insert(ix, pp1);

                //InsertSliders();
                //SelectedPoint = pp1;
            }
        }