MoveNubRenderer.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. using PaintDotNet.SystemLayer;
  2. using System;
  3. using System.Drawing;
  4. using System.Drawing.Drawing2D;
  5. namespace PaintDotNet.Measurement
  6. {
  7. public class MoveNubRenderer : CanvasControl
  8. {
  9. private Matrix transform;
  10. private float transformAngle;
  11. private int alpha;
  12. private MoveNubShape shape;
  13. public MoveNubShape Shape
  14. {
  15. get
  16. {
  17. return this.shape;
  18. }
  19. set
  20. {
  21. InvalidateOurself();
  22. this.shape = value;
  23. InvalidateOurself();
  24. }
  25. }
  26. protected override void OnLocationChanging()
  27. {
  28. InvalidateOurself();
  29. base.OnLocationChanging();
  30. }
  31. protected override void OnLocationChanged()
  32. {
  33. InvalidateOurself();
  34. base.OnLocationChanged();
  35. }
  36. protected override void OnSizeChanging()
  37. {
  38. InvalidateOurself();
  39. base.OnSizeChanging();
  40. }
  41. protected override void OnSizeChanged()
  42. {
  43. InvalidateOurself();
  44. base.OnSizeChanged();
  45. }
  46. public Matrix Transform
  47. {
  48. get
  49. {
  50. return this.transform.Clone();
  51. }
  52. set
  53. {
  54. InvalidateOurself();
  55. if (value == null)
  56. {
  57. throw new ArgumentNullException();
  58. }
  59. if (this.transform != null)
  60. {
  61. this.transform.Dispose();
  62. this.transform = null;
  63. }
  64. this.transform = value.Clone();
  65. this.transformAngle = Utility.GetAngleOfTransform(this.transform);
  66. InvalidateOurself();
  67. }
  68. }
  69. public int Alpha
  70. {
  71. get
  72. {
  73. return this.alpha;
  74. }
  75. set
  76. {
  77. if (value < 0 || value > 255)
  78. {
  79. throw new ArgumentOutOfRangeException("value", value, "value must be [0, 255]");
  80. }
  81. if (this.alpha != value)
  82. {
  83. this.alpha = value;
  84. InvalidateOurself();
  85. }
  86. }
  87. }
  88. private RectangleF GetOurRectangle()
  89. {
  90. PointF[] ptFs = new PointF[1] { this.Location };
  91. this.transform.TransformPoints(ptFs);
  92. float ratio = (float)Math.Ceiling(1.0 / OwnerList.ScaleFactor.Ratio);
  93. float ourWidth = UI.ScaleWidth(this.Size.Width);
  94. float ourHeight = UI.ScaleHeight(this.Size.Height);
  95. if (!Single.IsNaN(ratio))
  96. {
  97. RectangleF rectF = new RectangleF(ptFs[0], new SizeF(0, 0));
  98. rectF.Inflate(ratio * ourWidth, ratio * ourHeight);
  99. return rectF;
  100. }
  101. else
  102. {
  103. return RectangleF.Empty;
  104. }
  105. }
  106. private void InvalidateOurself()
  107. {
  108. InvalidateOurself(false);
  109. }
  110. private void InvalidateOurself(bool force)
  111. {
  112. if (this.Visible || force)
  113. {
  114. RectangleF rectF = GetOurRectangle();
  115. Rectangle rect = Utility.RoundRectangle(rectF);
  116. rect.Inflate(1, 1);
  117. Invalidate(rect);
  118. }
  119. }
  120. public bool IsPointTouching(PointF ptF, bool pad)
  121. {
  122. RectangleF rectF = GetOurRectangle();
  123. if (pad)
  124. {
  125. float padding = 2.0f * 1.0f / (float)this.OwnerList.ScaleFactor.Ratio;
  126. rectF.Inflate(padding + 1.0f, padding + 1.0f);
  127. }
  128. return rectF.Contains(ptF);
  129. }
  130. public bool IsPointTouching(Point pt, bool pad)
  131. {
  132. RectangleF rectF = GetOurRectangle();
  133. if (pad)
  134. {
  135. float padding = 2.0f * 1.0f / (float)this.OwnerList.ScaleFactor.Ratio;
  136. rectF.Inflate(padding + 1.0f, padding + 1.0f);
  137. }
  138. return pt.X >= rectF.Left && pt.Y >= rectF.Top && pt.X < rectF.Right && pt.Y < rectF.Bottom;
  139. }
  140. protected override void OnVisibleChanged()
  141. {
  142. InvalidateOurself(true);
  143. }
  144. protected override void OnRender(Graphics g, Point offset)
  145. {
  146. lock (this)
  147. {
  148. float ourSize = UI.ScaleWidth(Math.Min(Width, Height));
  149. g.SmoothingMode = SmoothingMode.AntiAlias;
  150. g.TranslateTransform(-offset.X, -offset.Y, MatrixOrder.Append);
  151. PointF ptF = (PointF)this.Location;
  152. ptF = Utility.TransformOnePoint(this.transform, ptF);
  153. ptF.X *= (float)OwnerList.ScaleFactor.Ratio;
  154. ptF.Y *= (float)OwnerList.ScaleFactor.Ratio;
  155. PointF[] pts = new PointF[8]
  156. {
  157. new PointF(-1, -1), // up+left
  158. new PointF(+1, -1), // up+right
  159. new PointF(+1, +1), // down+right
  160. new PointF(-1, +1), // down+left
  161. new PointF(-1, 0), // left
  162. new PointF(+1, 0), // right
  163. new PointF(0, -1), // up
  164. new PointF(0, +1) // down
  165. };
  166. Utility.RotateVectors(pts, this.transformAngle);
  167. Utility.NormalizeVectors(pts);
  168. using (Pen white = new Pen(Color.FromArgb(this.alpha, Color.White), -1.0f),
  169. black = new Pen(Color.FromArgb(this.alpha, Color.Black), -1.0f))
  170. {
  171. PixelOffsetMode oldPOM = g.PixelOffsetMode;
  172. g.PixelOffsetMode = PixelOffsetMode.None;
  173. if (this.shape != MoveNubShape.Circle)
  174. {
  175. PointF[] outer = new PointF[4]
  176. {
  177. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize)),
  178. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize)),
  179. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize)),
  180. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize))
  181. };
  182. PointF[] middle = new PointF[4]
  183. {
  184. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize - 1)),
  185. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize - 1)),
  186. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize - 1)),
  187. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize - 1))
  188. };
  189. PointF[] inner = new PointF[4]
  190. {
  191. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize - 2)),
  192. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize - 2)),
  193. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize - 2)),
  194. Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize - 2))
  195. };
  196. g.DrawPolygon(white, outer);
  197. g.DrawPolygon(black, middle);
  198. g.DrawPolygon(white, inner);
  199. }
  200. else if (this.shape == MoveNubShape.Circle)
  201. {
  202. RectangleF rect = new RectangleF(ptF, new SizeF(0, 0));
  203. rect.Inflate(ourSize - 1, ourSize - 1);
  204. g.DrawEllipse(white, rect);
  205. rect.Inflate(-1.0f, -1.0f);
  206. g.DrawEllipse(black, rect);
  207. rect.Inflate(-1.0f, -1.0f);
  208. g.DrawEllipse(white, rect);
  209. }
  210. if (this.shape == MoveNubShape.Compass)
  211. {
  212. black.SetLineCap(LineCap.Round, LineCap.DiamondAnchor, DashCap.Flat);
  213. black.EndCap = LineCap.ArrowAnchor;
  214. black.StartCap = LineCap.ArrowAnchor;
  215. white.SetLineCap(LineCap.Round, LineCap.DiamondAnchor, DashCap.Flat);
  216. white.EndCap = LineCap.ArrowAnchor;
  217. white.StartCap = LineCap.ArrowAnchor;
  218. PointF ul = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[0], ourSize - 1));
  219. PointF ur = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[1], ourSize - 1));
  220. PointF lr = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[2], ourSize - 1));
  221. PointF ll = Utility.AddVectors(ptF, Utility.MultiplyVector(pts[3], ourSize - 1));
  222. PointF top = Utility.MultiplyVector(Utility.AddVectors(ul, ur), 0.5f);
  223. PointF left = Utility.MultiplyVector(Utility.AddVectors(ul, ll), 0.5f);
  224. PointF right = Utility.MultiplyVector(Utility.AddVectors(ur, lr), 0.5f);
  225. PointF bottom = Utility.MultiplyVector(Utility.AddVectors(ll, lr), 0.5f);
  226. using (SolidBrush whiteBrush = new SolidBrush(white.Color))
  227. {
  228. PointF[] poly = new PointF[] { ul, ur, lr, ll };
  229. g.FillPolygon(whiteBrush, poly, FillMode.Winding);
  230. }
  231. g.DrawLine(black, top, bottom);
  232. g.DrawLine(black, left, right);
  233. }
  234. g.PixelOffsetMode = oldPOM;
  235. }
  236. }
  237. }
  238. public MoveNubRenderer(SurfaceBoxRendererList ownerList)
  239. : base(ownerList)
  240. {
  241. this.shape = MoveNubShape.Square;
  242. this.transform = new Matrix();
  243. this.transform.Reset();
  244. this.alpha = 255;
  245. Size = new SizeF(5, 5);
  246. }
  247. }
  248. }