using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Text.Json.Serialization;
using DH.Commons.Enums;
using static DH.Commons.Enums.EnumHelper;


namespace DH.UI.Model.Winform
{
    [Serializable]
    public abstract class ElementBase : IShapeElement, IEventHandle, ICloneable,  IComparable<ElementBase>, IDisposable
    {
        #region 常量
        protected int _mouseIntersectDistance = 4;
        #endregion

        #region 标识符
        /// <summary>
        /// ID,采用GUID
        /// </summary>
        [ReadOnly(true)]
        [Category("\t通用标识")]
        [Description("GUID")]
        public virtual string ID { get; set; } = Guid.NewGuid().ToString().ToUpper();

        /// <summary>
        /// 序号
        /// </summary>
        [Category("\t通用标识")]
        [Description("序号")]
        public virtual int Index { get; set; } = 0;

        [Browsable(false)]
        public virtual int GroupIndex { get; set; } = 0;

        private string name = "";
        /// <summary>
        /// 名称
        /// </summary>
        [Category("\t通用标识")]
        [Description("名称")]
        public virtual string Name
        {
            get
            {
                if (string.IsNullOrWhiteSpace(name))
                {
                    return GetDisplayText();
                }
                else
                {
                    return name;
                }
            }
            set => name = value;
        }
        #endregion

        #region 启用状态
        private bool isEnabled = true;

        //[Browsable(false)]
        public virtual bool IsEnabled
        {
            get
            {
                return isEnabled;
            }
            set
            {
                //if (isEnabled != value)
                //{
                //    isEnabled = value;

                //    PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs("IsEnabled"), null, null);
                //}

                Set(ref isEnabled, value);
            }
        }

        [Browsable(false)]
        public virtual bool IsShowing { get; set; } = true;

        private bool showList = true;
        [Browsable(false)]
        public virtual bool ShowList
        {
            get => showList;
            set => Set(ref showList, value);
        }
        #endregion

        #region 字段
        [JsonIgnore]
        protected PointF _startPoint, _currentPoint;
        #endregion

        #region 绘图特性
        [Browsable(false)]
        public NoticedPoints CreatePoints { get; set; } = new NoticedPoints();

        public virtual bool IsCreatedDone()
        {
            return CreatePoints.Count >= 2;
        }

        //protected Region Region { get; set; }

        #region 画笔相关
        #region 绘图画笔
        [JsonIgnore]
        [Browsable(false)]
        protected Pen Pen { get; set; } = new Pen(Color.Red, 1);

        protected virtual void SetNewStatePen()
        {
            Pen = new Pen(Color.Red, 3);
        }

        protected virtual void SetNormalPen()
        {
            Pen = new Pen(Color.Red, 1);
        }

        protected virtual void SetHoverPen()
        {
            Pen = new Pen(Color.BlueViolet, 3);
        }

        protected virtual void SetInSidePen()
        {
            Pen = new Pen(Color.YellowGreen, 3);
        }

        protected virtual void SetSelectedPen()
        {
            Pen = new Pen(Color.Pink, 3);
        }

        protected virtual void SetMeasureDoneOKPen()
        {
            Pen = new Pen(Color.Green, 2);
        }

        protected virtual void SetMeasureDoneNGPen()
        {
            Pen = new Pen(Color.Red, 2);
        }

        protected virtual void SetMeasuringPen()
        {
            Pen = new Pen(Color.Yellow, 3);
        }
        #endregion

        #region 文字画笔
        //[JsonIgnore]
        //protected Pen PenText = new Pen(Color.Black, 1);
        //[JsonIgnore]
        //protected Pen PenTextOK = new Pen(Color.Green, 1.5f);
        //[JsonIgnore]
        //protected Pen PenTextNG = new Pen(Color.Red, 2);

        ///// <summary>
        ///// 字体大小
        ///// </summary>
        //[Category("显示属性")]
        //[Description("字体大小")]
        ////[Browsable(false)]
        //public virtual float FontSize { get; set; } = 15;
        /// <summary>
        /// 字体大小
        /// </summary>
        [Category("显示属性")]
        [Description("字体设置")]
        [Browsable(false)]
        public virtual Font Font { get; set; } = new Font(new FontFamily("Tahoma"), 15, GraphicsUnit.World);

        /// <summary>
        /// 字体和基元的距离
        /// </summary>
        [Category("显示属性")]
        [Description("字体和基元的距离")]
        [Browsable(false)]
        public virtual int FontDistance { get; set; } = 15;

        [Category("显示属性")]
        [Description("显示字符说明")]
        [Browsable(false)]
        public virtual bool IsShowRemark { get; set; } = true;

        #endregion
        #endregion

        //public Graphics Graphics { get; set; }
        public abstract void Draw(Graphics g);
        protected abstract void DrawResult(Graphics g);
        #endregion

        #region 状态
        private ElementState state = ElementState.New;
        [JsonIgnore]
        [Browsable(false)]
        public ElementState State
        {
            get
            {
                return state;
            }
            set
            {
                if (state != value)
                {
                    ElementState preState = state;
                    Set(ref state, value);
                    EventRouter.TriggerElementsMouseStateChanged(this, preState, state);
                    switch (state)
                    {
                        case ElementState.MouseHover:
                            SetHoverPen();
                            break;
                        case ElementState.MouseInSide:
                            SetInSidePen();
                            break;
                        case ElementState.Selected:
                            SetSelectedPen();
                            break;
                        case ElementState.Normal:
                            SetNormalPen();
                            break;
                        case ElementState.Measuring:
                            SetMeasuringPen();
                            break;
                        case ElementState.MeasureDoneOK:
                            SetMeasureDoneOKPen();
                            break;
                        case ElementState.MeasureDoneNG:
                            SetMeasureDoneNGPen();
                            break;
                        case ElementState.New:
                            SetNewStatePen();
                            break;
                    }
                }
            }
        }

        /// <summary>
        /// 是否是运行模式
        /// </summary>
        [Browsable(false)]
        public RunMode RunMode { get; set; } = RunMode.NormalMode;
        #endregion

        #region 复制
        public abstract object Clone();

        public virtual void Initial()
        {
            State = ElementState.New;
            CreatePoints = new NoticedPoints();
        }
        #endregion

        #region IMouseEvent
        public virtual void OnMouseDoubleClick(PointF p)
        {
            if (State == ElementState.MeasureDoneNG || State == ElementState.MeasureDoneOK)
                return;

            //if (State == ElementState.MouseInSide)
            //{
            //    State = ElementState.Selected;
            //}
            //else if (State == ElementState.Selected || State == ElementState.Moving)
            //{
            //    if (IsMouseInSide(p))
            //    {
            //        State = ElementState.MouseInSide;
            //    }
            //}
            if (IsMouseInSide(p))
            {
                State = ElementState.Selected;
            }
        }

        public abstract void OnKeyDown(object sender, KeyEventArgs e);

        public abstract void OnKeyUp(object sender, KeyEventArgs e);

        public virtual void OnMouseDown(PointF p)
        {
            //switch (State)
            //{
            //    case ElementState.New:
            //        OnMouseDownWhenNew(p);
            //        break;
            //    case ElementState.MouseHover:
            //        break;
            //    case ElementState.MouseInSide:
            //        State = ElementState.Selected;
            //        break;
            //    case ElementState.Selected:
            //        _startPoint = p;
            //        State = ElementState.Moving;
            //        break;
            //    case ElementState.Normal:
            //        break;
            //}
            if (State == ElementState.New)
            {
                OnMouseDownWhenNew(p);
            }
            else if (IsMouseCanMoveElement(p) && State == ElementState.Selected)
            {
                State = ElementState.Moving;
            }
            else if (IsMouseCanStretchBottom(p) && State == ElementState.CanStretchBottom)
            {
                State = ElementState.StretchingBottom;
            }
            else if (IsMouseCanStretchTop(p) && State == ElementState.CanStretchTop)
            {
                State = ElementState.StretchingTop;
            }
            else if (IsMouseCanStretchLeft(p) && State == ElementState.CanStretchLeft)
            {
                State = ElementState.StretchingLeft;
            }
            else if (IsMouseCanStretchRight(p) && State == ElementState.CanStretchRight)
            {
                State = ElementState.StretchingRight;
            }
            else if (IsMouseCanStretchLeftLowerCorner(p) && State == ElementState.CanStretchLeftLowerCorner)
            {
                State = ElementState.StretchingLeftLowerCorner;
            }
            else if (IsMouseCanStretchLeftUpperCorner(p) && State == ElementState.CanStretchLeftUpperCorner)
            {
                State = ElementState.StretchingLeftUpperCorner;
            }
            else if (IsMouseCanStretchRightLowerCorner(p) && State == ElementState.CanStretchRightLowerCorner)
            {
                State = ElementState.StretchingRightLowerCorner;
            }
            else if (IsMouseCanStretchRightUpperCorner(p) && State == ElementState.CanStretchRightUpperCorner)
            {
                State = ElementState.StretchingRightUpperCorner;
            }
        }

        public virtual void OnMouseMove(PointF p)
        {
            switch (State)
            {
                case ElementState.New:
                    OnMouseMoveWhenNew(p);
                    break;
                case ElementState.Selected:
                    {
                        if (IsMouseCanStretchLeft(p))
                        {
                            State = ElementState.CanStretchLeft;
                        }
                        else if (IsMouseCanStretchRight(p))
                        {
                            State = ElementState.CanStretchRight;
                        }
                        else if (IsMouseCanStretchTop(p))
                        {
                            State = ElementState.CanStretchTop;
                        }
                        else if (IsMouseCanStretchBottom(p))
                        {
                            State = ElementState.CanStretchBottom;
                        }
                        else if (IsMouseCanStretchLeftLowerCorner(p))
                        {
                            State = ElementState.CanStretchLeftLowerCorner;
                        }
                        else if (IsMouseCanStretchLeftUpperCorner(p))
                        {
                            State = ElementState.CanStretchLeftUpperCorner;
                        }
                        else if (IsMouseCanStretchRightLowerCorner(p))
                        {
                            State = ElementState.CanStretchRightLowerCorner;
                        }
                        else if (IsMouseCanStretchRightUpperCorner(p))
                        {
                            State = ElementState.CanStretchRightUpperCorner;
                        }

                        break;
                    }
                case ElementState.Moving:
                    _currentPoint = p;
                    //Translate(_currentPoint.X - _startPoint.X, _currentPoint.Y - _startPoint.Y);
                    //_startPoint = _currentPoint;
                    Relocate(p);
                    break;
                case ElementState.MouseHover:
                case ElementState.MouseInSide:
                case ElementState.Normal:
                    //if (IsMouseInSide(p))
                    //{
                    //    State = ElementState.MouseInSide;
                    //}
                    //else if (IsMouseHover(p))
                    //{
                    //    State = ElementState.MouseHover;
                    //}
                    //else
                    //{
                    //    State = ElementState.Normal;
                    //}
                    break;
                case ElementState.CanStretchBottom:
                    if (!IsMouseCanStretchBottom(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchTop:
                    if (!IsMouseCanStretchTop(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchLeft:
                    if (!IsMouseCanStretchLeft(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchRight:
                    if (!IsMouseCanStretchRight(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchLeftUpperCorner:
                    if (!IsMouseCanStretchLeftUpperCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchLeftLowerCorner:
                    if (!IsMouseCanStretchLeftLowerCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchRightLowerCorner:
                    if (!IsMouseCanStretchRightLowerCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.CanStretchRightUpperCorner:
                    if (!IsMouseCanStretchRightUpperCorner(p))
                    {
                        State = ElementState.Selected;
                    }
                    break;
                case ElementState.StretchingTop:
                    StretchTop(p);
                    break;
                case ElementState.StretchingBottom:
                    StretchBottom(p);
                    break;
                case ElementState.StretchingLeft:
                    StretchLeft(p);
                    break;
                case ElementState.StretchingRight:
                    StretchRight(p);
                    break;
                case ElementState.StretchingLeftLowerCorner:
                    StretchLeftLowerCorner(p);
                    break;
                case ElementState.StretchingLeftUpperCorner:
                    StretchLeftUpperCorner(p);
                    break;
                case ElementState.StretchingRightLowerCorner:
                    StretchRightLowerCorner(p);
                    break;
                case ElementState.StretchingRightUpperCorner:
                    StretchRightUpperCorner(p);
                    break;
            }
        }

        public virtual void OnMouseUp(PointF p)
        {
            switch (State)
            {
                case ElementState.New:
                    OnMouseUpWhenNew(p);
                    break;
                case ElementState.Moving:
                    State = ElementState.Selected;
                    break;
                case ElementState.Selected:
                    if (!IsMouseInSide(p))
                    {
                        State = ElementState.Normal;
                    }
                    break;
                case ElementState.StretchingBottom:
                    State = ElementState.CanStretchBottom;
                    break;
                case ElementState.StretchingLeft:
                    State = ElementState.CanStretchLeft;
                    break;
                case ElementState.StretchingRight:
                    State = ElementState.CanStretchRight;
                    break;
                case ElementState.StretchingTop:
                    State = ElementState.CanStretchTop;
                    break;
                case ElementState.StretchingLeftLowerCorner:
                    State = ElementState.CanStretchLeftLowerCorner;
                    break;
                case ElementState.StretchingLeftUpperCorner:
                    State = ElementState.CanStretchLeftUpperCorner;
                    break;
                case ElementState.StretchingRightUpperCorner:
                    State = ElementState.CanStretchRightUpperCorner;
                    break;
                case ElementState.StretchingRightLowerCorner:
                    State = ElementState.CanStretchRightLowerCorner;
                    break;
                default:
                    State = ElementState.Normal;
                    break;
            }

            AfterTranformOp();
        }

        public virtual void AfterTranformOp()
        {
        }

        #region 当基元状态为新建或可编辑时的鼠标操作动作
        /// <summary>
        /// 当状态为New时的鼠标按下操作
        /// </summary>
        /// <param name="p"></param>
        public abstract void OnMouseDownWhenNew(PointF p);

        public abstract void OnMouseMoveWhenNew(PointF p);

        public abstract void OnMouseUpWhenNew(PointF p);
        #endregion

        #endregion

        #region 委托事件
        [JsonIgnore]
        public Action<ElementBase> OnDrawDone;
        [JsonIgnore]
        public Action<ElementBase> OnMeasureDone;
        [JsonIgnore]
        public Action<ElementBase> OnElementEnableChanged;
        #endregion

        #region 几何特性
        /// <summary>
        /// 基类基础的Rectangle 用于计算MouseHover和Inside等
        /// </summary>
        [Browsable(false)]
        public Rectangle BaseRectangle { get; set; }
     

        public abstract bool IsMouseHover(PointF p);

        public abstract bool IsMouseInSide(PointF p);

        public abstract bool IsIntersect(RectangleF rect);
        #region Move & Stretch & Move Anchor
        public virtual bool IsMouseCanMoveElement(PointF p)
        {
            return false;
        }

        public virtual bool IsMouseCanStretchLeft(PointF p)
        {
            return false;
        }

        public virtual bool IsMouseCanStretchRight(PointF p)
        {
            return false;
        }

        public virtual bool IsMouseCanStretchTop(PointF p)
        {
            return false;
        }

        public virtual bool IsMouseCanStretchBottom(PointF p)
        {
            return false;
        }

        public virtual void StretchLeft(PointF p)
        {
        }

        public virtual void StretchRight(PointF p)
        {
        }

        public virtual void StretchTop(PointF p)
        {
        }

        public virtual void StretchBottom(PointF p)
        {
        }

        public virtual bool IsMouseCanStretchLeftUpperCorner(PointF p)
        {
            return false;
        }

        public virtual bool IsMouseCanStretchRightUpperCorner(PointF p)
        {
            return false;
        }

        public virtual bool IsMouseCanStretchLeftLowerCorner(PointF p)
        {
            return false;
        }

        public virtual bool IsMouseCanStretchRightLowerCorner(PointF p)
        {
            return false;
        }

        public virtual void StretchLeftUpperCorner(PointF p)
        {
        }

        public virtual void StretchRightUpperCorner(PointF p)
        {
        }

        public virtual void StretchLeftLowerCorner(PointF p)
        {
        }

        public virtual void StretchRightLowerCorner(PointF p)
        {
        }

        public virtual bool IsMouseCanMoveAnchor(PointF p)
        {
            return false;
        }
        #endregion

        #endregion

        #region 变形操作
        public abstract void Translate(float x, float y);

        public virtual void Relocate(PointF point) { }

        //public abstract void RotateAt(int x, int y, float degree);
        #endregion

        #region 运动
        //[Browsable(false)]
        //public PlanPoint MovePoint { get; set; }
        #endregion

        #region 相机
        //[Browsable(false)]
        //public CameraOperationConfigBase CameraOpConfig { get; set; }
        #endregion

        #region 光源
        #endregion

        #region 算法
        /// <summary>
        /// 算法
        /// </summary>
        /// <param name="paras">计算参数</param>
        public virtual void Calculate(Bitmap image) { }

        public virtual void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight) { }

        public virtual void Calculate(string imagePath) { }
        #endregion

        #region 图片保存
        //[Description("图片保存方式")]
        //public ImageSaveMode ImageSaveMode { get; set; } = ImageSaveMode.NoSave;

        //public virtual void SaveImage(Bitmap image)
        //{
        //    if (string.IsNullOrWhiteSpace(AOIMeasure.GlobalVar.ImageSaveDirectory) || ImageSaveMode == ImageSaveMode.NoSave)
        //    {
        //        return;
        //    }

        //    DirectoryInfo dir = new DirectoryInfo(GlobalVar.ImageSaveDirectory);
        //    if (!dir.Exists)
        //    {
        //        dir.Create();
        //    }

        //    string imgPath = Path.Combine(AOIMeasure.GlobalVar.ImageSaveDirectory, Name + "_" + DateTime.Now.ToString("MMdd_HHmmss") + ".bmp");
        //    switch (ImageSaveMode)
        //    {
        //        case ImageSaveMode.SaveImage:
        //            image.Save(imgPath);
        //            break;
        //        case ImageSaveMode.SaveImageWithElement:
        //            Bitmap bmp = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb);
        //            using (Graphics g = Graphics.FromImage(bmp))
        //            {
        //                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        //                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        //                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
        //                g.DrawImage(image, 0, 0, image.Width, image.Height);

        //                Draw(g);
        //            }

        //            bmp.Save(imgPath);
        //            break;
        //    }
        //}

        //public virtual void SaveImage(IntPtr imagePtr, int ptrSize)
        //{
        //    Bitmap map = null;
        //    unsafe
        //    {
        //        byte* pArray = (byte*)imagePtr;
        //        byte[] array = new byte[ptrSize];
        //        Marshal.Copy(imagePtr, array, 0, ptrSize);
        //        using (MemoryStream ms = new MemoryStream(array))
        //        {
        //            map = (Bitmap)Image.FromStream(ms);
        //        }
        //    }

        //    SaveImage(map);
        //}

        //public virtual void SaveImage(string imagePath)
        //{
        //    using (Bitmap map = Image.FromFile(imagePath) as Bitmap)
        //    {
        //        SaveImage(map);
        //    }
        //}
        #endregion

        #region 值设置
        public virtual void InitialMeasureResult()
        {
            //PropertyInfo[] prop = this.GetType().GetProperties();
            //Array.ForEach(prop, p =>
            //{
            //    if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
            //    {
            //        MeasureSpec spec = p.GetValue(this) as MeasureSpec;
            //        spec.Result = MeasureResult.NotYet;
            //        p.SetValue(this, spec);
            //    }
            //});
        }

        public virtual void SetActualValue(double v)
        {
            //PropertyInfo[] prop = this.GetType().GetProperties();
            //Array.ForEach(prop, p =>
            // {
            //     if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
            //     {
            //         MeasureSpec spec = p.GetValue(this) as MeasureSpec;
            //         spec.ActualValue = (float)v;
            //         p.SetValue(this, spec);
            //     }
            // });
        }

        public virtual void SetStandardValue(double v)
        {
            //PropertyInfo[] prop = this.GetType().GetProperties();
            //Array.ForEach(prop, p =>
            //{
            //    if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
            //    {
            //        MeasureSpec spec = p.GetValue(this) as MeasureSpec;
            //        spec.StandardValue = (float)v;
            //        p.SetValue(this, spec);
            //    }
            //});
        }
        #endregion

        #region IPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        public virtual void Set<T>(ref T field, T newValue, [CallerMemberName] string propName = null)
        {
            if (!field.Equals(newValue))
            {
                field = newValue;
                //PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs(propName), null, null);
                RaisePropertyChanged(propName);
            }
        }

        public virtual void RaisePropertyChanged(string propName = "")
        {
            //PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs(propName), null, null);

            //Task.Run(() =>
            //{
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
            //});
        }
        #endregion

        public override string ToString()
        {
            return GetDisplayText();
        }

        public abstract string GetDisplayText();

        #region IComparable
        public virtual int CompareTo(ElementBase other)
        {
            //throw new NotImplementedException();
            return Index - other.Index;
        }
        #endregion

        #region IDisposable Support
        private bool disposedValue = false; // 要检测冗余调用

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // 释放托管状态(托管对象)。
                    Pen?.Dispose();
                }

                // TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
                // TODO: 将大型字段设置为 null。

                disposedValue = true;
            }
        }

        // TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
        // ~ElementBase()
        // {
        //   // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
        //   Dispose(false);
        // }

        // 添加此代码以正确实现可处置模式。
        public void Dispose()
        {
            // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
            Dispose(true);
            // TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
            // GC.SuppressFinalize(this);
        }
        #endregion
    }

    [Serializable]
    public abstract class DisplayElementBase : ElementBase
    {
        //public override object Clone()
        //{
        //    throw new NotImplementedException();
        //}

        //public override void Draw(Graphics g)
        //{
        //    throw new NotImplementedException();
        //}

        //public override string GetDisplayText()
        //{
        //    throw new NotImplementedException();
        //}

        //public override bool IsIntersect(Rectangle rect)
        //{
        //    throw new NotImplementedException();
        //}

        public override bool IsMouseHover(PointF p)
        {
            return false;
        }

        //public override bool IsMouseInSide(Point p)
        //{
        //    throw new NotImplementedException();
        //}

        public override void OnKeyDown(object sender, KeyEventArgs e)
        {
        }

        public override void OnKeyUp(object sender, KeyEventArgs e)
        {
        }

        public override void OnMouseDownWhenNew(PointF p)
        {
        }

        public override void OnMouseMoveWhenNew(PointF p)
        {
        }

        public override void OnMouseUpWhenNew(PointF p)
        {
        }

        public override void Translate(float x, float y)
        {
        }

        protected override void DrawResult(Graphics g)
        {
        }
    }

    public interface IEventHandle
    {
        void OnMouseMove(PointF p);

        void OnMouseDown(PointF p);

        void OnMouseUp(PointF p);

        void OnMouseDoubleClick(PointF p);

        void OnKeyDown(object sender, KeyEventArgs e);

        void OnKeyUp(object sender, KeyEventArgs e);
    }

    public class ElementIndexCompare : IComparer<ElementBase>
    {
        public int Compare(ElementBase x, ElementBase y)
        {
            return x.Index - y.Index;
        }
    }
}