| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 | using PaintDotNet.SystemLayer;using System;using System.Drawing;using System.Drawing.Drawing2D;namespace PaintDotNet.Measurement{    public class MoveNubRenderer : CanvasControl    {        private Matrix transform;        private float transformAngle;        private int alpha;        private MoveNubShape shape;        public MoveNubShape Shape        {            get            {                return this.shape;            }            set            {                InvalidateOurself();                this.shape = value;                InvalidateOurself();            }        }        protected override void OnLocationChanging()        {            InvalidateOurself();            base.OnLocationChanging();        }        protected override void OnLocationChanged()        {            InvalidateOurself();            base.OnLocationChanged();        }        protected override void OnSizeChanging()        {            InvalidateOurself();            base.OnSizeChanging();        }        protected override void OnSizeChanged()        {            InvalidateOurself();            base.OnSizeChanged();        }        public Matrix Transform        {            get            {                return this.transform.Clone();            }            set            {                InvalidateOurself();                if (value == null)                {                    throw new ArgumentNullException();                }                if (this.transform != null)                {                    this.transform.Dispose();                    this.transform = null;                }                this.transform = value.Clone();                this.transformAngle = Utility.GetAngleOfTransform(this.transform);                InvalidateOurself();            }        }        public int Alpha        {            get            {                return this.alpha;            }            set            {                if (value < 0 || value > 255)                {                    throw new ArgumentOutOfRangeException("value", value, "value must be [0, 255]");                }                if (this.alpha != value)                {                    this.alpha = value;                    InvalidateOurself();                }            }        }        private RectangleF GetOurRectangle()        {            PointF[] ptFs = new PointF[1] { this.Location };            this.transform.TransformPoints(ptFs);            float ratio = (float)Math.Ceiling(1.0 / OwnerList.ScaleFactor.Ratio);            float ourWidth = UI.ScaleWidth(this.Size.Width);            float ourHeight = UI.ScaleHeight(this.Size.Height);            if (!Single.IsNaN(ratio))            {                RectangleF rectF = new RectangleF(ptFs[0], new SizeF(0, 0));                rectF.Inflate(ratio * ourWidth, ratio * ourHeight);                return rectF;            }            else            {                return RectangleF.Empty;            }        }        private void InvalidateOurself()        {            InvalidateOurself(false);        }        private void InvalidateOurself(bool force)        {            if (this.Visible || force)            {                RectangleF rectF = GetOurRectangle();                Rectangle rect = Utility.RoundRectangle(rectF);                rect.Inflate(1, 1);                Invalidate(rect);            }        }        public bool IsPointTouching(PointF ptF, bool pad)        {            RectangleF rectF = GetOurRectangle();            if (pad)            {                float padding = 2.0f * 1.0f / (float)this.OwnerList.ScaleFactor.Ratio;                rectF.Inflate(padding + 1.0f, padding + 1.0f);            }            return rectF.Contains(ptF);        }        public bool IsPointTouching(Point pt, bool pad)        {            RectangleF rectF = GetOurRectangle();            if (pad)            {                float padding = 2.0f * 1.0f / (float)this.OwnerList.ScaleFactor.Ratio;                rectF.Inflate(padding + 1.0f, padding + 1.0f);            }            return pt.X >= rectF.Left && pt.Y >= rectF.Top && pt.X < rectF.Right && pt.Y < rectF.Bottom;        }        protected override void OnVisibleChanged()        {            InvalidateOurself(true);        }        protected override void OnRender(Graphics g, Point offset)        {            lock (this)            {                float ourSize = UI.ScaleWidth(Math.Min(Width, Height));                g.SmoothingMode = SmoothingMode.AntiAlias;                g.TranslateTransform(-offset.X, -offset.Y, MatrixOrder.Append);                PointF ptF = (PointF)this.Location;                ptF = Utility.TransformOnePoint(this.transform, ptF);                ptF.X *= (float)OwnerList.ScaleFactor.Ratio;                ptF.Y *= (float)OwnerList.ScaleFactor.Ratio;                PointF[] pts = new PointF[8]                                         {                                             new PointF(-1, -1), // up+left                                             new PointF(+1, -1), // up+right                                             new PointF(+1, +1), // down+right                                             new PointF(-1, +1), // down+left                                             new PointF(-1, 0),  // left                                             new PointF(+1, 0),  // right                                             new PointF(0, -1),  // up                                             new PointF(0, +1)   // down                                         };                Utility.RotateVectors(pts, this.transformAngle);                Utility.NormalizeVectors(pts);                using (Pen white = new Pen(Color.FromArgb(this.alpha, Color.White), -1.0f),                           black = new Pen(Color.FromArgb(this.alpha, Color.Black), -1.0f))                {                    PixelOffsetMode oldPOM = g.PixelOffsetMode;                    g.PixelOffsetMode = PixelOffsetMode.None;                    if (this.shape != MoveNubShape.Circle)                    {                        PointF[] outer = new PointF[4]                        {                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize))                        };                        PointF[] middle = new PointF[4]                        {                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize - 1)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize - 1)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize - 1)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize - 1))                        };                        PointF[] inner = new PointF[4]                        {                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize - 2)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize - 2)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize - 2)),                            Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize - 2))                        };                        g.DrawPolygon(white, outer);                        g.DrawPolygon(black, middle);                        g.DrawPolygon(white, inner);                    }                    else if (this.shape == MoveNubShape.Circle)                    {                        RectangleF rect = new RectangleF(ptF, new SizeF(0, 0));                        rect.Inflate(ourSize - 1, ourSize - 1);                        g.DrawEllipse(white, rect);                        rect.Inflate(-1.0f, -1.0f);                        g.DrawEllipse(black, rect);                        rect.Inflate(-1.0f, -1.0f);                        g.DrawEllipse(white, rect);                    }                    if (this.shape == MoveNubShape.Compass)                    {                        black.SetLineCap(LineCap.Round, LineCap.DiamondAnchor, DashCap.Flat);                        black.EndCap = LineCap.ArrowAnchor;                        black.StartCap = LineCap.ArrowAnchor;                        white.SetLineCap(LineCap.Round, LineCap.DiamondAnchor, DashCap.Flat);                        white.EndCap = LineCap.ArrowAnchor;                        white.StartCap = LineCap.ArrowAnchor;                        PointF ul = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize - 1));                        PointF ur = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize - 1));                        PointF lr = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize - 1));                        PointF ll = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize - 1));                        PointF top = Utility.MultiplyVector(Utility.AddVectors(ul, ur), 0.5f);                        PointF left = Utility.MultiplyVector(Utility.AddVectors(ul, ll), 0.5f);                        PointF right = Utility.MultiplyVector(Utility.AddVectors(ur, lr), 0.5f);                        PointF bottom = Utility.MultiplyVector(Utility.AddVectors(ll, lr), 0.5f);                        using (SolidBrush whiteBrush = new SolidBrush(white.Color))                        {                            PointF[] poly = new PointF[] { ul, ur, lr, ll };                            g.FillPolygon(whiteBrush, poly, FillMode.Winding);                        }                        g.DrawLine(black, top, bottom);                        g.DrawLine(black, left, right);                    }                    g.PixelOffsetMode = oldPOM;                }            }        }        public MoveNubRenderer(SurfaceBoxRendererList ownerList)            : base(ownerList)        {            this.shape = MoveNubShape.Square;            this.transform = new Matrix();            this.transform.Reset();            this.alpha = 255;            Size = new SizeF(5, 5);        }    }}
 |