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

namespace TrendCtrlII
{
    public enum EDRAGTYPE
    {
        SCREEN,
        ZOOM,
        UC
    }

    public enum EBUTTONTYPE
    {
        LEFTMON,
        RIGHTMON
    }

    public enum EALIGN
    {
        LEFT,
        CENTER,
        RIGHT
    }

    public partial class TrendCtrlII : UserControl
    {
        private ChartStyle _Style = new ChartStyle();
        public CMouseinfo Mouseinfo;    //마우스위치정보

        public string yymm;
        private Int64 starttime;
        private Int64 endtime;
      
        //zoom area
        private Int64 startview;  //zoom 시작시간
        private Int64 endview;    //zoom 종료시간        
        public Int64 startviewo;  //zoom 시작시간
        public Int64 endviewo;    //zoom 종료시간
        public Int64 querystart;
        public Int64 queryend;

        public Single LineWidth = 1;
        private Rectangle UserZoom;     //사용자줌영역

        //실값
        public Single[] values;
        public int[] times;
        private CChinfo[] chinfo;

        private Rectangle Cursorrect;

        //화면상의 버튼데이터
        //private List<RectangleF> Buttons = new List<RectangleF>(0);
        //private List<Object> Buttonstag = new List<Object>(0);
        //private List<EBUTTONTYPE> Buttonstype = new List<EBUTTONTYPE>(0);

        private Boolean init;    //그리드초기화완료여부
        public String initmsg = "initializing...";
        public int initpercent = 0;

        public List<CUserCursor> uc = new List<CUserCursor>(0); //사용자커서 최대2개까지한다.
                
        //미정리
                
        //MY EVENT
        //public event OnClickProbeSensorHandlerL OnClickLEFT; //셀클릭
        //public delegate void OnClickProbeSensorHandlerL();       
        //public event OnClickProbeSensorHandlerR OnClickRIGHT; //셀클릭
        //public delegate void OnClickProbeSensorHandlerR();
        public event OnUpdateUserControlHandler OnUpdateUserCursor; //UPDATE USER CURSOR
        public delegate void OnUpdateUserControlHandler(int idx);       


        //화면디자인관련      
        private Cursor cursor = Cursors.Default;    //현재커서의모양

        private StringBuilder Warn_msg = new StringBuilder("");   //경고메세지(화면 최상단중앙에 표시됨)
        private Font Warn_Font;
        
        //기타설정'
        public RectangleF WindowRect;  //머릿부분
        public RectangleF ChartRect;


        public TrendCtrlII()
        {
            InitializeComponent();

            // Initialize Variables

            // Set Optimized Double Buffer to reduce flickering
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

            // Redraw when resized
            this.SetStyle(ControlStyles.ResizeRedraw, true);

            this.Font = SystemInformation.MenuFont;
            this.Warn_Font = new Font("나눔고딕", 20, FontStyle.Bold);
            this.Warn_msg.Append("메세지가 없습니다");
            this.Mouseinfo = new CMouseinfo(new PointF(0, 0));
                      
        }

        public ChartStyle Style
        {
            get { return this._Style; }
            set { this._Style = value; }
        }

        /// <summary>
        /// Draws the background gradient and the grid into Graphics <paramref name="g"/>
        /// </summary>
        /// <param name="g">Graphic</param>
        public void DrawBackgroundWindow(Graphics g,RectangleF crect,RectangleF winrect)
        {
            //using (Brush gradientBrush = new LinearGradientBrush(this.WindowRect, Style.design_backcolor_start, Style.design_backcolor_bottom, LinearGradientMode.Vertical))
            //{
            //    g.FillRectangle(gradientBrush, this.WindowRect);
            //}
            //g.FillRectangle(Brushes.Black, this.WindowRect);

            //전체창에대한 보더
            RectangleF borderrect = new RectangleF(winrect.Left, winrect.Top, winrect.Width - 1, winrect.Height - 1);
            g.DrawRectangle(Pens.Gray, borderrect.Left, borderrect.Top, borderrect.Width, borderrect.Height);
                   

            //실제차트정보
           //g.FillRectangle(Brushes.Gray, ChartRect.Left + 2, ChartRect.Top + 2, ChartRect.Width, ChartRect.Height);
           //g.FillRectangle(Brushes.Black, ChartRect);


            //Display Collection TIME
            //String Str = "Collection Time : " + GetDateTimeStr(startview, false) + " - " + GetDateTimeStr(endview, false);
            //SizeF fontszie = g.MeasureString(Str, this.Font);
           //// Rectangle rect = new Rectangle((int)winrect.Left, (int)winrect.Top, (int)winrect.Width, (int)(fontszie.Height * 2));
        //    g.DrawString(Str, this.Font, Brushes.Black, rect.Left + 10, 3+rect.Top + (rect.Height - fontszie.Height) / 2);
           // //g.DrawLine(Pens.Black, winrect.Left, fontszie.Height * 2, winrect.Left + winrect.Width, fontszie.Height * 2);
            
            //CHART BORDER
            g.DrawRectangle(new Pen(Color.Black, 2), crect.Left, crect.Top, crect.Width, crect.Height);
            
        }

        /// Override OnPaint method
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            this.SuspendLayout();
            
            //Buttons.Clear();
            //Buttonstag.Clear();
            //Buttonstype.Clear();
            //윈도우크기와 차트영역을 활성화한다.
                                             
            //표시아이템이없다면 오류를 낸다.
            if ( !init || chinfo == null)
            {
                //progress
                int bw = (int)(this.Width * 0.8);
                int bh = (int)(this.Height * 0.05);
                Rectangle rr = new Rectangle((this.Width - bw) / 2, (this.Height - bh) / 2 + 10, bw, bh);

                //Display Initial Message
                Font nf = new Font("나눔고딕", 20, FontStyle.Bold);
                Rectangle FullRect = new Rectangle(0, 0, this.Width, this.Height);
                SizeF initsize = e.Graphics.MeasureString(initmsg, nf);
                e.Graphics.DrawString(initmsg, nf, Brushes.Black, this.Width / 2 - initsize.Width / 2, this.Height / 2 - initsize.Height / 2 - bh);
                
                //Display progress Bar
                if (initpercent > 100) initpercent = 100;
                int perc = (int)(rr.Width * initpercent / 100);
                e.Graphics.FillRectangle(Brushes.Green, new Rectangle(rr.Left, rr.Top, perc, rr.Height));
                
                //Display Control Border
                e.Graphics.DrawRectangle(Pens.DarkGray, rr);

                //using (Brush gradientBrush = new LinearGradientBrush(FullRect, Color.Gray, Color.Gray, LinearGradientMode.Vertical))
                //{
                //    
                //    e.Graphics.FillRectangle(gradientBrush, FullRect);
                //    // String initstr = "initializing...";
                //    //if (initmsg != "") initstr += "\n\n" + initmsg;    
                //}

                //LinearGradientBrush lb = new LinearGradientBrush(rr, Color.Gray, Color.WhiteSmoke,LinearGradientMode.Vertical);
                //lb.Dispose();                
                //e.Graphics.DrawRectangle(Pens.DarkGoldenrod, FullRect.Left, FullRect.Top, FullRect.Width - 1, FullRect.Height - 1);

                this.ResumeLayout();                
                return;
            }

          
            // AntiAliasing
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

            //e.Graphics.DrawString(this.chinfo.Length.ToString(), this.Font, Brushes.Red, 200, 200);

            try { DrawBackgroundWindow(e.Graphics, ChartRect, WindowRect); }   //전체배경및 차트배경 }
            catch { }


            try
            {
                Draw_Grid(e.Graphics, ChartRect);  //x축,y축의 눈금과 그리드표시
            }
            catch { }
            //Draw_NaviLR(e.Graphics, ChartRect);
            try
            {
                Draw_channel(e.Graphics, ChartRect, WindowRect);
            }
            catch { }
            try
            {
                Draw_ZoomSelct(e.Graphics);
            }
            catch { }
            try
            {
                Draw_Cursor(e.Graphics, ChartRect);
            }
            catch { }
            try
            {
                Draw_MouseInfo(e.Graphics);
            }
            catch
            {
                Draw_Debug(e.Graphics);
            }

            this.Update();
            this.ResumeLayout();
        }

        public void Draw_Cursor(Graphics g,RectangleF Crect )
        {
            
            if (this.uc.Count == 0) return;
            Font cfont = new Font("나눔고딕", 10, FontStyle.Bold);

            //커서는 기본 2개를 둔다(전체사이즈를 측정하기위해서 임시로 크기를 테스트한다.)
            String cursorstr = "▦ C1 2012-00-00- 00:00:00\n▦ C1 2012-00-00- 00:00:00\n▦ C1 2012-00-00- 00:00:00";
            SizeF FontSize = g.MeasureString(cursorstr.ToString(), cfont);

            //커서가표시될영역

            Cursorrect = new Rectangle(0, 0, 50,50);
            Cursorrect.X = (int)(Crect.Left + Crect.Width - FontSize.Width * 1.1) - 1;
            Cursorrect.Y = (int)Crect.Top + 2;
            Cursorrect.Width = (int)(FontSize.Width * 1.1);
            Cursorrect.Height = (int)(FontSize.Height * 1.3);

            g.FillRectangle(Brushes.Black, Cursorrect);
            g.DrawRectangle(Pens.Gray, Cursorrect);

            Single newy = Cursorrect.Top + ((Cursorrect.Height - FontSize.Height)/2) ;
            Single Maxwidth = 0;
                      
            String fulltext = "";
            foreach (CUserCursor uctl in this.uc)
            {
                Single newx = GetXfromTime(uctl.Time, Crect);
                uctl.Newx = newx;
             
                Single imgsizew = Properties.Resources.down_16.Width;
                Single imgsizeh = Properties.Resources.down_16.Height;

                cursorstr = ("▦ C" + (uctl.Idx + 1).ToString() + " " + GetTimeStr((int)uctl.Time, true, true, true, true));
                
               // cursorstr += uctl.Newx.ToString();

                FontSize = g.MeasureString(cursorstr.ToString(), cfont);
                if (FontSize.Width > Maxwidth) Maxwidth = FontSize.Width;

                if (uctl.Idx < 1)
                {
                    g.DrawImage(Properties.Resources.down_16, (newx - imgsizew / 2)-1, Crect.Top - imgsizeh - 5);
                    //g.DrawLine(new Pen(Color.Gray, 2), newx+1, Crect.Top, newx+1, Crect.Top + Crect.Height);
                    g.DrawLine(new Pen(Color.Green, 1), newx, Crect.Top, newx, Crect.Top + Crect.Height);
                  //  g.DrawString(newx.ToString() + "," + uctl.Time.ToString(), this.Font, Brushes.Red, newx, 300);
                    g.DrawString(cursorstr, cfont, Brushes.Lime, Cursorrect.Left + ((Cursorrect.Width - FontSize.Width) / 2), newy);
                    fulltext = cursorstr;
                 
                }
                else
                {
                    cursorstr += "\n\t△t " + GetTimeStr((int)Math.Abs(uctl.Time - uc[0].Time), false, true, true, false);

                    g.DrawImage(Properties.Resources.down_orange, (newx - imgsizew / 2) - 1, Crect.Top - imgsizeh - 5);
                    //g.DrawLine(new Pen(Color.Gray, 2), newx + 1, Crect.Top, newx + 1, Crect.Top + Crect.Height);
                    g.DrawLine(new Pen(Color.Orange, 1), newx, Crect.Top, newx, Crect.Top + Crect.Height);
                 //   g.DrawString(newx.ToString() + "," + uctl.Time.ToString(), this.Font, Brushes.Red, newx, 300);
                    g.DrawString(cursorstr, cfont, Brushes.Orange, Cursorrect.Left + ((Cursorrect.Width - FontSize.Width) / 2), newy); 
                    if (fulltext == "") fulltext = cursorstr;
                    else fulltext += "\n" + cursorstr; 
                        
                }
                newy += FontSize.Height + 1;
            }

            FontSize = g.MeasureString(fulltext, cfont);
            Cursorrect = new Rectangle((int)(ChartRect.Left + ChartRect.Width - Maxwidth), (int)ChartRect.Top, (int)Maxwidth, (int)(newy - FontSize.Height));
        }

        public void Draw_MouseInfo(Graphics g)
        {
            if (this.Mouseinfo.Showinfo)    //마웃위치정보를 화면에 표시를 한다.
            {
                String tm = GetTimeStr((int)Mouseinfo.Time, true, true,true,true) + "\n" + Mouseinfo.Volt.ToString("#0.00") + "v";
                if (Style.디버그메세지) tm += "\n" + Mouseinfo.Time.ToString();
                
                SizeF tmsize = g.MeasureString(tm,Style._mouseinfofont);

                RectangleF rect = new RectangleF(Mouseinfo.Position.X + 5, Mouseinfo.Position.Y + 5, tmsize.Width+10, tmsize.Height+10);
                //g.FillRectangle(new SolidBrush(Color.FromArgb(140,Color.Green)), rect);
                g.DrawRectangle(Pens.Black, rect.Left, rect.Top, rect.Width, rect.Height);
                
                g.DrawString(tm, Style._mouseinfofont, new SolidBrush(Style.design_mouseinfocolor  ), rect.Left + (rect.Width - tmsize.Width) / 2, rect.Top + (rect.Height - tmsize.Height) / 2);
            }
        }

        public void Draw_Grid(Graphics g,RectangleF crect)
        {
           
            //가로(시간축)표시
            //DrawString(g, GetDateTimeStr(endview, true), Style._xfont, Brushes.Black, new PointF(crect.Left + crect.Width, crect.Top + crect.Height + 5), EALIGN.CENTER);
            DateTime SDate = DateTime.FromFileTime(startview);
            DateTime EDate = DateTime.FromFileTime(endview);
            TimeSpan TS = EDate - SDate;    //timespan

            //표시간견(10등분)
            UInt32 tm =  (UInt32)(TS.TotalSeconds / 10);
            for (DateTime SD = SDate; SD <= EDate; SD.AddSeconds(tm) )
            {

            }

                for (Int64 i = 0; i <= (endview - startview); i += tm)
                {
                    Int64 NewDateNumber = startview + i;
                    DateTime NewDate = DateTime.FromFileTime(NewDateNumber);
                    if (SDate.Day != NewDate.Day)
                    {
                        //일자가 바귀엇으므로 해당 일즤 세로축을 표시
                        DateTime LineDay = DateTime.Parse(NewDate.ToString("yyyy-MM-dd 00:00:00"));
                        Single newx2 = GetXfromTime(LineDay.ToFileTime(), crect);
                        g.DrawLine(new Pen(Color.FromArgb(50, Color.Black)), newx2, crect.Top, newx2, crect.Top + crect.Height);
                        //Font newf = new Font("나눔고딕", 40, FontStyle.Bold);
                        //DrawString(g, timestr2, newf, Brushes.Black, new PointF(newx2, ChartRect.Top + ChartRect.Height - 100), EALIGN.CENTER);
                        SDate = NewDate;
                    }

                    Single newx = GetXfromTime(NewDateNumber, crect);
                    String timestr = "";

                    if (i == 0) timestr = GetDateTimeStr(NewDateNumber, true);
                    else timestr = GetTimeStr(NewDateNumber, i == 0 ? true : false, false);

                    timestr = NewDate.ToString("yy-MM-dd") + "\n" + NewDate.ToString("HH:mm:ss");

                    // timestr += "\n" + disptime.ToString();

                    DrawString(g, timestr, Style._xfont, Brushes.Black, new PointF(newx, crect.Top + crect.Height + 5), EALIGN.CENTER);

                    if (i > 0) g.DrawLine(new Pen(Color.Gray), newx, crect.Top, newx, crect.Top + crect.Height);
                }
            
                        
            //세로(VOLT)표시
            //g.DrawString("start="+Style._startvolt.ToString(), this.Font, Brushes.Red, 100, 100);
            //g.DrawString("end="+Style._endvolt.ToString(), this.Font, Brushes.Red, 100, 120);

            //g.DrawString("최소="+Style.최소값.ToString(), this.Font, Brushes.Red, 100, 140); 
            //g.DrawString("최대="+Style.최대값.ToString(), this.Font, Brushes.Red, 100, 160);

           Single term = (Style._endvolt - Style._startvolt) / 10;

           for (Single i = Style._startvolt; i <= Style._endvolt; i += term)
            {
                // 세로길이 = 10v : 
                Single newy = GetYfromVolt(i, crect);
                if (i != 0) g.DrawLine(new Pen(Color.Gray), crect.Left, newy, crect.Left + crect.Width, newy);

                //소수점없는경우에눈금표시한다.
                DrawString(g, i.ToString("#0.00"), Style._yfont, Brushes.Black, new PointF(crect.Left - 2, newy), EALIGN.RIGHT, EALIGN.CENTER);
                

                
                //int disptime = i + startview;
                //String timestr = GetTimeStr(disptime, i == 0 ? true : false);

                //DrawString(g, timestr, Style._xfont, Brushes.Orange, new PointF(newx, ChartRect.Top + ChartRect.Height), EALIGN.CENTER);

                //if (i > 0) g.DrawLine(new Pen(Color.FromArgb(100, Color.Red)), newx, ChartRect.Top, newx, ChartRect.Top + ChartRect.Height);
            }

        }

        public void Draw_Debug(Graphics g)
        {
            if (!Style.디버그메세지) return;

            Single newy = 50;
            String newstr = "";
            SizeF fontsize;

            newstr = "Mouseinfo=" + this.Mouseinfo.Position.ToString() + " " + this.Mouseinfo.Showinfo.ToString() ;
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);

            newstr = "Mouseinfo0=" + this.Mouseinfo.Position0.ToString()+ " idx=" + this.Mouseinfo.DragIndex.ToString();
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);

            if (uc.Count > 0)
            {
                newstr = "uc1=" + uc[0].Newx.ToString() + "," + uc[0].Time.ToString();
                fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
                g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);
            }

            if (uc.Count > 1)
            {
                newstr = "uc2=" + uc[1].Newx.ToString() + "," + uc[1].Time.ToString();
                fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
                g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);
            }
            
            newstr = "Time=" + starttime.ToString() + "/" + endtime.ToString();
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);

            newstr = "ViewTime=" + startview.ToString() + "/" + endview.ToString();
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);

            newstr = "ViewTimeO=" + startviewo.ToString() + "/" + endviewo.ToString();
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);
            
            newstr = "Drag=" + Mouseinfo.Drag.ToString() + " " + Mouseinfo.DragType.ToString();
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);

            newstr = "DragStart=" + Mouseinfo.DragStart.ToString();
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);

            newstr = "UserZoom=" + UserZoom.ToString();
            fontsize = g.MeasureString(newstr, this.Font); newy += fontsize.Height;
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);
            newy += fontsize.Height;

            newstr = "CHinfo=" + chinfo.GetUpperBound(0);
            for (int i =0;i<= chinfo.GetUpperBound(0);i++)            
            {
                newstr += "\n" + i.ToString()  + "," + this.chinfo[i].idx + ",visible:" + chinfo[i].Show.ToString();
            }
            fontsize = g.MeasureString(newstr, this.Font); 
            g.DrawString(newstr, this.Font, Brushes.Red, 100, newy);
            newy += fontsize.Height;
        }
        
        public void Draw_channel(Graphics g,RectangleF crect,RectangleF wrect)
        {

            //각채널의 그래프를 그린다.
            foreach (CChinfo c in chinfo)
            {
                if (c == null) continue;
                if (!c.Show) continue;
                if (c.Value.Count < 1) continue;
                
                List<PointF> linearrya = new List<PointF>(0);

                Single PreX = 0;
                Single PreY = 0;

                Boolean fc1 = false, fc2 = false;
                for (int i = 0; i < c.Value.Count; i++) //가능한 셀값을 모두 확인한다.
                {
                    Single time = c.Time[i];    //이셀의 시간
                    Single volt = c.Value[i];   //이셀의 볼트

                    //if (volt == 0) continue;

                    Single newx = GetXfromTime(time, crect) - 1;
                    Single newy = GetYfromVolt(volt, crect) - 1;

                    //너무가까운데이터는 그리지 않는다.
                    if (Math.Abs(newx - PreX) < 0.2 || Math.Abs(newy - PreY) < 0.2) continue;

                    if (!c.Show)
                    {
                        c.C1value = "--";
                        c.C2value = "--";
                    } else if (uc.Count > 0 &&  time >= uc[0].Time && fc1 == false)    //셀의시간이 커서의시간을 넘는 순간의 값을 저장
                    {

                        //g.DrawString(uc[0].Time.ToString() + "," + time.ToString() + " volt=" + volt.ToString(), this.Font, Brushes.Red, 200, 200);

                        if (volt > 60) c.C1value = "OVER";
                        else c.C1value = volt.ToString();

                        fc1 = true;
                    }
                    if (uc.Count > 1 &&  time >= uc[1].Time && fc2 == false)
                    {
                        //g.DrawString(uc[1].Time.ToString() + "," + time.ToString() + " volt=" + volt.ToString(), this.Font, Brushes.Red, 200, 300);

                        if (volt > 60) c.C2value = "OVER";
                        else c.C2value =  volt.ToString();
                        
                        fc2 = true;
                    }
                 
                    // e.Graphics.DrawString(time.ToString() + " v=" + volt.ToString(), this.Font, Brushes.Black, newx, newy);
                    if (newx >= wrect.Left && newx <= wrect.Left + wrect.Width && newy >= wrect.Top && newy <= wrect.Top + wrect.Height) 
                        linearrya.Add(new PointF(newx, newy));

                    g.FillEllipse(new SolidBrush(c.color),  new RectangleF(newx-1, newy-1, 2, 2));
                }

                try {
                    g.DrawLines(new Pen(c.color, LineWidth), linearrya.ToArray()); 
                }
                catch { }
            }
        }

        public void Draw_ZoomSelct(Graphics g)
        {
            //사용자줌영역표시
            if (this.UserZoom.Width != 0)
            {
                int x, y, w, h;
                if (UserZoom.Width > 0)
                {
                    x = UserZoom.Left;
                    w = UserZoom.Width;
                }
                else
                {
                    x = UserZoom.Width + UserZoom.Left;
                    w = Math.Abs(UserZoom.Width);
                }
                if (UserZoom.Height > 0)
                {
                    y = UserZoom.Top;
                    h = UserZoom.Height;
                }
                else
                {
                    y = UserZoom.Height + UserZoom.Top;
                    h = Math.Abs(UserZoom.Height);
                }

                Rectangle rect = new Rectangle(x, y, w, h);
                int startx = (int)Math.Round(GetTimeFromX(rect.Left - this.ChartRect.Left, ChartRect), 1);
                int endx = (int)Math.Round(GetTimeFromX(rect.Left + rect.Width - ChartRect.Left, ChartRect), 1);
                Single starty =(Single)(Math.Round(GetVoltfromY(rect.Top - this.ChartRect.Top, ChartRect), 1));
                Single endy = (Single)Math.Round(GetVoltfromY(rect.Top + rect.Height - ChartRect.Top, ChartRect), 1);

                //선택된 영역 Drawing
                if (endx - startx >= 5) g.FillRectangle(new SolidBrush(Color.FromArgb(150, Color.Lime)), rect);
                else g.FillRectangle(new SolidBrush(Color.FromArgb(150, Color.Red)), rect);

                g.DrawRectangle(Pens.Black, rect);

                //시간정보 Display
                g.DrawString(GetTimeStr(startx + starttime, true,true) + "," + (Style.최대값 - starty).ToString("#0.0") + "v" , this.Font, Brushes.Black, rect.Left, rect.Top);

                String fontstr = GetTimeStr(endx + starttime, true, true) + "," + (Style.최대값 - endy).ToString("#0.0") + "v";
                SizeF fontsize = g.MeasureString(fontstr, this.Font);
                g.DrawString(fontstr, this.Font, Brushes.Black, rect.Left - 5 + rect.Width - fontsize.Width, rect.Top + rect.Height - fontsize.Height);
            }
        }

        /// <summary>
        /// 화면의 좌,우 측에 존재하는 이돈버튼(월을 움직이는 버튼이며 월 이동을위해서 이벤트를 발생한다)
        /// </summary>
        /// <param name="G"></param>
        //public void Draw_NaviLR(Graphics G, RectangleF crect)
        //{
        //    return;

        //    //LEFT NAVI
        //    Single x, y, xw = 30;
        //    x = crect.Left - 3;
        //    y = crect.Top + crect.Height / 2 - xw / 2;

        //    PointF[] aa = new PointF[4];
        //    aa[0] = new PointF(x, y);
        //    aa[1] = new PointF(x - xw, y + xw);
        //    aa[2] = new PointF(x, y + xw + xw);
        //    aa[3] = new PointF(x, y);

        //    PointF[] aa1 = new PointF[4];
        //    aa1[0] = new PointF(x + 2, y + 2);
        //    aa1[1] = new PointF(x + 2 - xw, y + xw + 2);
        //    aa1[2] = new PointF(x + 2, y + xw + xw + 2);
        //    aa1[3] = new PointF(x + 2, y + 2);
        //    G.FillPolygon(Brushes.Black, aa1);
        //    G.FillPolygon(Brushes.DarkRed, aa);
        //    G.DrawPolygon(Pens.Black, aa);

        //    Buttons.Add(new RectangleF(x - xw, y, xw, xw*2));
        //    Buttonstag.Add("LBUTTON");
        //    Buttonstype.Add(EBUTTONTYPE.LEFTMON);

        //    //RIGHT NAVI
        //    x = crect.Left + crect.Width + 3;
        //    y = crect.Top + crect.Height / 2 - xw / 2;

        //    aa = new PointF[4];
        //    aa[0] = new PointF(x, y);
        //    aa[1] = new PointF(x + xw, y + xw);
        //    aa[2] = new PointF(x, y + xw + xw);
        //    aa[3] = new PointF(x, y);

        //    aa1 = new PointF[4];
        //    aa1[0] = new PointF(x + 2, y + 2);
        //    aa1[1] = new PointF(x + 2 + xw, y + xw + 2);
        //    aa1[2] = new PointF(x + 2, y + xw + xw + 2);
        //    aa1[3] = new PointF(x + 2, y + 2);
        //    G.FillPolygon(Brushes.Black, aa1);
        //    G.FillPolygon(Brushes.DarkRed, aa);
        //    G.DrawPolygon(Pens.Black, aa);
        //    Buttons.Add(new RectangleF(x, y, xw, xw*2));
        //    Buttonstag.Add("RBUTTON");
        //    Buttonstype.Add(EBUTTONTYPE.RIGHTMON);
        //}


        public String GetDateTimeStr(Int64 Filetime, Boolean linefeed)
        {
            DateTime TimeDate = DateTime.FromFileTime(Filetime);
            String timestr = "";
            if (linefeed) timestr = TimeDate.ToShortDateString() + "\n" + TimeDate.ToShortTimeString();  //' yymm + "-" + day.ToString("00") + "\n" + hour.ToString("00") + ":" + min.ToString("00") + ":" + sec.ToString("00");
            else timestr = TimeDate.ToString();// yymm + "-" + day.ToString("00") + " " + hour.ToString("00") + ":" + min.ToString("00") + ":" + sec.ToString("00");
                      
            return timestr;
        }
        public String GetTimeStr(Int64 Filetime, Boolean withday, Boolean withseconed, Boolean nolf = false, Boolean showyear = false)
        {
            DateTime TimeDate = DateTime.FromFileTime(Filetime);
            String timestr = "";

            if (TimeDate.Second == 0 || !withseconed)
                timestr = TimeDate.ToString("HH:mm");//  TimeDate.Hour.ToString("00") + ":" +  TimeDate.Minute.ToString("00");
            else
                timestr = TimeDate.ToString("HH:mm:ss"); // hour.ToString("00") + ":" + min.ToString("00") + ":" + sec.ToString("00");

            if (withday)
            {
                if (showyear)
                {
                    timestr = TimeDate.ToString("yyMM-dd") + " " +  timestr;
                }
                else
                {
                    if (nolf) timestr = TimeDate.ToString("dd") + "일 " + timestr;
                    else timestr = timestr + "\n" + TimeDate.ToString("dd") + "일";
                }               
            } 
            return timestr;
        }

        /// <summary>
        /// (전체시간 * 현재X) / 전체너비
        /// </summary>
        /// <param name="t"></param>
        /// <returns></returns>
        private Single GetTimeFromX(Single t, RectangleF crect)
        {
            return ((endview - startview) * t) / crect.Width;
        }
        private Single GetXfromTime(Single t,RectangleF crect)
        {
            return (((crect.Width) * (t - startview)) / (endview - startview)) + crect.Left;
        }
        private Single GetVoltfromY(Single Y, RectangleF crect)
        {

            return ((Style._endvolt - Style._startvolt) * Y) / crect.Height;

        }
        private Single GetYfromVolt(Single volt, RectangleF crect)
        {
            //volt = (Style._endvolt - Style._startvolt) - volt;
            return (crect.Height - ((crect.Height * (volt - Style._startvolt)) / (Style._endvolt - Style._startvolt))) + crect.Top;
            //return (((crect.Height) * volt) / (Style.최대값)) + crect.Top;
            
        }

        private void DrawString(Graphics G, String str, Font font, Brush br, PointF ops, EALIGN XCenter = EALIGN.LEFT, EALIGN YCenter = EALIGN.LEFT)
        {
            SizeF fsize = G.MeasureString(str, font);
            Single newx = ops.X;            
            Single newy = ops.Y;

            if (XCenter == EALIGN.CENTER) newx = ops.X - fsize.Width / 2;
            else if (XCenter == EALIGN.RIGHT) newx = ops.X - fsize.Width;

            if (YCenter == EALIGN.CENTER) newy = ops.Y - fsize.Height / 2;
            else if (YCenter == EALIGN.RIGHT) newy = ops.Y - fsize.Height;

            G.DrawString(str, font, br, newx, newy);
        }

        public Int64 Starttime
        {
            get { return this.starttime; }
            set { this.starttime = value; startview = value; }
        }

        public Int64 Endtime
        {
            get { return this.endtime; }
            set { this.endtime = value; endview = value; }
        }

        public Int64 Startview
        {
            get { return this.startview; }
            set { this.startview = value; }
        }

        public Int64 Endview
        {
            get { return this.endview; }
            set { this.endview = value; }
        }

        public Boolean INIT
        {
            get { return this.init; }
            set { this.init = value; }
        }
        public CChinfo[] CHInfo
        {
            get { return this.chinfo; }
            set { this.chinfo = value; }
        }
        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);            
            this.WindowRect = new RectangleF(0, 0, this.Width, this.Height);
            this.ChartRect = new RectangleF(Style.왼쪽여백, (Style.위쪽여백/2), this.Width - (Style.왼쪽여백 * 2), (Single)(this.Height - (Style.위쪽여백 * 1.5)));
            Invalidate();
        }

        private int check_userpoint(MouseEventArgs e)
        {
            if (this.uc.Count ==0 ) return -1;
            for (int i = 0; i < this.uc.Count; i++)
            {
                CUserCursor uuc = this.uc[i];

                //현재위치가 해당 Rectagle 안이라면 속해있다.                    
                if ((int)this.Mouseinfo.Position.X >= (int)uuc.Newx - 2 && (int)this.Mouseinfo.Position.X <= (int)(uuc.Newx) + 2)

                 //   MessageBox.Show(i.ToString());

                    return i;
            }
            return -1;
        }

        //private int check_buttons(MouseEventArgs e)
        //{
        //    if (this.Buttons == null) return -1;
        //    for (int i = 0; i < this.Buttons.Count; i++)
        //    {
        //        RectangleF rect = this.Buttons[i];

        //        //현재위치가 해당 Rectagle 안이라면 속해있다.                    
        //        if (e.X > rect.X && e.X < rect.X + rect.Width)
        //        {
        //            if (e.Y > rect.Y && e.Y < rect.Y + rect.Height) return i;
        //        }
        //    }
        //    return -1;
        //}
            
        private void InitializeComponent()
        {
            this.SuspendLayout();
            // 
            // TrendCtrl
            // 
            this.Name = "TrendCtrl";
            this.Size = new System.Drawing.Size(287, 321);
            this.Load += new System.EventHandler(this.DispCtrl_Load);
            this.MouseDoubleClick += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseDoubleClick);
            this.MouseDown += new System.Windows.Forms.MouseEventHandler(this.DispCtrl_MouseDown);
            this.MouseMove += new System.Windows.Forms.MouseEventHandler(this.DispCtrl_MouseMove);
            this.MouseUp += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseUp);
            this.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.TrendCtrl_MouseWhell);
            this.ResumeLayout(false);

        }

    private void DispCtrl_MouseDown(object sender, MouseEventArgs e)
    {

        //드래그판단을위한 위치값을 저장한다.
        Mouseinfo.DragStart = new PointF(e.X - ChartRect.Left, e.Y - ChartRect.Top);

        //우측버튼은 줌의 초기화를 수행한다.
        if (e.Button == System.Windows.Forms.MouseButtons.Right)
        {
            //startview = starttime;
            //endview = endtime;
            //Style._startvolt = Style.최소값;
            //Style._endvolt = Style.최대값;
            //Refresh();
            //return;
        }
        else if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            //현재마우스위치의 아이템을 찾ㄴ은다.
            //int idx = check_buttons(e);
            //if (idx != -1)
            //{
            //    Object tt = this.Buttonstag[idx];
            //    EBUTTONTYPE BT = this.Buttonstype[idx];

            //    switch (BT)
            //    {
            //        case EBUTTONTYPE.LEFTMON:
            //            OnClickLEFT();
            //            break;
            //        case EBUTTONTYPE.RIGHTMON:
            //            OnClickRIGHT();
            //            break;
            //    }
            //}

            int idx = check_userpoint(e);
            if (idx != -1)
            {
                Mouseinfo.DragType = EDRAGTYPE.UC;
                Mouseinfo.DragIndex = idx;
                return;
            }

            //아무것도없는 빈공간이라면 화면이동(=줌시작)으로 대체한다.
            //if (idx == -1 && e.X >= ChartRect.Left && e.X <= ChartRect.Left + ChartRect.Width && e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height)
            //{
            //    if (endview - startview == (endtime - starttime))
            //    {
            //        Mouseinfo.DragType = EDRAGTYPE.ZOOM;                    
            //        this.UserZoom = new Rectangle(e.X, e.Y, 0, 0);
            //    }
            //    else
            //    {
            //         Mouseinfo.DragType = EDRAGTYPE.SCREEN;
            //         this.UserZoom = new Rectangle(0, 0, 0, 0);
            //    }
            //    return;
            //}


        }
    }

    private void DispCtrl_MouseMove(object sender, MouseEventArgs e)
    {
        //마우스의 위치가 실시간 저장된다.
        if (this.Mouseinfo == null) this.Mouseinfo = new CMouseinfo(new PointF(e.X - this.WindowRect.Left, e.Y - this.WindowRect.Top));
        else                        this.Mouseinfo.Position = new PointF(e.X - this.WindowRect.Left, e.Y - this.WindowRect.Top);
   
        this.Mouseinfo.Time = GetTimeFromX(e.X - ChartRect.Left,ChartRect)+ this.startview;
        this.Mouseinfo.Volt = this._Style._endvolt -  GetVoltfromY(e.Y - ChartRect.Top, ChartRect) ;
        this.Mouseinfo.Showinfo = false;
        
        //MouseStatus initialize...
        Mouseinfo.Hand = false;
        Mouseinfo.Cross = false;
        Mouseinfo.Move = false;
        Mouseinfo.ChangePos = false;

        //
        if (e.X >= ChartRect.X && e.X <= ChartRect.X + ChartRect.Width)
            if (e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height) Mouseinfo.Showinfo = true;
            else Mouseinfo.Showinfo = false;                                                     


        //이동중인데 마우스가 눌려있다면 DRAG다
        if (e.Button == MouseButtons.Left) Mouseinfo.Drag = true;
        else Mouseinfo.Drag = false;

        if (Mouseinfo.Drag) //드래그중이다
        {
           Mouseinfo.Move = true; //화면이동으로
        }
        else
        {
            if (e.X >= ChartRect.Left && e.X <= ChartRect.Left + ChartRect.Width)
            {
                if (e.Y >= ChartRect.Top && e.Y <= ChartRect.Top + ChartRect.Height)
                {
                    Mouseinfo.Cross = true; //화면내부라면 크로스
                }
                else Mouseinfo.Cross = false;
            }
            else Mouseinfo.Cross = false;
        }
                  
        //버튼위라면 HAND를 활성화한다.
        //int idx = this.check_buttons(e);
        //if (idx != -1)
        //{
        //    Mouseinfo.Cross = false;
        //    Mouseinfo.Hand = true;
        //    Mouseinfo.Drag = false;
        //    Mouseinfo.ChangePos = false;
        //} 

        //사용자포인터위라면?
        int idx = this.check_userpoint(e);
        if (idx != -1)
        {
            Mouseinfo.Cross = false;
            Mouseinfo.Hand = false;
            Mouseinfo.Drag = false;
            Mouseinfo.ChangePos = true;
        } 

        //드래그중판단
        if (Mouseinfo.Drag)
        {
            switch (Mouseinfo.DragType)
            {
                case EDRAGTYPE.UC:
                    Single newx = ( e.X);
                    float newtime = GetTimeFromX(newx - ChartRect.Left, ChartRect) + startview;
                    this.uc[Mouseinfo.DragIndex].Newx = newx;
                    this.uc[Mouseinfo.DragIndex].Time = newtime;
                    //OnUpdateUserCursor(Mouseinfo.DragIndex);
                    break;
                case EDRAGTYPE.ZOOM:
                    this.UserZoom.Width = (int)(e.X - Mouseinfo.DragStart.X - ChartRect.Left);
                    this.UserZoom.Height = (int)(e.Y - Mouseinfo.DragStart.Y - ChartRect.Left);
                    if (Mouseinfo.Cross) this.Cursor = Cursors.Cross;
                    break;
                case EDRAGTYPE.SCREEN:
                    if (Mouseinfo.Move)
                    {
                        this.Cursor = Cursors.NoMove2D;
                        Mouseinfo.Showinfo = false;
                    }


                    //이동한pixcel을 시간정보로 변환한다.
                    //현재마우스위치값 - 드래그시작마우스위치값을 뺸 픽셀을 초로환산한다.

                    Single term =  Mouseinfo.DragStart.X-Mouseinfo.Position.X; //양수라면 오른쪽으로 이동했다.
                    Single termtime = GetTimeFromX(term, ChartRect);

                    Single termy = Mouseinfo.Position.Y- Mouseinfo.DragStart.Y- ChartRect.Top  ;
                    Single termvolt = GetVoltfromY(termy, ChartRect);

                    Single mstime = termtime ; //((endview - startview) / 50);
                    Single mvolt = termvolt;
                    //if (Mouseinfo.Position.X < Mouseinfo.Position0.X)
                    //{
                    //    mstime = -1 * mstime;
                    //}
                    Int64 SD = startviewo +  (int)mstime;
                    Int64 ED = endviewo + (int)mstime;

                    Single SV = Style._startvolto + mvolt;
                    Single EV = Style._endvolto + mvolt;

                    if ((SD < starttime || ED > endtime))
                    {
                        //더이상 줌을 못한다..
                    }
                    else
                    {
                        startview = SD;
                        endview = ED;

                        Style._startvolt = SV;
                        Style._endvolt = EV;

                        //startviewo = startview;
                        //endviewo = endview;
                    }
                 
                    
                    break;
            }
        }
        else
        {
            if (Mouseinfo.Hand) this.Cursor = Cursors.Hand;
            if (Mouseinfo.Cross) this.Cursor = Cursors.Cross;
            if (Mouseinfo.ChangePos) this.Cursor = Cursors.SizeWE;
        }

        this.Refresh();
    }

    private void TrendCtrl_MouseWhell(object sender, MouseEventArgs e)
    {
        //MessageBox.Show(e.Delta.ToString());
        //int news = 0, newe = 0;

        //news = startview;
        //newe = endview;

        //if (e.Delta > 0)
        //{
        //    //up
        //    news += (endview-startview)/10;
        //    newe -= (endview - startview) / 10;
        //}
        //else
        //{
        //    //down
        //    news -= (endview - startview) / 10;
        //    newe += (endview - startview) / 10;
        //}

        //if (news > endtime) news = endtime;
        //if (news < starttime) news = starttime;
        //if (newe > endtime) newe = endtime;
        //if (newe < starttime) newe = starttime;

        //if (news < starttime || newe > endtime)
        //{
        //    //MessageBox.Show("데이터가 없으므로 줌을 사용할 수 없습니다");                
        //}
        //else
        //{
        //    startview = news; 
        //    endview = newe;
        //    startviewo = news;
        //    endviewo = newe;            
        //}
        //this.Refresh();
      
    }

    private void TrendCtrl_MouseUp(object sender, MouseEventArgs e)
    {
        if (Mouseinfo.Drag && Mouseinfo.DragType == EDRAGTYPE.UC)
        {
            ////만약 화면 박을 넘어서면 삭제한다.
            //if (uc[Mouseinfo.DragIndex].Newx <= ChartRect.Left || uc[Mouseinfo.DragIndex].Newx >= ChartRect.Left + ChartRect.Width)
            //{
            //    uc.Remove(uc[Mouseinfo.DragIndex]);
            //    if (uc.Count == 1)
            //    {
            //        uc[0].Idx = 0;
            //        foreach (CChinfo c in this.chinfo)
            //        {
            //            c.C2value = "";
            //        }
            //    }
            //}
            this.Refresh();
            OnUpdateUserCursor(Mouseinfo.DragIndex);
        }

        //startviewo = startview;
        //endviewo = endview;
        //Style._startvolto = Style._startvolt;
        //Style._endvolto = Style._endvolt;

        //Mouseinfo.Drag = false;
        //if (UserZoom.Width != 0) //줌영역이 있다면 줌을 활성화한다.
        //{
        //    int x1, x2,y1,y2;
        //    x1 = UserZoom.Left;
        //    x2 = UserZoom.Left + UserZoom.Width;
        //    y1 = UserZoom.Top;
        //    y2 = UserZoom.Top + UserZoom.Height;

        //    int startx = (int)Math.Round(GetTimeFromX(x1 - ChartRect.Left, ChartRect), 0);
        //    int endx = (int)Math.Round(GetTimeFromX(x2 - ChartRect.Left, ChartRect), 0);

        //    Single starty =(Single) Math.Round(GetVoltfromY(y1 - ChartRect.Top, ChartRect), 1);
        //    Single endy = (Single)Math.Round(GetVoltfromY(y2 - ChartRect.Top, ChartRect), 1);

        //    if (endx < startx)  //교환
        //    {
        //        int t = startx;
        //        startx = endx;
        //        endx = t;
        //    }

        //    //if (endy < starty)  //교환
        //    //{
        //    //    Single t = starty;
        //    //    starty = endy;
        //    //    endy = t;
        //    //}

        //    if (endx - startx >= 10) //보기영역이 5초는 넘어야 줌이 가능한다.
        //    {
        //        this.startview = startx + this.starttime ;
        //        this.endview = endx + this.starttime;

        //        this.startviewo = this.startview;
        //        this.endviewo = this.endview;


        //        if (starty < endy)
        //        {
        //            this.Style._endvolt = Style.최대값 - starty;// +this.Style.최소값;
        //            this.Style._startvolt = Style.최대값 - endy;// +this.Style.최대값;
        //        }
        //        else
        //        {
        //            this.Style._startvolt = Style.최대값 - starty;// +this.Style.최소값;
        //            this.Style._endvolt = Style.최대값 - endy;// +this.Style.최대값;
        //        }
                
        //        ////////////
        //        this.Style._startvolto = this.Style._startvolt;
        //        this.Style._endvolto = this.Style._endvolt;

        //        //////////////

        //        UserZoom.Width = 0;
        //        this.Refresh();
        //    }
        //    else
        //    {
        //        UserZoom.Width = 0;
        //        this.Refresh();
        //    }
        //}
    }

    private void TrendCtrl_MouseDoubleClick(object sender, MouseEventArgs e)
    {
        //마우스더블클릭
        int idx = check_userpoint(e);
        if (idx != -1)
        {
            //삭제한다.
            uc.Remove(uc[Mouseinfo.DragIndex]);
            if (uc.Count == 1)
            {
                uc[0].Idx = 0;
                foreach (CChinfo c in this.chinfo)
                {
                    c.C2value = "";
                }
            }
            this.Refresh();
            OnUpdateUserCursor(Mouseinfo.DragIndex);
            return;
        }

        if (e.Button == System.Windows.Forms.MouseButtons.Left)
        {
            if (this.uc.Count < 2)
            {
                Single newx = GetXfromTime(Mouseinfo.Time, ChartRect);
                this.uc.Add(new CUserCursor((short)this.uc.Count, Mouseinfo.Time, newx));
                this.Refresh();
                OnUpdateUserCursor(this.uc.Count);
            }

        }

    }


    private void DispCtrl_Load(object sender, EventArgs e)
    {

    }

    

    }       //end class

}   //end namespace