using Bro.Common.Helper; using Bro.Common.Interface; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Runtime.CompilerServices; using System.Windows.Forms; using static Bro.Common.Helper.EnumHelper; namespace Bro.UI.Model.Winform { [Serializable] public abstract class ElementBase : IShapeElement, IEventHandle, ICloneable, IComplexDisplay, IComparable, IDisposable { #region 常量 protected int _mouseIntersectDistance = 4; #endregion #region 标识符 /// /// ID,采用GUID /// [ReadOnly(true)] [Category("通用标识")] [Description("GUID")] public virtual string ID { get; set; } = Guid.NewGuid().ToString().ToUpper(); /// /// 序号 /// [Category("通用标识")] [Description("序号")] public virtual int Index { get; set; } = 0; /// /// 名称 /// [Category("通用标识")] [Description("名称")] public virtual string Name { get; set; } #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 Point _startPoint, _currentPoint; #endregion #region 绘图特性 [JsonIgnore] [Browsable(false)] public NoticedPoints DrawPoints { get; set; } = new NoticedPoints(); protected int DrawPointCount { get; set; } //protected Region Region { get; set; } #region 画笔相关 #region 绘图画笔 [JsonIgnore] [Browsable(false)] protected Pen Pen { get; set; } = new Pen(Color.Red, 1); 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 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; state = value; EventRouter.ChangeElementsMouseState?.Invoke(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; } } } } /// /// 是否是运行模式 /// [Browsable(false)] public RunMode RunMode { get; set; } = RunMode.SetMode; #endregion #region 复制 public abstract object Clone(); public virtual void Initial() { DrawPoints = new NoticedPoints(); } #endregion #region IMouseEvent public virtual void OnMouseDoubleClick(Point 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; } } } public abstract void OnKeyDown(object sender, KeyEventArgs e); public abstract void OnKeyUp(object sender, KeyEventArgs e); public virtual void OnMouseDown(Point 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; } } public virtual void OnMouseMove(Point p) { switch (State) { case ElementState.New: OnMouseMoveWhenNew(p); break; case ElementState.Selected: break; case ElementState.Moving: _currentPoint = p; Translate(_currentPoint.X - _startPoint.X, _currentPoint.Y - _startPoint.Y); _startPoint = _currentPoint; 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; } } public virtual void OnMouseUp(Point p) { switch (State) { case ElementState.Moving: //Calculate(null); State = ElementState.Selected; break; case ElementState.Selected: //Calculate(null); break; default: break; } } #region 当基元状态为新建或可编辑时的鼠标操作动作 /// /// 当状态为New时的鼠标按下操作 /// /// public abstract void OnMouseDownWhenNew(Point p); public abstract void OnMouseMoveWhenNew(Point p); public abstract void OnMouseUpWhenNew(Point 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; } public abstract bool IsMouseHover(Point p); public abstract bool IsMouseInSide(Point p); public abstract bool IsIntersect(Rectangle rect); public abstract void CalculateBaseRectangle(); #endregion #region 变形操作 public abstract void Translate(int x, int y); //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 abstract void Calculate(Bitmap image); public abstract void Calculate(IntPtr imagePtr, int ptrSize, int imageWidth, int imageHeight); public abstract 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); } } #endregion 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 } public interface IEventHandle { void OnMouseMove(Point p); void OnMouseDown(Point p); void OnMouseUp(Point p); void OnMouseDoubleClick(Point 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; } } }