337 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.ComponentModel;
 | |
| using System.Data;
 | |
| using System.Drawing;
 | |
| using System.Linq;
 | |
| using System.Text;
 | |
| using System.Windows.Forms;
 | |
| 
 | |
| namespace StaffLayoutCtl
 | |
| {
 | |
|     public partial class grid : Control
 | |
|     {
 | |
| 
 | |
|         public Boolean DeveloperMode = true;
 | |
|         private Point GridCount = new Point(30, 20);
 | |
|         private CGrid[,] gridrect = null;
 | |
| 
 | |
|         public grid()
 | |
|         {
 | |
|             InitializeComponent();
 | |
| 
 | |
|             // Set Optimized Double Buffer to reduce flickering
 | |
|             this.SetStyle(ControlStyles.UserPaint, true);
 | |
|             this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
 | |
|             this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
 | |
|             this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
 | |
| 
 | |
|             // Redraw when resized
 | |
|             this.SetStyle(ControlStyles.ResizeRedraw, true);
 | |
|             this.Resize += arLabel_Resize;
 | |
|             this.MouseDown += grid_MouseDown;
 | |
|             this.MouseMove += grid_MouseMove;
 | |
|             this.MouseUp += grid_MouseUp;
 | |
| 
 | |
|              gridrect = new CGrid[GridCount.X, GridCount.Y];
 | |
|         }
 | |
| 
 | |
|         void grid_MouseUp(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             Boolean bOK = false;
 | |
|             if(mousedn && mouseDrag && selectindex != -1 && diffrect != RectangleF.Empty)
 | |
|             {
 | |
|                 if(Math.Abs(mousediff.X) >= 10 && Math.Abs(mousediff.Y) >= 10)
 | |
|                 {
 | |
|                     //좌측코드가 속한 row,col 값으로 이동한다.
 | |
|                     for(int i = 0; i<= gridrect.GetUpperBound(0);i++)
 | |
|                     {
 | |
|                         for (int j = 0; j <= gridrect.GetUpperBound(1); j++)
 | |
|                         {
 | |
|                             var grid = this.gridrect[i, j];
 | |
|                             if(grid.Rect.Contains( diffrect.Location ))
 | |
|                             {
 | |
|                                 var item = this.Items[selectindex];
 | |
|                                 item.Row = grid.Row;
 | |
|                                 item.Col = grid.Col;
 | |
|                                 bOK = true;
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                         if (bOK) break;
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             mousedn = false;
 | |
|             mouseDrag = false;            
 | |
|             this.Invalidate();
 | |
|         }
 | |
| 
 | |
|         void grid_MouseMove(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             mousepos = e.Location;
 | |
|             if (mousedn) mouseDrag = true;
 | |
|             else mouseDrag = false;
 | |
| 
 | |
|             //선택개체 위로 오면 마우스 모양을 변경한다.
 | |
|             if (selectindex < 0)
 | |
|             {
 | |
|                 if (this.Cursor != Cursors.Arrow)
 | |
|                 {
 | |
|                     this.Cursor = Cursors.Arrow;
 | |
|                     this.Invalidate();
 | |
|                 }
 | |
| 
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 var item = Items[selectindex];
 | |
| 
 | |
|                 //중앙부에 있다면 이동형 핸드를
 | |
|                 //외곽에 있다면 크기 조정용 을 표시한다.
 | |
| 
 | |
|                 //크기조정용 영역을 게산한다.
 | |
|                 RectangleF rectt = new RectangleF(item.Rect.Left, item.Rect.Top - 10, item.Rect.Width, 20);
 | |
|                 RectangleF rectb = new RectangleF(item.Rect.Left, item.Rect.Bottom - 10, item.Rect.Height, 20);
 | |
|                 RectangleF rectl = new RectangleF(item.Rect.Left - 10, item.Rect.Top, 20, item.Rect.Height);
 | |
|                 RectangleF rectr = new RectangleF(item.Rect.Right - 10, item.Rect.Top, 20, item.Rect.Height);
 | |
| 
 | |
|                 if (rectt.Contains(e.Location))
 | |
|                 {
 | |
|                     if (this.Cursor != Cursors.PanNorth)
 | |
|                     {
 | |
|                         this.Cursor = Cursors.PanNorth;
 | |
|                         this.Invalidate();
 | |
|                     }
 | |
|                 }
 | |
|                 else if (rectb.Contains(e.Location))
 | |
|                 {
 | |
|                     if (this.Cursor != Cursors.PanSouth)
 | |
|                     {
 | |
|                         this.Cursor = Cursors.PanSouth;
 | |
|                         this.Invalidate();
 | |
|                     }
 | |
|                 }
 | |
|                 else if (rectl.Contains(e.Location))
 | |
|                 {
 | |
|                     if (this.Cursor != Cursors.PanWest)
 | |
|                     {
 | |
|                         this.Cursor = Cursors.PanWest;
 | |
|                         this.Invalidate();
 | |
|                     }
 | |
|                 }
 | |
|                 else if (rectr.Contains(e.Location))
 | |
|                 {
 | |
|                     if (this.Cursor != Cursors.PanEast)
 | |
|                     {
 | |
|                         this.Cursor = Cursors.PanEast;
 | |
|                         this.Invalidate();
 | |
|                     }
 | |
|                 }
 | |
|                 else if (item.Rect.Contains(e.Location))
 | |
|                 {
 | |
|                     if (this.Cursor != Cursors.Hand)
 | |
|                     {
 | |
|                         this.Cursor = Cursors.Hand;
 | |
|                         this.Invalidate();
 | |
|                     }
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     if (this.Cursor != Cursors.Arrow)
 | |
|                     {
 | |
|                         this.Cursor = Cursors.Arrow;
 | |
|                         this.Invalidate();
 | |
|                     }
 | |
|                     else
 | |
|                     {
 | |
|                         if (mousedn)
 | |
|                         {
 | |
| 
 | |
| 
 | |
|                         }
 | |
|                     }
 | |
|                 }
 | |
|                 this.Invalidate(); //화면이 업데이트되도록 함
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         Boolean mouseDrag = false;
 | |
|         Boolean mousedn = false;
 | |
|         Point mousednpos = Point.Empty;
 | |
|         Point mousepos = Point.Empty;
 | |
|         int selectindex = -1;
 | |
|         void grid_MouseDown(object sender, MouseEventArgs e)
 | |
|         {
 | |
|             mousedn = true;
 | |
|             //save down point
 | |
|             mousednpos = e.Location;
 | |
| 
 | |
|             //선택된 아이템을 찾아야한다.
 | |
|             Boolean selected = false;
 | |
|             int r = 0;
 | |
|             int c = 0;
 | |
|             for (int i = 0; i < Items.Count; i++)
 | |
|             {
 | |
|                 var item = Items[i];
 | |
|                 if (item.Rect.Contains(e.Location))
 | |
|                 {
 | |
|                     selectindex = i;
 | |
|                     selected = true;
 | |
|                     r = item.Row;
 | |
|                     c = item.Col;
 | |
|                     selectRect = item.Rect;
 | |
|                     //다른 아이템의 선택을 해제한다.
 | |
|                     Console.WriteLine(string.Format("select item : {0}/{1}", item.Row, item.Col));
 | |
|                     break;
 | |
|                 }
 | |
|             }
 | |
|             if (selected)
 | |
|             {
 | |
|                 foreach (var item in Items)
 | |
|                 {
 | |
|                     if (item.Row == r && item.Col == c) item.Select = true;
 | |
|                     else item.Select = false;
 | |
|                 }
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 selectindex = -1;
 | |
|                 var selitem = Items.Where(t => t.Select);
 | |
|                 foreach (var item in selitem)
 | |
|                     item.Select = false;
 | |
|             }
 | |
|             Invalidate();
 | |
|         }
 | |
|         void arLabel_Resize(object sender, EventArgs e)
 | |
|         {
 | |
|             Make_Grid();
 | |
|             Invalidate();
 | |
|         }
 | |
| 
 | |
|         Point mousediff = Point.Empty;
 | |
|         RectangleF diffrect = RectangleF.Empty;
 | |
| 
 | |
|         protected override void OnPaint(PaintEventArgs pe)
 | |
|         {
 | |
|             base.OnPaint(pe);
 | |
|             Draw_Grid(pe.Graphics);
 | |
|             Draw_Item(pe.Graphics);
 | |
| 
 | |
|             if (mouseDrag && mousedn && selectindex != -1 && mousednpos != Point.Empty)
 | |
|             {
 | |
|                 mousediff = new Point(mousepos.X - mousednpos.X, mousepos.Y - mousednpos.Y);
 | |
| 
 | |
|                 //이동영역을 
 | |
|                 diffrect = new RectangleF(selectRect.Left + mousediff.X,
 | |
|                    selectRect.Top + mousediff.Y,
 | |
|                    selectRect.Width, selectRect.Height);
 | |
| 
 | |
|                 using(SolidBrush sb = new SolidBrush(Color.FromArgb(100,Color.Gray)))
 | |
|                 {
 | |
|                     pe.Graphics.FillRectangle(sb, diffrect);
 | |
|                 }
 | |
| 
 | |
|                 pe.Graphics.DrawRectangle(Pens.DimGray, diffrect.Left, diffrect.Top, diffrect.Width, diffrect.Height);
 | |
|             }
 | |
|             Draw_Debug(pe.Graphics);
 | |
| 
 | |
|         }
 | |
|         void Draw_Debug(Graphics g)
 | |
|         {
 | |
|             System.Text.StringBuilder sb = new StringBuilder();
 | |
|             sb.AppendLine("diff = " + mousediff.ToString());
 | |
|             sb.AppendLine("drag : " + mouseDrag.ToString());
 | |
|             sb.AppendLine("mouse down : " + mousedn.ToString() + ", " + mousednpos.ToString());
 | |
|             sb.AppendLine("mouse pos : " + this.mousepos.ToString());
 | |
|             sb.AppendLine("select index : " + this.selectindex.ToString() + "," + this.selectRect.ToString());
 | |
|             sb.AppendLine("sel rect : " + this.selectRect.ToString());
 | |
|             sb.AppendLine("diff rect : " + this.diffrect.ToString());
 | |
|             sb.AppendLine("cell size : " + cellSize.ToString());
 | |
|             using (Font f = new Font("Consolas", 20f))
 | |
|             {
 | |
|                 g.DrawString(sb.ToString(), f, Brushes.Black, 50 - 1, 50 - 1);
 | |
|                 g.DrawString(sb.ToString(), f, Brushes.Black, 50 - 1, 50 + 1);
 | |
|                 g.DrawString(sb.ToString(), f, Brushes.Black, 50 + 1, 50 - 1);
 | |
|                 g.DrawString(sb.ToString(), f, Brushes.Black, 50 + 1, 50 + 1);
 | |
|                 g.DrawString(sb.ToString(), f, Brushes.Red, 50, 50);
 | |
|             }
 | |
| 
 | |
|         }
 | |
|         public List<CItem> Items = new List<CItem>();
 | |
|         RectangleF selectRect = RectangleF.Empty;
 | |
|         SizeF cellSize = SizeF.Empty;
 | |
|         void Draw_Item(Graphics g)
 | |
|         {
 | |
|             if (DeveloperMode)
 | |
|             {
 | |
|                 //demo item 
 | |
|                 Items.Clear();
 | |
|                 Items.Add(new CItem(r: 1, c: 1, rs: 2, cs: 2, text: "김치균", bg: Color.White.ToArgb()));
 | |
|                 Items.Add(new CItem(4, 4, 1, 1, "박성민"));
 | |
|                 Items.Add(new CItem(6, 6, 10, 3, "고진일"));
 | |
|                 Items.Add(new CItem(7, 7, 2, 2, "테스트"));
 | |
|                 Items[1].Select = true;
 | |
|             }
 | |
| 
 | |
|             int idx = 0;
 | |
|             foreach (var item in Items)
 | |
|             {
 | |
|                 float x = item.Col * cellSize.Width;
 | |
|                 float y = item.Row * cellSize.Height;
 | |
|                 float w = item.ColSpan * cellSize.Width;
 | |
|                 float h = item.RowSpan * cellSize.Height;
 | |
|                 RectangleF rectf = new RectangleF(x, y, w, h);
 | |
|                 g.FillRectangle(Brushes.Yellow, rectf);
 | |
|                 item.Rect = rectf;
 | |
|                 if (item.Select)
 | |
|                 {
 | |
|                     g.DrawRectangle(new Pen(Color.Blue, 4f),
 | |
|                         rectf.Left, rectf.Top, rectf.Width, rectf.Height);
 | |
| 
 | |
|                     //크기조정을 위한 좌우 화살표가 필요하다.
 | |
|                 }
 | |
| 
 | |
|                 string data = idx.ToString();
 | |
|                 if (item.Text != "'") data = item.Text;
 | |
|                 g.DrawString(data + item.Select.ToString(), this.Font, Brushes.Black, x, y);
 | |
|                 idx += 1;
 | |
|             }
 | |
|         }
 | |
|         void Make_Grid()
 | |
|         {
 | |
|             float gw = DisplayRectangle.Width / GridCount.Y;
 | |
|             float gh = DisplayRectangle.Height / GridCount.X;
 | |
|             cellSize = new SizeF(gw, gh);
 | |
|             for (int i = 0; i < GridCount.X; i++)
 | |
|             {
 | |
|                 for (int j = 0; j < GridCount.Y; j++)
 | |
|                 {
 | |
|                     int idx = (i * GridCount.Y) + j;                    
 | |
|                     RectangleF rect = new RectangleF(j * gw, i * gh, gw, gh); ;
 | |
|                     this.gridrect[i, j] = new CGrid(idx);
 | |
|                     this.gridrect[i, j].Rect = rect;
 | |
|                     this.gridrect[i, j].Row = i;
 | |
|                     this.gridrect[i, j].Col = j;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         void Draw_Grid(Graphics g)
 | |
|         {
 | |
|             if(gridrect[0,0]== null) Make_Grid();
 | |
| 
 | |
|             for (int i = 0; i <= gridrect.GetUpperBound(0); i++)
 | |
|             {
 | |
|                 for (int j = 0; j <= gridrect.GetUpperBound(1); j++)
 | |
|                 {
 | |
|                     var grid = this.gridrect[i, j];
 | |
|                     g.DrawRectangle(Pens.Black, grid.Rect.Left, grid.Rect.Top, grid.Rect.Width, grid.Rect.Height);
 | |
|                     g.DrawString(grid.IDX.ToString(), this.Font, Brushes.Blue, grid.Rect.Left, grid.Rect.Top);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|         }
 | |
|     }
 | |
| }
 | 
