using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ColorProgressBarDemo
{
    public partial class ColorProgressBar : UserControl
    {
        public ColorProgressBar()
        {
            InitializeComponent();
        }

        private void ColorProgressBar_Paint(object sender, PaintEventArgs e)
        {
            BackColor = this.Parent.BackColor;

            //brzegi
            Pen cien = new Pen(SystemColors.ControlDark);
            Pen swiatlo = new Pen(SystemColors.ControlLightLight);
            e.Graphics.DrawLine(cien, 0, Height - 1, 0, 0);
            e.Graphics.DrawLine(cien, 0, 0, Width - 1, 0);
            e.Graphics.DrawLine(swiatlo, Width - 1, 0, Width - 1, Height - 1);
            e.Graphics.DrawLine(swiatlo, Width - 1, Height - 1, 0, Height - 1);

            //pasek
            Bitmap bufor = new Bitmap(Width, Height);
            Graphics g = Graphics.FromImage(bufor);
            BackColor = this.Parent.BackColor;

            const int margines = 2;
            int stepwidth = 2 * Height / 3;
            double procenty = 0;
            if (Maximum > Minimum) procenty = (Value - Minimum) / (double)(Maximum - Minimum);
            int szerokosc = (int)Math.Round(procenty * (Width - 2 * margines - 1));
            for (int i = margines; i < margines + szerokosc; i++)
            {
                if (!Smooth && ((i % stepwidth) > 0) && (i % stepwidth < margines + 1)) continue;
                g.DrawLine(new Pen(ObliczKolor(i)), i, margines, i, Height - margines - 1);
            }

            e.Graphics.DrawImage(bufor, 0, 0);
        }

        private Color ObliczKolor(int i)
        {
            if (i < 0 || i > Width) throw new Exception("Zly parametr i");
            return Color.FromArgb(
                ColorBegin.R + i * (ColorEnd.R - ColorBegin.R) / Width,
                ColorBegin.G + i * (ColorEnd.G - ColorBegin.G) / Width,
                ColorBegin.B + i * (ColorEnd.B - ColorBegin.B) / Width);
        }

        #region Wlasnosci
        private int minimum = 0;
        private int maximum = 100;
        private int value = 0;
        private int step = 10;
        private Color colorBegin = Color.Yellow;
        private Color colorEnd = Color.Red;
        private bool smooth;

        [
            Category("Behavior"),
            Description("Dolna granica zakresu wartości, jakie mogą być prezentowane przez komponent.")
        ]
        public int Minimum
        {
            get { return minimum; }
            set
            {
                if (value > maximum) value = maximum;
                minimum = value;
                Refresh();
            }
        }

        [
            Category("Behavior"),
            Description("Górna granica zakresu wartości, jakie mogą być prezentowane przez komponent.")
        ]
        public int Maximum
        {
            get { return maximum; }
            set
            {
                if (value < minimum) value = minimum;
                maximum = value;
                Refresh();
            }
        }

        [
            Category("Behavior"),
            Description("Wartość prezentowana przez komponent.")
        ]
        public int Value
        {
            get { return this.value; }
            set
            {
                if (value < minimum) value = minimum;
                if (value > maximum) value = maximum;
                if (this.value != value)
                {
                    this.value = value;
                    OnValueChanged(this, new EventArgs(), value);
                    Refresh();
                }
            }
        }

        [
            Category("Behavior"),
            Description("Wielkość, o którą zwiększana jest własność Value przez metodę PerformStep().")
        ]
        public int Step
        {
            get { return step; }
            set { step = value; }
        }

        [
            Category("Appearance"),
            Description("Pierwszy kolor wyznaczający gradient barw widoczny na pasku postępu.")
        ]
        public Color ColorBegin
        {
            get { return colorBegin; }
            set
            {
                colorBegin = value;
                Refresh();
            }
        }

        [
            Category("Appearance"),
            Description("Drugi kolor wyznaczający gradient barw widoczny na pasku postępu.")
        ]
        public Color ColorEnd
        {
            get { return colorEnd; }
            set
            {
                colorEnd = value;
                Refresh();
            }
        }

        [
            Category("Appearance"),
            Description("Jeżeli wartość ta równa jest true, pasek jest gładki.")
        ]
        public bool Smooth
        {
            get { return smooth; }
            set
            {
                smooth = value;
                Refresh();
            }
        }
        #endregion

        public void PerformStep()
        {
            Value += Step;
        }

        private void ColorProgressBar_Resize(object sender, EventArgs e)
        {
            Refresh();
        }

        #region Zdarzenie ValueChanged
        public delegate void ValueChangedEventHandler(object sender, EventArgs e, int value);

        [
            Category("Behavior"),
            Description("Zachodzi w przypadku zmiany własności Value.")
        ]
        public event ValueChangedEventHandler ValueChanged;

        protected virtual void OnValueChanged(object sender, EventArgs e, int value)
        {
            if (ValueChanged != null) ValueChanged(this, e, value);
        }
        #endregion
    }
}
