Files
Groupware/SubProject/CMSControl/cmsview.cs

688 lines
28 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CMSControl
{
public enum eSystemStep : byte
{
IDLE = 0,
INPUT,
OUTPUT,
REINPUT,
FINISH,
RESULT,
CLOSING = 90,
CLOSEWAIT,
CLOSED,
}
public partial class cmsview : Control
{
public eSystemStep step = eSystemStep.IDLE;
public UInt16 _page;
private Point _gridcount;
public UInt16 GridItemCount { get { return (UInt16)(_gridcount.X * _gridcount.Y); } }
public Boolean isDebug { get; set; }
public int LastContactSlotIDX = -1;
//private Font _fontid;
//private Font _fontno;
//private Font _fontcontent;
public float NoStrSize = 100f;
public Boolean bRePaint;
public List<Slot> Slots = new List<Slot>();
public List<Item> Items = new List<Item>();
public UInt16 ItemMargin { get; set; }
public Point GridCount { get { return _gridcount; } set { _gridcount = value; } }
public Font Font_No; //slotno
public Font Font_Top; //top
public Font Font_Bottom; //bottom
public Font Font_Middle; //bottom
public Font Font_Count; //bottom
public System.Drawing.Color color_font_no = Color.White;
public System.Drawing.Color color_font_top = Color.White;
public System.Drawing.Color color_font_middle = Color.White;
public System.Drawing.Color color_font_bottom_left = Color.White;
public System.Drawing.Color color_font_bottom_right = Color.White;
public Padding Padding_No;
public Padding Padding_Top;
public Padding Padding_Bottom;
public Padding Padding_Middle;
public Padding Padding_Count;
public string DisplayT;
public string DisplayM;
public string DisplayBL;
public string DisplayBR;
public System.Windows.Forms.HorizontalAlignment TextAlignT = HorizontalAlignment.Left;
public System.Windows.Forms.HorizontalAlignment TextAlignM = HorizontalAlignment.Left;
public System.Windows.Forms.HorizontalAlignment TextAlignBL = HorizontalAlignment.Left;
public System.Windows.Forms.HorizontalAlignment TextAlignBR = HorizontalAlignment.Right;
public Boolean Enable_MultiBox = false;
public event EventHandler<ItemClickEvent> ItemClick;
public event EventHandler<MessageEvent> Message;
public UInt16 GetMaxPageCount
{
get
{
if (GridItemCount == 0) return 0;
return (UInt16)(Math.Ceiling(Slots.Count * 1.0 / GridItemCount));
}
}
public UInt16 Page
{
get
{
return _page;
}
set
{
if (value < 1) value = 1;
UInt16 MaxPage = GetMaxPageCount;
if (MaxPage < 1) MaxPage = 1;
if (value > MaxPage) value = MaxPage;
if (value != _page)
{
_page = value;
bRePaint = true;
this.Invalidate();
}
}
}
public cmsview()
{
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 += cmsview_MouseDown;
this._page = 1;
ItemMargin = 3;
this.GridCount = new Point(8, 12);
Font_No = new Font("Consolas", 15f);
Font_Bottom = new Font("Consolas", 8f);
Font_Top = new Font("Consolas", 8f);
bRePaint = false;
isDebug = false;
}
public void RaiseMessage(Boolean iserr, string msg)
{
if (Message != null)
Message(this, new MessageEvent(iserr, msg));
}
public void ClearSelectItem()
{
foreach (var no in preSelectedIndex)
this.Slots[no].Selected = false;
}
/// <summary>
/// 지정한 index 의 아이템을 선택합니다. 페이지는 자동 전환됩니다.
/// </summary>
/// <param name="idx"></param>
public Boolean SelectItem(int idx)
{
ushort newPage = (ushort)(Math.Ceiling((double)(idx + 1) / GridItemCount));
if (newPage != this._page) Page = newPage;
if (idx >= Slots.Count)
{
RaiseMessage(true, "Index (" + idx.ToString() + ")Range Error ItemCount=" + this.Slots.Count.ToString());
return false; //존재하지않는 아이템이다.
}
Slots[idx].Selected = true;
if (ItemClick != null)
ItemClick(this, new ItemClickEvent(Point.Empty, idx, MouseButtons.Left, eClickArea.No));
//이전에 선택된 것은 제거한다.
ClearPreSelected();
preSelectedIndex.Add(idx);
this.Invalidate();
return true;
}
/// <summary>
/// id가 일치하는 대상을 모두 찾습니다.
/// </summary>
/// <param name="ID1"></param>
public int SelectItem(string ID1, string ID2)
{
int retval = 0;
//이전에 선택된 것은 제거한다.
ClearPreSelected();
//자식데이터가 속해있다면 그것들을 모두 체크해야한다.
var items = this.Items.Where(t => t.ID1 == ID1 && t.ID2 == ID2);
if (items.Count() < 1)
{
RaiseMessage(false, "Not Found UID=" + ID1);
return retval;
}
//해당 자식들이 속해잇는 슬롯을 모두 선택해준다.
foreach (var item in items)
{
if (item.SlotIDX < this.Slots.Count)
{
var slot = this.Slots[item.SlotIDX];
if (!slot.Selected)
{
slot.Selected = true;
retval += 1;
preSelectedIndex.Add(slot.Index);
}
}
}
ushort newPage = 1;
if (preSelectedIndex.Count > 0)
newPage = (ushort)(Math.Ceiling((double)(preSelectedIndex[preSelectedIndex.Count - 1] + 1) / GridItemCount));
if (newPage != this._page) Page = newPage;
if (ItemClick != null && preSelectedIndex.Count > 0)
ItemClick(this, new ItemClickEvent(Point.Empty, preSelectedIndex[0], MouseButtons.Left, eClickArea.No));
this.Invalidate();
return retval;
}
public int SelectItem(string ID1)
{
int retval = 0;
//이전에 선택된 것은 제거한다.
ClearPreSelected();
//자식데이터가 속해있다면 그것들을 모두 체크해야한다.
var items = this.Items.Where(t => t.ID1 == ID1);
if (items.Count() < 1)
{
RaiseMessage(false, "Not Found UID=" + ID1);
return 0;
}
//해당 자식들이 속해잇는 슬롯을 모두 선택해준다.
foreach (var item in items)
{
if (item.SlotIDX < this.Slots.Count)
{
var slot = this.Slots[item.SlotIDX];
if (!slot.Selected)
{
slot.Selected = true;
retval += 1;
preSelectedIndex.Add(slot.Index);
}
}
}
ushort newPage = 1;
if (preSelectedIndex.Count > 0)
newPage = (ushort)(Math.Ceiling((double)(preSelectedIndex[preSelectedIndex.Count - 1] + 1) / GridItemCount));
if (newPage != this._page) Page = newPage;
this.Invalidate();
return retval;
}
public List<int> preSelectedIndex = new List<int>();
void cmsview_MouseDown(object sender, MouseEventArgs e)
{
//클릭을 하면 어떤개체가
if (GridItemCount < 1 || Slots.Count < 1)
{
RaiseMessage(true, "No items");
return;
}
int StartIndex = (this.Page - 1) * GridItemCount;
for (int i = StartIndex; i < (StartIndex + GridItemCount); i++)
{
if (i < Slots.Count)
{
var item = Slots[i];
if (item.Rect.Contains(e.Location))
{
eClickArea area = eClickArea.Normal;
if (item.RectNo.Contains(e.Location)) area = eClickArea.No;
else if (item.RectM.Contains(e.Location)) area = eClickArea.Title;
else if (item.RectB.Contains(e.Location)) area = eClickArea.Content;
item.Selected = true;
if (ItemClick != null)
ItemClick(this, new ItemClickEvent(e.Location, item.Index, e.Button, area));
ClearPreSelected();
preSelectedIndex.Add(item.Index);
item.Selected = true;
this.Invalidate();
break;
}
}
else break;
}
}
void ClearPreSelected()
{
//이전에 선택된 것은 제거한다.
foreach (var index in preSelectedIndex)
if (index < Slots.Count) Slots[index].Selected = false;
preSelectedIndex.Clear();
}
void arLabel_Resize(object sender, EventArgs e)
{
bRePaint = true;
Invalidate();
}
int cnt = 0;
protected override void OnPaint(PaintEventArgs pe)
{
base.OnPaint(pe);
cnt += 1;
int StartIndex = (this.Page - 1) * GridItemCount;
if (GridItemCount < 1)
{
DrawHelp(pe.Graphics);
}
else
{
///테스트로 데이터를 만든다.
if (Slots.Count < 1)
{
for(int i = 0; i < this.GridItemCount;i++)
{
Slots.Add(new Slot()
{
BackColor = Color.Lime,
BorderColor = Color.Gray,
BorderSize = 2f,
Enable = true,
ForeColor = Color.Black,
Name = "test" + i.ToString(),
Index = (byte)i,
No = (i+1).ToString(),
Selected = false
});
}
bRePaint = true;
}
//영역을 다시그려야하는 상황
if (bRePaint && GridItemCount > 0 && Slots.Count > 0)
{
int gridW = (int)((this.Width - this.Padding.Left - this.Padding.Right) / GridCount.X);
int gridH = (int)((this.Height - this.Padding.Top - this.Padding.Bottom) / GridCount.Y);
Rectangle rect, rect2, rectNo, rectT, rectM, rectB, rectCNT;
int idx = 0;
for (int r = 0; r < GridCount.Y; r++)
{
for (int c = 0; c < GridCount.X; c++)
{
int x = (c * gridW);
int y = (r * gridH);
rect = new Rectangle(x + this.Padding.Left, y + this.Padding.Top, gridW, gridH);
rect2 = new Rectangle(
rect.Left + this.ItemMargin,
rect.Top + ItemMargin,
rect.Width - ItemMargin * 2,
rect.Height - ItemMargin * 2);
float NoWidth = NoStrSize; // rect2.Width * 0.2f;
rectNo = new Rectangle(rect2.Left, rect2.Top, (int)NoWidth, (int)(rect2.Height * 0.3));
var dispHeight1 = (int)(rect2.Height * 0.3);
var dispHeight2 = (int)(rect2.Height * 0.4);
var dispHeight3 = rect2.Height - dispHeight1 - dispHeight2;
rectT = new Rectangle(rectNo.Right, rect2.Top, rect2.Width - rectNo.Width, dispHeight1); ;
rectM = new Rectangle(rectNo.Left, rectT.Bottom, rect2.Width, dispHeight2);
rectB = new Rectangle(rectNo.Left, rectM.Bottom, (int)(rect2.Width / 2.0), dispHeight3);
rectCNT = new Rectangle(rectB.Right, rectM.Bottom, (int)(rect2.Width / 2.0), dispHeight3);
if (StartIndex + idx < Slots.Count)
{
//items[StartIndex + idx].No = (byte)( idx + 1);
Slots[StartIndex + idx].Rect = rect2;
Slots[StartIndex + idx].RectNo = rectNo;
Slots[StartIndex + idx].RectT = rectT;
Slots[StartIndex + idx].RectM = rectM;
Slots[StartIndex + idx].RectB = rectB;
Slots[StartIndex + idx].RectCnt = rectCNT;
Slots[StartIndex + idx].ForeColor = this.ForeColor;
idx += 1;
}
else break;
}
if (StartIndex + idx >= Slots.Count) break;
}
bRePaint = false;
}
for (int i = StartIndex; i < StartIndex + GridItemCount; i++)
{
if (i >= Slots.Count) break; //over check
var item = Slots[i];
var slotItems = Items.Where(t => t.SlotIDX == item.Index);
DrawSlot(pe.Graphics, item, slotItems);
}
if (isDebug)
{
using (Font f = new Font("Consolas", 15))
{
System.Text.StringBuilder sb = new StringBuilder();
sb.AppendLine("## Debug Message ##");
sb.AppendLine("Step : " + this.step.ToString());
sb.AppendLine("Refresh Count : " + this.cnt.ToString());
sb.AppendLine("Slot count : " + Slots.Count.ToString());
sb.AppendLine("Item Count : " + Items.Count.ToString());
sb.AppendLine("font no : " + this.Font_No.ToString());
sb.AppendLine("font top : " + this.Font_Top.ToString());
sb.AppendLine("font mid : " + this.Font.ToString());
sb.AppendLine("font bot : " + this.Font_Bottom.ToString());
sb.Append("Pre Selected index : ");
foreach (var item in preSelectedIndex)
sb.Append(item + ",");
if (preSelectedIndex.Count == 1)
{
//세부내역도 표시한다.
var slot = this.Slots[preSelectedIndex[0]];
var items = this.Items.Where(t => t.SlotIDX == slot.Index);
foreach (var item in items)
{
sb.Append("item " + item.ID1 + ",qty=" + item.Qty.ToString());
}
}
pe.Graphics.DrawString(sb.ToString(), f, Brushes.Black, 11f, 11f);
pe.Graphics.DrawString(sb.ToString(), f, Brushes.Yellow, 10f, 10f);
}
}
}
}
void DrawHelp(Graphics g)
{
System.Text.StringBuilder sb = new StringBuilder();
sb.AppendLine("컨트롤 설정이 완료되지 않았습니다.\n");
sb.AppendLine("이 메세지는 GRID COUNT가 설정되지 않았거나 ITEMS 항목이 없는 경우 표시됩니다.");
sb.AppendLine("ITEMS 갯수가 GRID 갯수를 넘을 경우 페이지가 분리됩니다.\n");
sb.AppendLine("현재 GRID 갯수는 : " + GridCount.ToString() + " = " + GridItemCount.ToString() + " 입니다.");
sb.AppendLine("현재 ITEM 갯수는 : " + Slots.Count.ToString() + " 입니다.\n");
sb.AppendLine("화면에 5x10 의 배열로 표시를 하려면 GridCount에 5x10을 설정하세요.");
sb.AppendLine("ITEMS 는 코드상에서 입력하세요.\n");
sb.AppendLine("# Example #");
sb.AppendLine("var newitem = new CMSControl.Item();");
sb.AppendLine("newitem.No = \"--\";");
sb.AppendLine("newitem.Title = \"ItemName\"");
sb.AppendLine("newitem.Contents = \"Model No\";");
sb.AppendLine("cmsview1.items.Add(newitem);");
g.DrawString(sb.ToString(), this.Font, Brushes.Red, 10f, 10f);
}
public Color slotColorUnUsed = Color.DimGray;
public Color slotColorDisable = Color.Gray;
public Color slotColorSelect = Color.Lime;
void DrawSlot(Graphics g, Slot slot, IEnumerable<Item> items)
{
if (slot.Rect.IsEmpty) return;
//fill background color
g.FillRectangle(Brushes.Gray, slot.Rect);
Color bdColor = Color.FromArgb(194, 192, 194);
Color bColor = slot.BackColor;
float bSize = 1.0f;
if (slot.Selected)
{
bSize = 5.5f;
//bColor = slotColorSelect;
bdColor = Color.Lime;
}
else if (slot.Index == LastContactSlotIDX)
{
bdColor = Color.Yellow;
bSize = 5.5f;
}
if (!slot.Enable) bColor = slotColorDisable;
else if (items.Count() < 1) bColor = slotColorUnUsed;
//no Color.FromArgb(231, 229, 231)
byte R = bColor.R;
byte G = bColor.G;
byte B = bColor.B;
if (R > 22) R -= 22; else R = 0;
if (G > 22) G -= 22; else G = 0;
if (B > 22) B -= 22; else B = 0;
Color bgColor2 = Color.FromArgb(R, G, B);
using (LinearGradientBrush brush = new LinearGradientBrush(slot.RectNo, bColor, bgColor2, LinearGradientMode.Vertical))
{
g.FillRectangle(brush, slot.RectNo);
}
g.DrawRectangle(new Pen(bColor), slot.RectNo);
if (slot.Opend)
{
if (slot.BorderColor == Color.Yellow) bdColor = Color.Tomato;
else bdColor = Color.Yellow;
bSize = 5.0f;
}
Boolean ItemQtyManage = true;
Boolean ItemQtySummary = false;
Boolean ItemExpManage = false;
if (items.Count() > 0)
{
var itemInfo = items.First();
ItemQtyManage = itemInfo.QtyManage;
ItemQtySummary = itemInfo.QtySummary;
ItemExpManage = itemInfo.ExpManage;
}
//아이템이 여러개 있다면 우측 상단에 책갈피 처럼 표시한다.
if (items.Count() > 1)
{
Rectangle openrect = new Rectangle(
(int)(slot.Rect.Right - 15),
(int)(slot.Rect.Top + 1),
15, 15);
Point[] pts = new Point[4];
pts[0] = new Point(slot.Rect.Right - 30, slot.Rect.Top + 1);
pts[1] = new Point(slot.Rect.Right - 1, slot.Rect.Top + 1);
pts[2] = new Point(slot.Rect.Right - 1, slot.Rect.Top + 30);
pts[3] = new Point(slot.Rect.Right - 30, slot.Rect.Top + 1);
g.FillPolygon(new SolidBrush(Color.FromArgb(40, 40, 40)), pts);
using (Font f = new Font("맑은 고딕", 10f))
DrawString(g, f, items.Count().ToString(), openrect, Color.White, 0);
}
string slotnoStr = (slot.Index + 1).ToString();
if (slot.No != "") slotnoStr = slot.No; //180607
if (slot.Enable)
{
string StrT = slot.Name;
string StrM = string.Empty;
string StrBL = string.Empty;
string StrBR = string.Empty;
//값이없는 경우 세부항목에서 가져온다.
var subItems = items.ToArray<Item>();
if (StrT == "")
{
StrT = ParserMessage(DisplayT, subItems); // subItems[0].ID1 + "\n" + subItems[0].VNAME;
}
if (subItems.Count() > 0)
{
StrM = ParserMessage(DisplayM, subItems);// subItems[0].Name;
StrBL = ParserMessage(DisplayBL, subItems);// subItems[0].Model;
StrBR = ParserMessage(DisplayBR, subItems);// "[" + subItems[0].Qty.ToString() + subItems[0].Unit + "]";
}
//g.DrawRectangle(new Pen(Color.Magenta, 1.5f), RectT);
//g.DrawRectangle(new Pen(Color.Red, 1.5f), RectM);
//g.DrawRectangle(new Pen(Color.Yellow, 1.5f), RectB);
//g.DrawRectangle(new Pen(Color.Yellow, 1.5f),);
DrawString(g, Font_No, slotnoStr, slot.RectNo, color_font_no, HorizontalAlignment.Center, Padding_No);
//title
if (StrT != "")
DrawString(g, Font_Top, StrT, slot.RectT, color_font_top, TextAlignT, Padding_Top);
if (StrM != "")
DrawString(g, Font_Middle, StrM, slot.RectM, color_font_middle, TextAlignM, Padding_Middle);
if (StrBL != "")
DrawString(g, Font_Bottom, StrBL, slot.RectB, color_font_bottom_left, TextAlignBL, Padding_Bottom);
if (StrBR != "" && ItemQtyManage)
DrawString(g, Font_Count, StrBR, slot.RectCnt, color_font_bottom_right, TextAlignBR, Padding_Count);
}
else
{
DrawString(g, this.Font_No, slotnoStr, slot.RectNo, color_font_no);
DrawString(g, this.Font_Middle, "Disabled", slot.RectM, color_font_no);
//DrawString(g, fConttent, "DISABLED", RectT, Color.Black, 0);
}
//g.DrawRectangle(Pens.White, slot.RectT);
//g.DrawRectangle(Pens.White, slot.RectM);
//g.DrawRectangle(Pens.White, slot.RectB);
//g.DrawRectangle(Pens.White, slot.RectCnt);
//g.DrawString(items.Count().ToString(), fNo, Brushes.Red, Rect.Left, Rect.Top);
g.DrawLine(new Pen(Color.Black, 5f), slot.Rect.Left + 3, slot.Rect.Bottom + 1, slot.Rect.Right + 2, slot.Rect.Bottom + 1);
g.DrawLine(new Pen(Color.Black, 5f), slot.Rect.Right + 1, slot.Rect.Top + 3, slot.Rect.Right + 1, slot.Rect.Bottom + 4);
//g.DrawRectangle(Pens.Black, slot.Rect.Left + 1, slot.Rect.Top + 1, slot.Rect.Width - 2, slot.Rect.Height - 2);
using (Pen p = new Pen(bdColor, bSize))
{
g.DrawRectangle(p, slot.Rect); //최종테두리
}
slot.BorderColor = bdColor;
//g.DrawString(this.BackColor.ToString(), fID, Brushes.Black,RectNo.Left, RectNo.Top);
if (slot.Expiration)
{
string msg = "Expiration";
var fsize = g.MeasureString(msg, this.Font);
var rectheight = (int)(fsize.Height * 1.5);
Rectangle msgRect = new Rectangle(slot.Rect.Left + 1, slot.Rect.Bottom - rectheight, slot.Rect.Width - 1, rectheight);
g.FillRectangle(new SolidBrush(Color.FromArgb(100, Color.Red)), msgRect);
DrawString(g, this.Font, msg, msgRect, Color.White);
//g.DrawString("expiration", this.Font, Brushes.White, msgRect.Left, msgRect.Top);
}
}
string ParserMessage(string org, Item[] subItems)
{
org = org.Replace("\\n", "\n");
if (subItems.Length > 0)
{
var item = subItems[0];
org = org.Replace("{ID1}", item.ID1);
org = org.Replace("{ID2}", item.ID2);
org = org.Replace("{NAME}", item.Name);
org = org.Replace("{MODEL}", item.Model);
org = org.Replace("{SERIAL}", item.Serial);
if (item.ScaleUnit != item.Unit && item.ScaleUnit != "")
{
org = org.Replace("{QTY}", (item.Qty / item.Scale).ToString());
org = org.Replace("{UNIT}", item.ScaleUnit);
}
else
{
org = org.Replace("{QTY}", item.Qty.ToString());
org = org.Replace("{UNIT}", item.Unit);
}
}
else
{
org = org.Replace("{ID1}", string.Empty);
org = org.Replace("{ID2}", string.Empty);
org = org.Replace("{NAME}", string.Empty);
org = org.Replace("{MODEL}", string.Empty);
org = org.Replace("{SERIAL}", string.Empty);
org = org.Replace("{QTY}", string.Empty);
org = org.Replace("{UNIT}", string.Empty);
}
return org;
}
void DrawString(Graphics g, Font f, string data, Rectangle rect, Color fcolor, System.Windows.Forms.HorizontalAlignment align = HorizontalAlignment.Center, Padding pad = new Padding())
{
var fsize = g.MeasureString(data, f);
float cx, cy;
cx = cy = 0;
switch (align)
{
case HorizontalAlignment.Left:
cx = pad.Left + rect.Left;
cy = pad.Top + rect.Top + (rect.Height - fsize.Height) / 2.0f;
break;
case HorizontalAlignment.Center:
cx = pad.Left + rect.Left + (rect.Width - fsize.Width) / 2.0f;
cy = pad.Top + rect.Top + (rect.Height - fsize.Height) / 2.0f;
break;
case HorizontalAlignment.Right:
cx = rect.Right - fsize.Width - pad.Right;
cy = pad.Top + rect.Top + (rect.Height - fsize.Height) / 2.0f;
break;
}
g.DrawString(data, f, new SolidBrush(fcolor), new PointF(cx + 1, cy + 1));
}
}
}