/******************************************************************************
 * SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
 * CopyRight (C) 2012-2022 ShenYongHua(沈永华).
 * QQ群：56829229 QQ：17612584 EMail：SunnyUI@QQ.Com
 *
 * Blog:   https://www.cnblogs.com/yhuse
 * Gitee:  https://gitee.com/yhuse/SunnyUI
 * GitHub: https://github.com/yhuse/SunnyUI
 *
 * SunnyUI.dll can be used for free under the GPL-3.0 license.
 * If you use this code, please keep this note.
 * 如果您使用此代码，请保留此说明。
 ******************************************************************************
 * 文件名称: UIIntegerUpDown.cs
 * 文件说明: 数字上下选择框
 * 当前版本: V3.1
 * 创建日期: 2020-01-01
 *
 * 2020-01-01: V2.2.0 增加文件说明
 * 2020-04-25: V2.2.4 更新主题配置类
 * 2020-08-14: V2.2.7 增加字体调整
 * 2020-12-10: V3.0.9 增加Readonly属性
******************************************************************************/

using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Sunny.UI
{
    [DefaultEvent("ValueChanged")]
    [DefaultProperty("Value")]
    public sealed partial class UIIntegerUpDown : UIPanel, IToolTip
    {
        public delegate void OnValueChanged(object sender, int value);

        public UIIntegerUpDown()
        {
            InitializeComponent();
            SetStyleFlags();
            ShowText = false;
            edit.Type = UITextBox.UIEditType.Integer;
            edit.Parent = pnlValue;
            edit.Visible = false;
            edit.BorderStyle = BorderStyle.None;
            edit.TextChanged += Edit_TextChanged;
            edit.Leave += Edit_Leave;
            pnlValue.Paint += PnlValue_Paint;
        }

        public Control ExToolTipControl()
        {
            return pnlValue;
        }

        private void PnlValue_Paint(object sender, PaintEventArgs e)
        {
            if (Enabled)
            {
                e.Graphics.DrawLine(RectColor, 0, 0, pnlValue.Width, 0);
                e.Graphics.DrawLine(RectColor, 0, Height - 1, pnlValue.Width, Height - 1);
            }
            else
            {
                e.Graphics.DrawLine(RectDisableColor, 0, 0, pnlValue.Width, 0);
                e.Graphics.DrawLine(RectDisableColor, 0, Height - 1, pnlValue.Width, Height - 1);
            }
        }

        private void Edit_Leave(object sender, EventArgs e)
        {
            if (edit.Visible)
            {
                edit.Visible = false;
                pnlValue.FillColor = pnlColor;
            }
        }

        private void Edit_TextChanged(object sender, EventArgs e)
        {
            if (edit != null && edit.Visible)
            {
                Value = edit.Text.ToInt();
            }
        }

        public event OnValueChanged ValueChanged;

        private int _value;

        [DefaultValue(0)]
        [Description("选中数值"), Category("SunnyUI")]
        public int Value
        {
            get => _value;
            set
            {
                value = CheckMaxMin(value);
                _value = value;
                pnlValue.Text = _value.ToString();
                ValueChanged?.Invoke(this, _value);
            }
        }

        protected override void OnFontChanged(EventArgs e)
        {
            base.OnFontChanged(e);

            if (pnlValue != null)
            {
                pnlValue.IsScaled = true;
                pnlValue.Font = Font;
            }

            if (edit != null)
            {
                edit.IsScaled = true;
                edit.Font = Font;
            }
        }

        private int step = 1;

        [DefaultValue(1)]
        [Description("步进值"), Category("SunnyUI")]
        public int Step
        {
            get => step;
            set => step = Math.Max(1, value);
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (ReadOnly) return;

            Value += Step;
            if (edit.Visible)
            {
                edit.Visible = false;
                pnlValue.FillColor = pnlColor;
            }
        }

        private void btnDec_Click(object sender, EventArgs e)
        {
            if (ReadOnly) return;

            Value -= Step;
            if (edit.Visible)
            {
                edit.Visible = false;
                pnlValue.FillColor = pnlColor;
            }
        }

        private int _maximum = int.MaxValue;
        private int _minimum = int.MinValue;

        [Description("最大值"), Category("SunnyUI")]
        [DefaultValue(int.MaxValue)]
        public int Maximum
        {
            get => _maximum;
            set
            {
                _maximum = value;
                if (_maximum < _minimum)
                    _minimum = _maximum;

                Value = CheckMaxMin(Value);
                edit.MaxValue = _maximum;
                Invalidate();
            }
        }

        [Description("最小值"), Category("SunnyUI")]
        [DefaultValue(int.MinValue)]
        public int Minimum
        {
            get => _minimum;
            set
            {
                _minimum = value;
                if (_minimum > _maximum)
                    _maximum = _minimum;

                Value = CheckMaxMin(Value);
                edit.MinValue = _maximum;
                Invalidate();
            }
        }

        private int CheckMaxMin(int value)
        {
            if (hasMaximum)
            {
                if (value > _maximum)
                    value = _maximum;
            }

            if (hasMinimum)
            {
                if (value < _minimum)
                    value = _minimum;
            }

            return value;
        }

        [DefaultValue(false)]
        [Description("是否判断最大值显示"), Category("SunnyUI")]
        public bool MaximumEnabled
        {
            get => HasMaximum;
            set => HasMaximum = value;
        }

        [DefaultValue(false)]
        [Description("是否判断最小值显示"), Category("SunnyUI")]
        public bool MinimumEnabled
        {
            get => HasMinimum;
            set => HasMinimum = value;
        }

        private bool hasMaximum;
        private bool hasMinimum;

        [DefaultValue(false), Browsable(false)]
        [Description("检查最大值"), Category("SunnyUI")]
        public bool HasMaximum
        {
            get => hasMaximum;
            set
            {
                if (hasMaximum != value)
                {
                    hasMaximum = value;
                    Value = CheckMaxMin(Value);
                    edit.HasMaxValue = value;
                    Invalidate();
                }
            }
        }

        [DefaultValue(false), Browsable(false)]
        [Description("检查最小值"), Category("SunnyUI")]
        public bool HasMinimum
        {
            get => hasMinimum;
            set
            {
                if (hasMinimum != value)
                {
                    hasMinimum = value;
                    Value = CheckMaxMin(Value);
                    edit.HasMinValue = value;
                    Invalidate();
                }
            }
        }

        private readonly UIEdit edit = new UIEdit();
        private Color pnlColor;
        private void pnlValue_DoubleClick(object sender, EventArgs e)
        {
            if (ReadOnly) return;

            edit.Left = 1;
            edit.Top = (pnlValue.Height - edit.Height) / 2;
            edit.Width = pnlValue.Width - 2;
            pnlColor = pnlValue.FillColor;
            pnlValue.FillColor = Color.White;
            edit.TextAlign = HorizontalAlignment.Center;
            edit.Text = pnlValue.Text;
            edit.BringToFront();
            edit.Visible = true;
            edit.Focus();
            edit.SelectAll();
        }

        [DefaultValue(false)]
        [Description("是否只读"), Category("SunnyUI")]
        public bool ReadOnly { get; set; }
    }
}