using Pilz.Drawing; using System.Runtime.CompilerServices; namespace Pilz.UI.WinForms.PaintingControl; [Serializable] internal class PaintingObjectResizing { public static event CheckEnabledEventHandler CheckEnabled; public delegate void CheckEnabledEventHandler(PaintingObjectResizing sender, ref bool enabled); private PaintingObject _mObj; private PaintingObject mObj { [MethodImpl(MethodImplOptions.Synchronized)] get { return _mObj; } [MethodImpl(MethodImplOptions.Synchronized)] set { if (_mObj != null) { _mObj.MouseDown -= mControl_MouseDown; _mObj.MouseUp -= mControl_MouseUp; _mObj.Paint -= mControl_Paint; _mObj.SelectedChanged -= mControl_MouseLeave; _mObj.ParentChanged -= mObj_ParentChanged; } _mObj = value; if (_mObj != null) { _mObj.MouseDown += mControl_MouseDown; _mObj.MouseUp += mControl_MouseUp; _mObj.Paint += mControl_Paint; _mObj.SelectedChanged += mControl_MouseLeave; _mObj.ParentChanged += mObj_ParentChanged; } } } private Control _mObjParent; private Control mObjParent { [MethodImpl(MethodImplOptions.Synchronized)] get { return _mObjParent; } [MethodImpl(MethodImplOptions.Synchronized)] set { _mObjParent = value; } } private Control _mObjControl; private Control mObjControl { [MethodImpl(MethodImplOptions.Synchronized)] get { return _mObjControl; } [MethodImpl(MethodImplOptions.Synchronized)] set { if (_mObjControl != null) { _mObjControl.MouseMove -= mControl_MouseMove; _mObjControl.ParentChanged -= mObjParent_ParentChanged; } _mObjControl = value; if (_mObjControl != null) { _mObjControl.MouseMove += mControl_MouseMove; _mObjControl.ParentChanged += mObjParent_ParentChanged; } } } private bool mMouseDown = false; private EdgeEnum mEdge = EdgeEnum.None; private int mWidth = 4; private int qWidth = 4 * 4; private Rectangle rect = new(); public bool Enabled { get; set; } = true; public SizeF MinimumSize { get; set; } = new SizeF(15f, 15f); [Serializable] private enum EdgeEnum { None, Right, Left, Top, Bottom, TopLeft, TopRight, BottomLeft, BottomRight } public bool IsResizing { get { return mMouseDown && mEdge != EdgeEnum.None; } } public PaintingObject PaintingObject { get { return mObj; } } public PaintingObjectResizing(PaintingObject obj) { mObjParent = null; mObjControl = null; mObj = obj; mObjControl = mObj.Parent; } private bool IsEnabled() { var enabled = Enabled; CheckEnabled?.Invoke(this, ref enabled); return enabled; } private void mControl_MouseDown(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left) mMouseDown = true; } private void mControl_MouseUp(object sender, MouseEventArgs e) { mMouseDown = false; if (mObj.Selected) mObj.AutoArrangeToGrid(); } private void KeepInRange(ref SizeF size) { if (size.Height < MinimumSize.Height || size.Width < MinimumSize.Width) size = new SizeF(Math.Max(size.Width, MinimumSize.Width), Math.Max(size.Height, MinimumSize.Height)); } private void mControl_MouseMove(object sender, MouseEventArgs e) { if (mMouseDown && mEdge != EdgeEnum.None) { var eX = (int)Math.Round(e.X + mObj.Parent.Offset.X); var eY = (int)Math.Round(e.Y + mObj.Parent.Offset.Y); switch (mEdge) { case EdgeEnum.TopLeft: { mObj.SetBounds(eX, eY, (int)Math.Round(mObj.Width + (mObj.Left - eX)), (int)Math.Round(mObj.Height + (mObj.Top - eY))); break; } case EdgeEnum.TopRight: { mObj.SetBounds(mObj.Left, eY, eX - mObj.Left, (int)Math.Round(mObj.Height + (mObj.Top - eY))); break; } case EdgeEnum.BottomRight: { mObj.SetBounds(mObj.Left, mObj.Top, eX - mObj.Left, eY - mObj.Top); break; } case EdgeEnum.BottomLeft: { mObj.SetBounds(eX, mObj.Top, (int)Math.Round(mObj.Width + (mObj.Left - eX)), eY - mObj.Top); break; } case EdgeEnum.Left: { mObj.SetBounds(eX, mObj.Top, (int)Math.Round(mObj.Width + (mObj.Left - eX)), (int)Math.Round(mObj.Height)); break; } case EdgeEnum.Right: { mObj.SetBounds(mObj.Left, mObj.Top, eX - mObj.Left, (int)Math.Round(mObj.Height)); break; } case EdgeEnum.Top: { mObj.SetBounds(mObj.Left, eY, (int)Math.Round(mObj.Width), (int)Math.Round(mObj.Height + (mObj.Top - eY))); break; } case EdgeEnum.Bottom: { mObj.SetBounds(mObj.Left, mObj.Top, (int)Math.Round(mObj.Width), eY - mObj.Top); break; } } var argsize = mObj.Size; KeepInRange(ref argsize); mObj.Size = argsize; } else if (!mMouseDown) { var eXo = e.X; var eYo = e.Y; var realX = (int)Math.Round(eXo + mObj.Parent.Offset.X); var realY = (int)Math.Round(eYo + mObj.Parent.Offset.Y); var eXwo = (int)Math.Round(eXo - mObj.X); var eYwo = (int)Math.Round(eYo - mObj.Y); var eX = (int)Math.Round(eXwo + mObj.Parent.Offset.X); var eY = (int)Math.Round(eYwo + mObj.Parent.Offset.Y); var eLocation = new Point(eX, eY); RectangleF extRect = mObj.RectangleExtended; var oldRect = mObj.Rectangle; var newRect = new RectangleF { X = extRect.X - oldRect.X, Y = extRect.Y - oldRect.Y, Width = (extRect.Width - oldRect.Width) / 2f, Height = (extRect.Height - oldRect.Height) / 2f }; var setToNone = false; var isOnTop = ReferenceEquals(mObj.Parent.GetObject(new PointF(realX, realY), true), mObj); if (IsEnabled() && isOnTop) { switch (true) { case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle((int)Math.Round(newRect.X), (int)Math.Round(newRect.Y), (int)Math.Round(newRect.Width), (int)Math.Round(newRect.Height))): { mObj.Cursor = Cursors.SizeNWSE; mEdge = EdgeEnum.TopLeft; break; } case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle((int)Math.Round(mObj.Width), (int)Math.Round(newRect.Y), (int)Math.Round(newRect.Width), (int)Math.Round(newRect.Height))): { mObj.Cursor = Cursors.SizeNESW; mEdge = EdgeEnum.TopRight; break; } case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle((int)Math.Round(mObj.Width), (int)Math.Round(mObj.Height), (int)Math.Round(newRect.Width), (int)Math.Round(newRect.Height))): { mObj.Cursor = Cursors.SizeNWSE; mEdge = EdgeEnum.BottomRight; break; } case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle((int)Math.Round(newRect.X), (int)Math.Round(mObj.Height), (int)Math.Round(newRect.Width), (int)Math.Round(newRect.Height))): { mObj.Cursor = Cursors.SizeNESW; mEdge = EdgeEnum.BottomLeft; break; } case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle((int)Math.Round(-newRect.Width), 0, (int)Math.Round(newRect.Width), (int)Math.Round(mObj.Height))): { mObj.Cursor = Cursors.SizeWE; mEdge = EdgeEnum.Left; break; } case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle((int)Math.Round(mObj.Width), 0, (int)Math.Round(newRect.Width), (int)Math.Round(mObj.Height))): { mObj.Cursor = Cursors.SizeWE; mEdge = EdgeEnum.Right; break; } case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle(0, (int)Math.Round(-newRect.Height), (int)Math.Round(mObj.Width), (int)Math.Round(newRect.Height))): { mObj.Cursor = Cursors.SizeNS; mEdge = EdgeEnum.Top; break; } case object _ when HelpfulDrawingFunctions.IsPointInRectangle(eLocation, new Rectangle(0, (int)Math.Round(mObj.Height), (int)Math.Round(mObj.Width), (int)Math.Round(newRect.Height))): { mObj.Cursor = Cursors.SizeNS; mEdge = EdgeEnum.Bottom; break; } default: { setToNone = true; break; } } } else { setToNone = true; } if (setToNone) { mObj.Cursor = Cursors.Default; mEdge = EdgeEnum.None; } } } private void mControl_Paint(PaintingObject sender, PaintEventArgs e) { // e.Graphics.FillRectangle(brush, rect) } private void mControl_MouseLeave(PaintingObject sender, EventArgs e) { if (!sender.Selected) mEdge = EdgeEnum.None; } private void mObjParent_ParentChanged(object sender, EventArgs e) { mObjParent = mObjControl.Parent; } private void mObj_ParentChanged(PaintingObject sender, EventArgs e) { mObjControl = mObj.Parent; mObjParent = mObjControl?.Parent; } }