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, IDisposable { #region 常量 protected int _mouseIntersectDistance = 4; #endregion #region 标识符 /// /// ID,采用GUID /// [ReadOnly(true)] [Category("\t通用标识")] [Description("GUID")] public virtual string ID { get; set; } = Guid.NewGuid().ToString().ToUpper(); /// /// 序号 /// [Category("\t通用标识")] [Description("序号")] public virtual int Index { get; set; } = 0; [Browsable(false)] public virtual int GroupIndex { get; set; } = 0; private string name = ""; /// /// 名称 /// [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); ///// ///// 字体大小 ///// //[Category("显示属性")] //[Description("字体大小")] ////[Browsable(false)] //public virtual float FontSize { get; set; } = 15; /// /// 字体大小 /// [Category("显示属性")] [Description("字体设置")] [Browsable(false)] public virtual Font Font { get; set; } = new Font(new FontFamily("Tahoma"), 15, GraphicsUnit.World); /// /// 字体和基元的距离 /// [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; } } } } /// /// 是否是运行模式 /// [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 当基元状态为新建或可编辑时的鼠标操作动作 /// /// 当状态为New时的鼠标按下操作 /// /// public abstract void OnMouseDownWhenNew(PointF p); public abstract void OnMouseMoveWhenNew(PointF p); public abstract void OnMouseUpWhenNew(PointF p); #endregion #endregion #region 委托事件 [JsonIgnore] public Action OnDrawDone; [JsonIgnore] public Action OnMeasureDone; [JsonIgnore] public Action OnElementEnableChanged; #endregion #region 几何特性 /// /// 基类基础的Rectangle 用于计算MouseHover和Inside等 /// [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 算法 /// /// 算法 /// /// 计算参数 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(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 { public int Compare(ElementBase x, ElementBase y) { return x.Index - y.Index; } } }