981 lines
30 KiB
C#
Raw Normal View History

2025-03-16 13:11:08 +08:00

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Text.Json.Serialization;
using DH.Commons.Enums;
using static DH.Commons.Enums.EnumHelper;
namespace DH.UI.Model.Winform
{
[Serializable]
public abstract class ElementBase : IShapeElement, IEventHandle, ICloneable, IComparable<ElementBase>, IDisposable
{
#region
protected int _mouseIntersectDistance = 4;
#endregion
#region
/// <summary>
/// ID采用GUID
/// </summary>
[ReadOnly(true)]
[Category("\t通用标识")]
[Description("GUID")]
public virtual string ID { get; set; } = Guid.NewGuid().ToString().ToUpper();
/// <summary>
/// 序号
/// </summary>
[Category("\t通用标识")]
[Description("序号")]
public virtual int Index { get; set; } = 0;
[Browsable(false)]
public virtual int GroupIndex { get; set; } = 0;
private string name = "";
/// <summary>
/// 名称
/// </summary>
[Category("\t通用标识")]
[Description("名称")]
public virtual string Name
{
get
{
if (string.IsNullOrWhiteSpace(name))
{
return GetDisplayText();
}
else
{
return name;
}
}
set => name = value;
}
#endregion
#region
private bool isEnabled = true;
//[Browsable(false)]
public virtual bool IsEnabled
{
get
{
return isEnabled;
}
set
{
//if (isEnabled != value)
//{
// isEnabled = value;
// PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs("IsEnabled"), null, null);
//}
Set(ref isEnabled, value);
}
}
[Browsable(false)]
public virtual bool IsShowing { get; set; } = true;
private bool showList = true;
[Browsable(false)]
public virtual bool ShowList
{
get => showList;
set => Set(ref showList, value);
}
#endregion
#region
[JsonIgnore]
protected PointF _startPoint, _currentPoint;
#endregion
#region
[Browsable(false)]
public NoticedPoints CreatePoints { get; set; } = new NoticedPoints();
public virtual bool IsCreatedDone()
{
return CreatePoints.Count >= 2;
}
//protected Region Region { get; set; }
#region
#region
[JsonIgnore]
[Browsable(false)]
protected Pen Pen { get; set; } = new Pen(Color.Red, 1);
protected virtual void SetNewStatePen()
{
Pen = new Pen(Color.Red, 3);
}
protected virtual void SetNormalPen()
{
Pen = new Pen(Color.Red, 1);
}
protected virtual void SetHoverPen()
{
Pen = new Pen(Color.BlueViolet, 3);
}
protected virtual void SetInSidePen()
{
Pen = new Pen(Color.YellowGreen, 3);
}
protected virtual void SetSelectedPen()
{
Pen = new Pen(Color.Pink, 3);
}
protected virtual void SetMeasureDoneOKPen()
{
Pen = new Pen(Color.Green, 2);
}
protected virtual void SetMeasureDoneNGPen()
{
Pen = new Pen(Color.Red, 2);
}
protected virtual void SetMeasuringPen()
{
Pen = new Pen(Color.Yellow, 3);
}
#endregion
#region
//[JsonIgnore]
//protected Pen PenText = new Pen(Color.Black, 1);
//[JsonIgnore]
//protected Pen PenTextOK = new Pen(Color.Green, 1.5f);
//[JsonIgnore]
//protected Pen PenTextNG = new Pen(Color.Red, 2);
///// <summary>
///// 字体大小
///// </summary>
//[Category("显示属性")]
//[Description("字体大小")]
////[Browsable(false)]
//public virtual float FontSize { get; set; } = 15;
/// <summary>
/// 字体大小
/// </summary>
[Category("显示属性")]
[Description("字体设置")]
[Browsable(false)]
public virtual Font Font { get; set; } = new Font(new FontFamily("Tahoma"), 15, GraphicsUnit.World);
/// <summary>
/// 字体和基元的距离
/// </summary>
[Category("显示属性")]
[Description("字体和基元的距离")]
[Browsable(false)]
public virtual int FontDistance { get; set; } = 15;
[Category("显示属性")]
[Description("显示字符说明")]
[Browsable(false)]
public virtual bool IsShowRemark { get; set; } = true;
#endregion
#endregion
//public Graphics Graphics { get; set; }
public abstract void Draw(Graphics g);
protected abstract void DrawResult(Graphics g);
#endregion
#region
private ElementState state = ElementState.New;
[JsonIgnore]
[Browsable(false)]
public ElementState State
{
get
{
return state;
}
set
{
if (state != value)
{
ElementState preState = state;
Set(ref state, value);
EventRouter.TriggerElementsMouseStateChanged(this, preState, state);
switch (state)
{
case ElementState.MouseHover:
SetHoverPen();
break;
case ElementState.MouseInSide:
SetInSidePen();
break;
case ElementState.Selected:
SetSelectedPen();
break;
case ElementState.Normal:
SetNormalPen();
break;
case ElementState.Measuring:
SetMeasuringPen();
break;
case ElementState.MeasureDoneOK:
SetMeasureDoneOKPen();
break;
case ElementState.MeasureDoneNG:
SetMeasureDoneNGPen();
break;
case ElementState.New:
SetNewStatePen();
break;
}
}
}
}
/// <summary>
/// 是否是运行模式
/// </summary>
[Browsable(false)]
public RunMode RunMode { get; set; } = RunMode.NormalMode;
#endregion
#region
public abstract object Clone();
public virtual void Initial()
{
State = ElementState.New;
CreatePoints = new NoticedPoints();
}
#endregion
#region IMouseEvent
public virtual void OnMouseDoubleClick(PointF p)
{
if (State == ElementState.MeasureDoneNG || State == ElementState.MeasureDoneOK)
return;
//if (State == ElementState.MouseInSide)
//{
// State = ElementState.Selected;
//}
//else if (State == ElementState.Selected || State == ElementState.Moving)
//{
// if (IsMouseInSide(p))
// {
// State = ElementState.MouseInSide;
// }
//}
if (IsMouseInSide(p))
{
State = ElementState.Selected;
}
}
public abstract void OnKeyDown(object sender, KeyEventArgs e);
public abstract void OnKeyUp(object sender, KeyEventArgs e);
public virtual void OnMouseDown(PointF p)
{
//switch (State)
//{
// case ElementState.New:
// OnMouseDownWhenNew(p);
// break;
// case ElementState.MouseHover:
// break;
// case ElementState.MouseInSide:
// State = ElementState.Selected;
// break;
// case ElementState.Selected:
// _startPoint = p;
// State = ElementState.Moving;
// break;
// case ElementState.Normal:
// break;
//}
if (State == ElementState.New)
{
OnMouseDownWhenNew(p);
}
else if (IsMouseCanMoveElement(p) && State == ElementState.Selected)
{
State = ElementState.Moving;
}
else if (IsMouseCanStretchBottom(p) && State == ElementState.CanStretchBottom)
{
State = ElementState.StretchingBottom;
}
else if (IsMouseCanStretchTop(p) && State == ElementState.CanStretchTop)
{
State = ElementState.StretchingTop;
}
else if (IsMouseCanStretchLeft(p) && State == ElementState.CanStretchLeft)
{
State = ElementState.StretchingLeft;
}
else if (IsMouseCanStretchRight(p) && State == ElementState.CanStretchRight)
{
State = ElementState.StretchingRight;
}
else if (IsMouseCanStretchLeftLowerCorner(p) && State == ElementState.CanStretchLeftLowerCorner)
{
State = ElementState.StretchingLeftLowerCorner;
}
else if (IsMouseCanStretchLeftUpperCorner(p) && State == ElementState.CanStretchLeftUpperCorner)
{
State = ElementState.StretchingLeftUpperCorner;
}
else if (IsMouseCanStretchRightLowerCorner(p) && State == ElementState.CanStretchRightLowerCorner)
{
State = ElementState.StretchingRightLowerCorner;
}
else if (IsMouseCanStretchRightUpperCorner(p) && State == ElementState.CanStretchRightUpperCorner)
{
State = ElementState.StretchingRightUpperCorner;
}
}
public virtual void OnMouseMove(PointF p)
{
switch (State)
{
case ElementState.New:
OnMouseMoveWhenNew(p);
break;
case ElementState.Selected:
{
if (IsMouseCanStretchLeft(p))
{
State = ElementState.CanStretchLeft;
}
else if (IsMouseCanStretchRight(p))
{
State = ElementState.CanStretchRight;
}
else if (IsMouseCanStretchTop(p))
{
State = ElementState.CanStretchTop;
}
else if (IsMouseCanStretchBottom(p))
{
State = ElementState.CanStretchBottom;
}
else if (IsMouseCanStretchLeftLowerCorner(p))
{
State = ElementState.CanStretchLeftLowerCorner;
}
else if (IsMouseCanStretchLeftUpperCorner(p))
{
State = ElementState.CanStretchLeftUpperCorner;
}
else if (IsMouseCanStretchRightLowerCorner(p))
{
State = ElementState.CanStretchRightLowerCorner;
}
else if (IsMouseCanStretchRightUpperCorner(p))
{
State = ElementState.CanStretchRightUpperCorner;
}
break;
}
case ElementState.Moving:
_currentPoint = p;
//Translate(_currentPoint.X - _startPoint.X, _currentPoint.Y - _startPoint.Y);
//_startPoint = _currentPoint;
Relocate(p);
break;
case ElementState.MouseHover:
case ElementState.MouseInSide:
case ElementState.Normal:
//if (IsMouseInSide(p))
//{
// State = ElementState.MouseInSide;
//}
//else if (IsMouseHover(p))
//{
// State = ElementState.MouseHover;
//}
//else
//{
// State = ElementState.Normal;
//}
break;
case ElementState.CanStretchBottom:
if (!IsMouseCanStretchBottom(p))
{
State = ElementState.Selected;
}
break;
case ElementState.CanStretchTop:
if (!IsMouseCanStretchTop(p))
{
State = ElementState.Selected;
}
break;
case ElementState.CanStretchLeft:
if (!IsMouseCanStretchLeft(p))
{
State = ElementState.Selected;
}
break;
case ElementState.CanStretchRight:
if (!IsMouseCanStretchRight(p))
{
State = ElementState.Selected;
}
break;
case ElementState.CanStretchLeftUpperCorner:
if (!IsMouseCanStretchLeftUpperCorner(p))
{
State = ElementState.Selected;
}
break;
case ElementState.CanStretchLeftLowerCorner:
if (!IsMouseCanStretchLeftLowerCorner(p))
{
State = ElementState.Selected;
}
break;
case ElementState.CanStretchRightLowerCorner:
if (!IsMouseCanStretchRightLowerCorner(p))
{
State = ElementState.Selected;
}
break;
case ElementState.CanStretchRightUpperCorner:
if (!IsMouseCanStretchRightUpperCorner(p))
{
State = ElementState.Selected;
}
break;
case ElementState.StretchingTop:
StretchTop(p);
break;
case ElementState.StretchingBottom:
StretchBottom(p);
break;
case ElementState.StretchingLeft:
StretchLeft(p);
break;
case ElementState.StretchingRight:
StretchRight(p);
break;
case ElementState.StretchingLeftLowerCorner:
StretchLeftLowerCorner(p);
break;
case ElementState.StretchingLeftUpperCorner:
StretchLeftUpperCorner(p);
break;
case ElementState.StretchingRightLowerCorner:
StretchRightLowerCorner(p);
break;
case ElementState.StretchingRightUpperCorner:
StretchRightUpperCorner(p);
break;
}
}
public virtual void OnMouseUp(PointF p)
{
switch (State)
{
case ElementState.New:
OnMouseUpWhenNew(p);
break;
case ElementState.Moving:
State = ElementState.Selected;
break;
case ElementState.Selected:
if (!IsMouseInSide(p))
{
State = ElementState.Normal;
}
break;
case ElementState.StretchingBottom:
State = ElementState.CanStretchBottom;
break;
case ElementState.StretchingLeft:
State = ElementState.CanStretchLeft;
break;
case ElementState.StretchingRight:
State = ElementState.CanStretchRight;
break;
case ElementState.StretchingTop:
State = ElementState.CanStretchTop;
break;
case ElementState.StretchingLeftLowerCorner:
State = ElementState.CanStretchLeftLowerCorner;
break;
case ElementState.StretchingLeftUpperCorner:
State = ElementState.CanStretchLeftUpperCorner;
break;
case ElementState.StretchingRightUpperCorner:
State = ElementState.CanStretchRightUpperCorner;
break;
case ElementState.StretchingRightLowerCorner:
State = ElementState.CanStretchRightLowerCorner;
break;
default:
State = ElementState.Normal;
break;
}
AfterTranformOp();
}
public virtual void AfterTranformOp()
{
}
#region
/// <summary>
/// 当状态为New时的鼠标按下操作
/// </summary>
/// <param name="p"></param>
public abstract void OnMouseDownWhenNew(PointF p);
public abstract void OnMouseMoveWhenNew(PointF p);
public abstract void OnMouseUpWhenNew(PointF p);
#endregion
#endregion
#region
[JsonIgnore]
public Action<ElementBase> OnDrawDone;
[JsonIgnore]
public Action<ElementBase> OnMeasureDone;
[JsonIgnore]
public Action<ElementBase> OnElementEnableChanged;
#endregion
#region
/// <summary>
/// 基类基础的Rectangle 用于计算MouseHover和Inside等
/// </summary>
[Browsable(false)]
public Rectangle BaseRectangle { get; set; }
EnumHelper.ElementState IShapeElement.State { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public abstract bool IsMouseHover(PointF p);
public abstract bool IsMouseInSide(PointF p);
public abstract bool IsIntersect(RectangleF rect);
#region Move & Stretch & Move Anchor
public virtual bool IsMouseCanMoveElement(PointF p)
{
return false;
}
public virtual bool IsMouseCanStretchLeft(PointF p)
{
return false;
}
public virtual bool IsMouseCanStretchRight(PointF p)
{
return false;
}
public virtual bool IsMouseCanStretchTop(PointF p)
{
return false;
}
public virtual bool IsMouseCanStretchBottom(PointF p)
{
return false;
}
public virtual void StretchLeft(PointF p)
{
}
public virtual void StretchRight(PointF p)
{
}
public virtual void StretchTop(PointF p)
{
}
public virtual void StretchBottom(PointF p)
{
}
public virtual bool IsMouseCanStretchLeftUpperCorner(PointF p)
{
return false;
}
public virtual bool IsMouseCanStretchRightUpperCorner(PointF p)
{
return false;
}
public virtual bool IsMouseCanStretchLeftLowerCorner(PointF p)
{
return false;
}
public virtual bool IsMouseCanStretchRightLowerCorner(PointF p)
{
return false;
}
public virtual void StretchLeftUpperCorner(PointF p)
{
}
public virtual void StretchRightUpperCorner(PointF p)
{
}
public virtual void StretchLeftLowerCorner(PointF p)
{
}
public virtual void StretchRightLowerCorner(PointF p)
{
}
public virtual bool IsMouseCanMoveAnchor(PointF p)
{
return false;
}
#endregion
#endregion
#region
public abstract void Translate(float x, float y);
public virtual void Relocate(PointF point) { }
//public abstract void RotateAt(int x, int y, float degree);
#endregion
#region
//[Browsable(false)]
//public PlanPoint MovePoint { get; set; }
#endregion
#region
//[Browsable(false)]
//public CameraOperationConfigBase CameraOpConfig { get; set; }
#endregion
#region
#endregion
#region
/// <summary>
/// 算法
/// </summary>
/// <param name="paras">计算参数</param>
public virtual void Calculate(Bitmap image) { }
public virtual void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight) { }
public virtual void Calculate(string imagePath) { }
#endregion
#region
//[Description("图片保存方式")]
//public ImageSaveMode ImageSaveMode { get; set; } = ImageSaveMode.NoSave;
//public virtual void SaveImage(Bitmap image)
//{
// if (string.IsNullOrWhiteSpace(AOIMeasure.GlobalVar.ImageSaveDirectory) || ImageSaveMode == ImageSaveMode.NoSave)
// {
// return;
// }
// DirectoryInfo dir = new DirectoryInfo(GlobalVar.ImageSaveDirectory);
// if (!dir.Exists)
// {
// dir.Create();
// }
// string imgPath = Path.Combine(AOIMeasure.GlobalVar.ImageSaveDirectory, Name + "_" + DateTime.Now.ToString("MMdd_HHmmss") + ".bmp");
// switch (ImageSaveMode)
// {
// case ImageSaveMode.SaveImage:
// image.Save(imgPath);
// break;
// case ImageSaveMode.SaveImageWithElement:
// Bitmap bmp = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppArgb);
// using (Graphics g = Graphics.FromImage(bmp))
// {
// g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
// g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
// g.DrawImage(image, 0, 0, image.Width, image.Height);
// Draw(g);
// }
// bmp.Save(imgPath);
// break;
// }
//}
//public virtual void SaveImage(IntPtr imagePtr, int ptrSize)
//{
// Bitmap map = null;
// unsafe
// {
// byte* pArray = (byte*)imagePtr;
// byte[] array = new byte[ptrSize];
// Marshal.Copy(imagePtr, array, 0, ptrSize);
// using (MemoryStream ms = new MemoryStream(array))
// {
// map = (Bitmap)Image.FromStream(ms);
// }
// }
// SaveImage(map);
//}
//public virtual void SaveImage(string imagePath)
//{
// using (Bitmap map = Image.FromFile(imagePath) as Bitmap)
// {
// SaveImage(map);
// }
//}
#endregion
#region
public virtual void InitialMeasureResult()
{
//PropertyInfo[] prop = this.GetType().GetProperties();
//Array.ForEach(prop, p =>
//{
// if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
// {
// MeasureSpec spec = p.GetValue(this) as MeasureSpec;
// spec.Result = MeasureResult.NotYet;
// p.SetValue(this, spec);
// }
//});
}
public virtual void SetActualValue(double v)
{
//PropertyInfo[] prop = this.GetType().GetProperties();
//Array.ForEach(prop, p =>
// {
// if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
// {
// MeasureSpec spec = p.GetValue(this) as MeasureSpec;
// spec.ActualValue = (float)v;
// p.SetValue(this, spec);
// }
// });
}
public virtual void SetStandardValue(double v)
{
//PropertyInfo[] prop = this.GetType().GetProperties();
//Array.ForEach(prop, p =>
//{
// if ((p.PropertyType.Name == typeof(MeasureSpec).Name) && p.CanRead && p.CanWrite)
// {
// MeasureSpec spec = p.GetValue(this) as MeasureSpec;
// spec.StandardValue = (float)v;
// p.SetValue(this, spec);
// }
//});
}
#endregion
#region IPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
public virtual void Set<T>(ref T field, T newValue, [CallerMemberName] string propName = null)
{
if (!field.Equals(newValue))
{
field = newValue;
//PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs(propName), null, null);
RaisePropertyChanged(propName);
}
}
public virtual void RaisePropertyChanged(string propName = "")
{
//PropertyChanged?.BeginInvoke(this, new PropertyChangedEventArgs(propName), null, null);
//Task.Run(() =>
//{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
//});
}
#endregion
public override string ToString()
{
return GetDisplayText();
}
public abstract string GetDisplayText();
#region IComparable
public virtual int CompareTo(ElementBase other)
{
//throw new NotImplementedException();
return Index - other.Index;
}
#endregion
#region IDisposable Support
private bool disposedValue = false; // 要检测冗余调用
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// 释放托管状态(托管对象)。
Pen?.Dispose();
}
// TODO: 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
// TODO: 将大型字段设置为 null。
disposedValue = true;
}
}
// TODO: 仅当以上 Dispose(bool disposing) 拥有用于释放未托管资源的代码时才替代终结器。
// ~ElementBase()
// {
// // 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
// Dispose(false);
// }
// 添加此代码以正确实现可处置模式。
public void Dispose()
{
// 请勿更改此代码。将清理代码放入以上 Dispose(bool disposing) 中。
Dispose(true);
// TODO: 如果在以上内容中替代了终结器,则取消注释以下行。
// GC.SuppressFinalize(this);
}
#endregion
}
[Serializable]
public abstract class DisplayElementBase : ElementBase
{
//public override object Clone()
//{
// throw new NotImplementedException();
//}
//public override void Draw(Graphics g)
//{
// throw new NotImplementedException();
//}
//public override string GetDisplayText()
//{
// throw new NotImplementedException();
//}
//public override bool IsIntersect(Rectangle rect)
//{
// throw new NotImplementedException();
//}
public override bool IsMouseHover(PointF p)
{
return false;
}
//public override bool IsMouseInSide(Point p)
//{
// throw new NotImplementedException();
//}
public override void OnKeyDown(object sender, KeyEventArgs e)
{
}
public override void OnKeyUp(object sender, KeyEventArgs e)
{
}
public override void OnMouseDownWhenNew(PointF p)
{
}
public override void OnMouseMoveWhenNew(PointF p)
{
}
public override void OnMouseUpWhenNew(PointF p)
{
}
public override void Translate(float x, float y)
{
}
protected override void DrawResult(Graphics g)
{
}
}
public interface IEventHandle
{
void OnMouseMove(PointF p);
void OnMouseDown(PointF p);
void OnMouseUp(PointF p);
void OnMouseDoubleClick(PointF p);
void OnKeyDown(object sender, KeyEventArgs e);
void OnKeyUp(object sender, KeyEventArgs e);
}
public class ElementIndexCompare : IComparer<ElementBase>
{
public int Compare(ElementBase x, ElementBase y)
{
return x.Index - y.Index;
}
}
}