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

981 lines
30 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}