using System;
|
using System.Collections.Generic;
|
using System.ComponentModel;
|
using System.Drawing;
|
using System.Drawing.Drawing2D;
|
using System.Linq;
|
using System.Text;
|
using System.Windows.Forms;
|
|
namespace HotelPms.Share.Windows.Component.Design
|
{
|
/// <summary>
|
/// 設計Frame:2015/05/13
|
/// </summary>
|
public class DesignPanel : Panel
|
{
|
#region ★★★★★ Declartions ★★★★★
|
|
public enum ItemType : int
|
{
|
Normal = 0,
|
Line,
|
}
|
|
public enum HitDownSquare : int
|
{
|
None = 0,
|
TopLeft,
|
TopCenter,
|
TopRight,
|
MiddleLeft,
|
MiddleRight,
|
BottomLeft,
|
BottomCenter,
|
BottomRight,
|
Body,
|
}
|
|
public sealed class HitTestInfo
|
{
|
public static readonly HitTestInfo Nowhere;
|
|
internal int y;
|
internal int x;
|
internal HitDownSquare type;
|
internal int index;
|
internal int itemY;
|
internal int itemX;
|
|
static HitTestInfo()
|
{
|
HitTestInfo.Nowhere = new HitTestInfo();
|
}
|
|
internal HitTestInfo()
|
{
|
this.type = HitDownSquare.None;
|
this.x = -1;
|
this.y = -1;
|
this.index = -1;
|
}
|
|
public int X
|
{
|
get { return this.x; }
|
}
|
|
public int Y
|
{
|
get { return this.y; }
|
}
|
|
public int ItemY
|
{
|
get { return this.itemY; }
|
}
|
|
public int ItemX
|
{
|
get { return this.itemX; }
|
}
|
|
|
public int Index
|
{
|
get { return this.index; }
|
}
|
|
public HitDownSquare Type
|
{
|
get { return this.type; }
|
}
|
|
public override int GetHashCode()
|
{
|
return this.x << 16 | this.y << 8 | (int)this.type;
|
}
|
|
public override bool Equals(object obj)
|
{
|
HitTestInfo hi = obj as HitTestInfo;
|
return (this.type == hi.type && this.x == hi.x && this.x == hi.x);
|
}
|
|
public override string ToString()
|
{
|
return string.Concat(new string[7] { "{ ", this.type.ToString(), ",", this.x.ToString(), ",", this.y.ToString(), "}" });
|
}
|
}
|
|
private bool isMouseDown = false;
|
|
private HitTestInfo curHitTestInfo = null;
|
//public bool isSelected = false;
|
private int m_SelectIndex = -1;
|
public bool m_MouseFocused = false;
|
public event EventHandler StyleChange;
|
private float m_Zoom = 1;
|
|
#endregion
|
|
#region ★★★★★ Property ★★★★★
|
|
private DesignItemCollection m_Items = null;
|
|
|
[Category("Item Setting")]
|
[DefaultValue(null)]
|
[Description("Item")]
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
|
public DesignItemCollection Items
|
{
|
get { return m_Items; }
|
set { m_Items = value; }
|
}
|
|
[Category("Item Setting")]
|
[DefaultValue(1F)]
|
[Description("Zoom")]
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
public float Zoom
|
{
|
get { return m_Zoom; }
|
set { m_Zoom = value <= 0 ? 1 : value; Invalidate(); }
|
}
|
|
[Category("Item Setting")]
|
[DefaultValue(-1)]
|
[Description("SelectIndex")]
|
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
|
public int SelectIndex
|
{
|
get { return m_SelectIndex; }
|
set { m_SelectIndex = value; Invalidate(); }
|
}
|
|
public DesignItem CurrentItem
|
{
|
get
|
{
|
if(m_SelectIndex == -1) { return null; }
|
return Items[m_SelectIndex];
|
}
|
}
|
|
#endregion
|
|
#region ★★★★★ Class Event ★★★★★
|
|
public DesignPanel()
|
{
|
//SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
|
this.SetStyle(ControlStyles.DoubleBuffer, true);
|
this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
|
this.SetStyle(ControlStyles.UserPaint, true);
|
this.SetStyle(ControlStyles.ResizeRedraw, true);
|
this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
//SetStyle(ControlStyles.SupportsTransparentBackColor, true);
|
//SetStyle(ControlStyles.Opaque, true); //透明
|
//this.BackColor = Color.Transparent;
|
|
m_Items = new DesignItemCollection(this);
|
}
|
|
#endregion
|
|
#region ★★★★★ Control Event ★★★★★
|
|
protected override void OnEnter(EventArgs e)
|
{
|
base.OnEnter(e);
|
//isSelected = true;
|
Invalidate();
|
}
|
|
protected override void OnLeave(EventArgs e)
|
{
|
base.OnLeave(e);
|
//isSelected = false;
|
Invalidate();
|
}
|
|
protected override void OnMouseEnter(EventArgs e)
|
{
|
base.OnMouseEnter(e);
|
m_MouseFocused = true;
|
Invalidate();
|
}
|
|
protected override void OnMouseLeave(EventArgs e)
|
{
|
base.OnMouseLeave(e);
|
m_MouseFocused = false;
|
Invalidate();
|
}
|
|
protected override void OnMouseDown(MouseEventArgs e)
|
{
|
this.Focus();
|
//e.X, e.Yとは実際画面の位置ではなく、ヒットされる該当コントロールに対する相対位置
|
isMouseDown = true;
|
curHitTestInfo = HitTest(e.X, e.Y);
|
SetCursor(curHitTestInfo);
|
m_SelectIndex = curHitTestInfo.index;
|
Invalidate();
|
System.Diagnostics.Debug.WriteLine(string.Format("OnMouseDown X:{0} Y:{1}", e.X, e.Y));
|
base.OnMouseDown(e);
|
}
|
|
protected override void OnMouseUp(MouseEventArgs e)
|
{
|
this.Cursor = Cursors.Default;
|
isMouseDown = false;
|
System.Diagnostics.Debug.WriteLine(string.Format("OnMouseUp X:{0} Y:{1}", e.X, e.Y));
|
base.OnMouseUp(e);
|
}
|
|
protected override void OnMouseMove(MouseEventArgs e)
|
{
|
if (!isMouseDown)
|
{
|
System.Diagnostics.Debug.WriteLine(string.Format("OnMouseMove X:{0} Y:{1}", e.X, e.Y));
|
HitTestInfo hit = HitTest(e.X, e.Y);
|
SetCursor(hit);
|
}
|
else
|
{
|
int offsetX = 0;
|
int offsetY = 0;
|
System.Diagnostics.Debug.WriteLine(string.Format("X:{0} Y:{1}", e.X, e.Y));
|
if (m_SelectIndex >= 0)
|
{
|
int x = (int)(e.X / m_Zoom);
|
int y = (int)(e.Y / m_Zoom);
|
DesignItem item = Items[m_SelectIndex];
|
switch (curHitTestInfo.Type)
|
{
|
|
case HitDownSquare.TopCenter:
|
offsetY = item.ClientRectangle.Y + item.ClientRectangle.Height - DesignItem.Square.Height * 3;
|
if (y < offsetY)
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.Location.X, y), new Size(item.ClientRectangle.Width, item.ClientRectangle.Y + item.ClientRectangle.Height - y));
|
}
|
break;
|
|
case HitDownSquare.TopRight:
|
offsetX = item.ClientRectangle.X + DesignItem.Square.Width * 3;
|
offsetY = item.ClientRectangle.Y + item.ClientRectangle.Height - DesignItem.Square.Height * 3;
|
if (x > offsetX)
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Location.Y), new Size(x - item.ClientRectangle.X, item.ClientRectangle.Height));
|
}
|
if (y < offsetY)
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.Location.X, y), new Size(item.ClientRectangle.Width, item.ClientRectangle.Y + item.ClientRectangle.Height - y));
|
}
|
break;
|
|
case HitDownSquare.TopLeft:
|
offsetX = item.ClientRectangle.X + item.ClientRectangle.Width - DesignItem.Square.Width * 3;
|
offsetY = item.ClientRectangle.Y + item.ClientRectangle.Height - DesignItem.Square.Height * 3;
|
if (x < offsetX)
|
{
|
item.ClientRectangle = new Rectangle(new Point(x, item.ClientRectangle.Y), new Size(item.ClientRectangle.X + item.ClientRectangle.Width - x, item.ClientRectangle.Height));
|
}
|
if (y < offsetY)
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, y), new Size(item.ClientRectangle.Width, item.ClientRectangle.Y + item.ClientRectangle.Height - y));
|
}
|
break;
|
|
case HitDownSquare.MiddleLeft:
|
offsetX = item.ClientRectangle.X + item.ClientRectangle.Width - DesignItem.Square.Width * 3;
|
if (x < offsetX)
|
{
|
item.ClientRectangle = new Rectangle(new Point(x, item.ClientRectangle.Y), new Size(item.ClientRectangle.X + item.ClientRectangle.Width - x, item.ClientRectangle.Height));
|
}
|
break;
|
|
case HitDownSquare.BottomCenter:
|
offsetY = item.ClientRectangle.Y + DesignItem.Square.Height * 3;
|
if (y > offsetY) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Width, y - item.ClientRectangle.Y)); }
|
break;
|
|
case HitDownSquare.BottomLeft:
|
offsetX = item.ClientRectangle.X + item.ClientRectangle.Width - DesignItem.Square.Width * 3;
|
offsetY = item.ClientRectangle.Y + DesignItem.Square.Height * 3;
|
if (x < offsetX)
|
{
|
item.ClientRectangle = new Rectangle(new Point(x, item.ClientRectangle.Y), new Size(item.ClientRectangle.X + item.ClientRectangle.Width - x, item.ClientRectangle.Height));
|
}
|
if (y > offsetY) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Width, y - item.ClientRectangle.Y)); }
|
break;
|
|
case HitDownSquare.BottomRight:
|
offsetX = item.ClientRectangle.X + DesignItem.Square.Width * 3;
|
offsetY = item.ClientRectangle.Y + DesignItem.Square.Height * 3;
|
if (x > offsetX)
|
{
|
item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(x - item.ClientRectangle.X, item.ClientRectangle.Height));
|
}
|
if (y > offsetY) { item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Width, y - item.ClientRectangle.Y)); }
|
break;
|
|
case HitDownSquare.MiddleRight:
|
offsetX = item.ClientRectangle.X + DesignItem.Square.Width * 3;
|
if (x > offsetX)
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Location.Y), new Size(x - item.ClientRectangle.X, item.ClientRectangle.Height));
|
}
|
break;
|
case HitDownSquare.Body:
|
offsetX = x - (int)(curHitTestInfo.X / m_Zoom);
|
offsetY = y - (int)(curHitTestInfo.Y / m_Zoom);
|
item.ClientRectangle = new Rectangle(new Point(curHitTestInfo.ItemX + offsetX, curHitTestInfo.ItemY + offsetY), item.ClientRectangle.Size);
|
break;
|
}
|
}
|
//RefreshBackground();
|
Invalidate();
|
if (StyleChange != null) { StyleChange(this, new EventArgs()); }
|
}
|
base.OnMouseMove(e);
|
}
|
|
protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
|
{
|
DesignItem item = null;
|
switch (e.KeyCode)
|
{
|
case Keys.Up:
|
if (m_SelectIndex >= 0)
|
{
|
item = Items[m_SelectIndex];
|
if (e.Shift)
|
{
|
if (item.ClientRectangle.Size.Height > DesignItem.Square.Height * 3)
|
{
|
item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width, item.ClientRectangle.Size.Height - 1));
|
}
|
}
|
else
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Y - 1), item.ClientRectangle.Size);
|
}
|
if (StyleChange != null) { StyleChange(this, new EventArgs()); }
|
}
|
break;
|
case Keys.Down:
|
if (m_SelectIndex >= 0)
|
{
|
item = Items[m_SelectIndex];
|
if (e.Shift)
|
{
|
item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width, item.ClientRectangle.Size.Height + 1));
|
}
|
else
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X, item.ClientRectangle.Y + 1), item.ClientRectangle.Size);
|
}
|
|
|
if (StyleChange != null) { StyleChange(this, new EventArgs()); }
|
}
|
break;
|
case Keys.Left:
|
if (m_SelectIndex >= 0)
|
{
|
item = Items[m_SelectIndex];
|
if (e.Shift)
|
{
|
if (item.ClientRectangle.Size.Width > DesignItem.Square.Width * 3)
|
{
|
item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width - 1, item.ClientRectangle.Size.Height));
|
}
|
}
|
else
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X - 1, item.ClientRectangle.Y), item.ClientRectangle.Size);
|
}
|
if (StyleChange != null) { StyleChange(this, new EventArgs()); }
|
}
|
break;
|
case Keys.Right:
|
if (m_SelectIndex >= 0)
|
{
|
item = Items[m_SelectIndex];
|
if (e.Shift)
|
{
|
item.ClientRectangle = new Rectangle(item.ClientRectangle.Location, new Size(item.ClientRectangle.Size.Width + 1, item.ClientRectangle.Size.Height));
|
}
|
else
|
{
|
item.ClientRectangle = new Rectangle(new Point(item.ClientRectangle.X + 1, item.ClientRectangle.Y), item.ClientRectangle.Size);
|
}
|
if (StyleChange != null) { StyleChange(this, new EventArgs()); }
|
}
|
break;
|
default:
|
base.OnPreviewKeyDown(e);
|
return;
|
}
|
e.IsInputKey = true;
|
//RefreshBackground();
|
Invalidate();
|
}
|
|
protected override void OnPaint(PaintEventArgs e)
|
{
|
base.OnPaint(e);//コントロールのプロパティで設定した部分の描画
|
|
GraphicsState state = e.Graphics.Save();
|
e.Graphics.ScaleTransform((float)m_Zoom, (float)m_Zoom);
|
|
//選択枠
|
int i = 0;
|
foreach (DesignItem item in m_Items)
|
{
|
System.Diagnostics.Debug.WriteLine(m_SelectIndex.ToString());
|
item.DesignMode = (i == m_SelectIndex);
|
item.Draw(e.Graphics);
|
i++;
|
}
|
|
e.Graphics.Restore(state);
|
}
|
|
#endregion
|
|
#region ★★★★★ Private Function ★★★★★
|
|
|
private void SetCursor(HitTestInfo hit)
|
{
|
switch (hit.type)
|
{
|
case HitDownSquare.BottomRight:
|
case HitDownSquare.TopLeft:
|
this.Cursor = Cursors.SizeNWSE;
|
break;
|
case HitDownSquare.BottomCenter:
|
case HitDownSquare.TopCenter:
|
this.Cursor = Cursors.SizeNS;
|
break;
|
case HitDownSquare.BottomLeft:
|
case HitDownSquare.TopRight:
|
this.Cursor = Cursors.SizeNESW;
|
break;
|
case HitDownSquare.MiddleLeft:
|
case HitDownSquare.MiddleRight:
|
this.Cursor = Cursors.SizeWE;
|
break;
|
case HitDownSquare.Body:
|
this.Cursor = Cursors.SizeAll;
|
break;
|
default:
|
this.Cursor = Cursors.Default;
|
break;
|
}
|
}
|
|
#endregion
|
|
#region ★★★★★ Public Function ★★★★★
|
|
private bool InRectangle(Rectangle r, int x, int y)
|
{
|
return (r.X * m_Zoom <= x && x <= (r.X + r.Width) * m_Zoom) && (r.Y * m_Zoom <= y && y <= (r.Y + r.Height) * m_Zoom);
|
}
|
|
public HitTestInfo HitTest(int x, int y)
|
{
|
HitTestInfo hit = new HitTestInfo();
|
hit.x = x;
|
hit.y = y;
|
|
for (int idx = Items.Count - 1; idx >= 0; idx--)
|
{
|
DesignItem item = Items[idx];
|
for (int i = 0; i < item.SmallRect.Length; i++)
|
{
|
//if (item.SmallRect[i].Contains(x, y))
|
if (InRectangle(item.SmallRect[i], x, y))
|
{
|
hit.type = (HitDownSquare)(i + 1);
|
hit.index = idx;
|
return hit;
|
}
|
}
|
|
for (int i = 0; i < item.BoundRect.Length; i++)
|
{
|
//if (item.BoundRect[i].Contains(x, y))
|
if (InRectangle(item.BoundRect[i], x, y))
|
{
|
switch (i)
|
{
|
case 0:
|
hit.type = HitDownSquare.TopCenter;
|
break;
|
case 1:
|
hit.type = HitDownSquare.MiddleLeft;
|
break;
|
case 2:
|
hit.type = HitDownSquare.BottomCenter;
|
break;
|
case 3:
|
hit.type = HitDownSquare.MiddleRight;
|
break;
|
}
|
if (item.Appearance == ItemType.Line)
|
{
|
hit.type = HitDownSquare.Body;
|
hit.itemX = item.ClientRectangle.X;
|
hit.itemY = item.ClientRectangle.Y;
|
}
|
hit.index = idx;
|
return hit;
|
}
|
}
|
|
Rectangle bodyR = item.ClientRectangle;
|
if (item.Appearance == ItemType.Line)
|
{
|
if (item.X1 == item.X2) { bodyR = new Rectangle(bodyR.Location, new Size((int)item.LineWidth < DesignItem.Square.Width ? DesignItem.Square.Width : (int)item.LineWidth, item.ClientRectangle.Height)); }
|
else if (item.Y1 == item.Y2) { bodyR = new Rectangle(bodyR.Location, new Size(item.ClientRectangle.Width, (int)item.LineWidth < DesignItem.Square.Height ? DesignItem.Square.Height : (int)item.LineWidth)); }
|
}
|
|
//if (bodyR.Contains(x, y))
|
if (InRectangle(bodyR, x, y))
|
{
|
hit.type = HitDownSquare.Body;
|
hit.index = idx;
|
hit.itemX = item.ClientRectangle.X;
|
hit.itemY = item.ClientRectangle.Y;
|
return hit;
|
}
|
}
|
|
return HitTestInfo.Nowhere;
|
}
|
|
public void RemoveItem()
|
{
|
if (m_SelectIndex == -1) { return; }
|
this.Items.RemoveAt(m_SelectIndex);
|
if (this.Items.Count == 0) { m_SelectIndex = -1; }
|
else if (m_SelectIndex >= this.Items.Count) { m_SelectIndex = this.Items.Count - 1; }
|
Invalidate();
|
}
|
|
public DesignItem SelectItem(string name)
|
{
|
for (int i = 0; i < Items.Count; i++)
|
{
|
if(Items[i].Name == name)
|
{
|
m_SelectIndex = i;
|
Invalidate();
|
return CurrentItem;
|
}
|
}
|
|
return null;
|
}
|
|
public void BringItemToFront()
|
{
|
if (m_SelectIndex == -1 || Items.Count == 1) { return; }
|
DesignItem item = CurrentItem;
|
Items.Remove(item);
|
Items.Add(item);
|
m_SelectIndex = Items.Count - 1;
|
Invalidate();
|
}
|
|
public void SendItemToBack()
|
{
|
if (m_SelectIndex == -1 || Items.Count == 1) { return; }
|
DesignItem item = CurrentItem;
|
Items.Remove(item);
|
Items.Insert(item, 0);
|
m_SelectIndex = 0;
|
Invalidate();
|
}
|
|
#endregion
|
}
|
}
|