DrawRoundRectangle.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. using PaintDotNet.Annotation.Enum;
  2. using PaintDotNet.Base.SettingModel;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Diagnostics;
  6. using System.Drawing;
  7. using System.Drawing.Drawing2D;
  8. using System.Globalization;
  9. using System.Runtime.Serialization;
  10. using System.Windows.Forms;
  11. namespace PaintDotNet.Annotation.Label
  12. {
  13. /// <summary>
  14. /// 标注->圆角矩形
  15. /// </summary>
  16. public class DrawRoundRectangle : DrawObject
  17. {
  18. private const string entryRectangle = "Rect";
  19. /// <summary>
  20. /// 标注样式信息model
  21. /// </summary>
  22. public LabelStyleModel.RoundedRectangle labelRoundedRectStyleModel;
  23. // 圆角半径
  24. private int radius = 10;
  25. public DrawRoundRectangle(ISurfaceBox surfaceBox, int x, int y, int width, int height) : base()
  26. {
  27. this.objectType = DrawClass.Label;
  28. this.drawToolType = DrawToolType.DrawRoundRectangle;
  29. labelRoundedRectStyleModel = surfaceBox.GetLabelStyleModel().roundedRectangle;
  30. rectangle.X = x;
  31. rectangle.Y = y;
  32. rectangle.Width = width;
  33. rectangle.Height = height;
  34. Initialize();
  35. }
  36. public DrawRoundRectangle(ISurfaceBox surfaceBox, List<PointF> points, ParentStyleModel parentStyleModel, Object content) : base()
  37. {
  38. this.objectType = DrawClass.Label;
  39. this.drawToolType = DrawToolType.DrawRoundRectangle;
  40. this.ISurfaceBox = surfaceBox;
  41. labelRoundedRectStyleModel = (LabelStyleModel.RoundedRectangle)parentStyleModel;
  42. rectangle.X = points[0].X;
  43. rectangle.Y = points[0].Y;
  44. rectangle.Width = points[1].X - points[0].X;
  45. rectangle.Height = points[1].Y - points[0].Y;
  46. }
  47. /// <summary>
  48. /// Clone this instance
  49. /// </summary>
  50. public override DrawObject Clone()
  51. {
  52. DrawRoundRectangle drawRoundRectangle = new DrawRoundRectangle(ISurfaceBox, 0, 0, 1, 0);
  53. drawRoundRectangle.objectType = DrawClass.Label;
  54. drawRoundRectangle.drawToolType = DrawToolType.DrawRoundRectangle;
  55. drawRoundRectangle.ISurfaceBox = this.ISurfaceBox;
  56. drawRoundRectangle.rectangle = this.rectangle;
  57. FillDrawObjectFields(drawRoundRectangle);
  58. return drawRoundRectangle;
  59. }
  60. public override DrawObject Clone(ISurfaceBox surfaceBox)
  61. {
  62. DrawRoundRectangle drawRoundRectangle = new DrawRoundRectangle(surfaceBox, 0, 0, 1, 0);
  63. drawRoundRectangle.objectType = DrawClass.Label;
  64. drawRoundRectangle.drawToolType = DrawToolType.DrawRoundRectangle;
  65. drawRoundRectangle.ISurfaceBox = surfaceBox;
  66. drawRoundRectangle.rectangle = this.rectangle;
  67. drawRoundRectangle.labelRoundedRectStyleModel = this.labelRoundedRectStyleModel;
  68. FillDrawObjectFields(drawRoundRectangle);
  69. return drawRoundRectangle;
  70. }
  71. /// <summary>
  72. /// Draw rectangle
  73. /// </summary>
  74. /// <param name="g"></param>
  75. public override void Draw(Graphics g)
  76. {
  77. Color color = Color.FromArgb(this.labelRoundedRectStyleModel.lineColor);
  78. Pen pen = new Pen(color, PenWidth);
  79. int penWidth = this.labelRoundedRectStyleModel.lineWidth;
  80. pen.DashStyle = (DashStyle)this.labelRoundedRectStyleModel.lineStyle;
  81. pen.Width = penWidth;
  82. Color fillColor = Color.FromArgb(this.labelRoundedRectStyleModel.fillColor);
  83. SolidBrush fillBrush = new SolidBrush(fillColor);
  84. Rectangle panel4 = DrawRectangle.GetNormalizedRectangle(Rectangle);
  85. //计算圆角半径,以短的一边为准
  86. if (panel4.Width > panel4.Height)
  87. radius = Convert.ToInt32(Math.Ceiling(panel4.Height * (this.labelRoundedRectStyleModel.roundAngle / 100)));
  88. else
  89. radius = Convert.ToInt32(Math.Ceiling(panel4.Width * (this.labelRoundedRectStyleModel.roundAngle / 100)));
  90. if (radius == 0)
  91. radius = 1;
  92. // 要实现 圆角化的 矩形
  93. Rectangle rect = new Rectangle(panel4.X, panel4.Y, panel4.Width - radius, panel4.Height - radius);
  94. // 指定图形路径, 有一系列 直线/曲线 组成
  95. GraphicsPath myPath = new GraphicsPath();
  96. myPath.StartFigure();
  97. myPath.AddArc(new Rectangle(new Point(rect.X, rect.Y), new Size(2 * radius, 2 * radius)), 180, 90);
  98. myPath.AddLine(new Point(rect.X + radius, rect.Y), new Point(rect.Right - radius, rect.Y));
  99. myPath.AddArc(new Rectangle(new Point(rect.Right - 2 * radius, rect.Y), new Size(2 * radius, 2 * radius)), 270, 90);
  100. myPath.AddLine(new Point(rect.Right, rect.Y + radius), new Point(rect.Right, rect.Bottom - radius));
  101. myPath.AddArc(new Rectangle(new Point(rect.Right - 2 * radius, rect.Bottom - 2 * radius), new Size(2 * radius, 2 * radius)), 0, 90);
  102. myPath.AddLine(new Point(rect.Right - radius, rect.Bottom), new Point(rect.X + radius, rect.Bottom));
  103. myPath.AddArc(new Rectangle(new Point(rect.X, rect.Bottom - 2 * radius), new Size(2 * radius, 2 * radius)), 90, 90);
  104. myPath.AddLine(new Point(rect.X, rect.Bottom - radius), new Point(rect.X, rect.Y + radius));
  105. myPath.CloseFigure();
  106. g.DrawPath(pen, myPath);
  107. g.FillPath(fillBrush, myPath);
  108. //g.DrawRectangle(pen, DrawRectangle.GetNormalizedRectangle(Rectangle));
  109. //pen.Dispose();
  110. }
  111. protected void SetRectangle(float x, float y, float width, float height)
  112. {
  113. rectangle.X = x;
  114. rectangle.Y = y;
  115. rectangle.Width = width;
  116. rectangle.Height = height;
  117. }
  118. /// <summary>
  119. /// Get number of handles
  120. /// </summary>
  121. public override int HandleCount
  122. {
  123. get
  124. {
  125. return 8;
  126. }
  127. }
  128. /// <summary>
  129. /// Get handle pointscroll by 1-based number
  130. /// </summary>
  131. /// <param name="handleNumber"></param>
  132. /// <returns></returns>
  133. public override PointF GetHandle(int handleNumber)
  134. {
  135. float x, y, xCenter, yCenter;
  136. xCenter = rectangle.X + rectangle.Width / 2;
  137. yCenter = rectangle.Y + rectangle.Height / 2;
  138. x = rectangle.X;
  139. y = rectangle.Y;
  140. switch (handleNumber)
  141. {
  142. case 1:
  143. x = rectangle.X;
  144. y = rectangle.Y;
  145. break;
  146. case 2:
  147. x = xCenter;
  148. y = rectangle.Y;
  149. break;
  150. case 3:
  151. x = rectangle.Right;
  152. y = rectangle.Y;
  153. break;
  154. case 4:
  155. x = rectangle.Right;
  156. y = yCenter;
  157. break;
  158. case 5:
  159. x = rectangle.Right;
  160. y = rectangle.Bottom;
  161. break;
  162. case 6:
  163. x = xCenter;
  164. y = rectangle.Bottom;
  165. break;
  166. case 7:
  167. x = rectangle.X;
  168. y = rectangle.Bottom;
  169. break;
  170. case 8:
  171. x = rectangle.X;
  172. y = yCenter;
  173. break;
  174. }
  175. return new PointF(x, y);
  176. }
  177. /// <summary>
  178. /// Hit test.
  179. /// Return value: -1 - no hit
  180. /// 0 - hit anywhere
  181. /// > 1 - handle number
  182. /// </summary>
  183. /// <param name="pointscroll"></param>
  184. /// <returns></returns>
  185. public override int HitTest(Point point)
  186. {
  187. if (Selected)
  188. {
  189. for (int i = 1; i <= HandleCount; i++)
  190. {
  191. if (GetHandleRectangle(i).Contains(point))
  192. return i;
  193. }
  194. }
  195. if (PointInObject(point))
  196. return 0;
  197. return -1;
  198. }
  199. protected override bool PointInObject(Point point)
  200. {
  201. return rectangle.Contains(point);
  202. }
  203. /// <summary>
  204. /// Get cursor for the handle
  205. /// </summary>
  206. /// <param name="handleNumber"></param>
  207. /// <returns></returns>
  208. public override Cursor GetHandleCursor(int handleNumber)
  209. {
  210. switch (handleNumber)
  211. {
  212. case 1:
  213. return Cursors.SizeNWSE;
  214. case 2:
  215. return Cursors.SizeNS;
  216. case 3:
  217. return Cursors.SizeNESW;
  218. case 4:
  219. return Cursors.SizeWE;
  220. case 5:
  221. return Cursors.SizeNWSE;
  222. case 6:
  223. return Cursors.SizeNS;
  224. case 7:
  225. return Cursors.SizeNESW;
  226. case 8:
  227. return Cursors.SizeWE;
  228. default:
  229. return Cursors.Default;
  230. }
  231. }
  232. /// <summary>
  233. /// Move handle to new pointscroll (resizing)
  234. /// </summary>
  235. /// <param name="pointscroll"></param>
  236. /// <param name="handleNumber"></param>
  237. public override void MoveHandleTo(Point point, int handleNumber)
  238. {
  239. float left = Rectangle.Left;
  240. float top = Rectangle.Top;
  241. float right = Rectangle.Right;
  242. float bottom = Rectangle.Bottom;
  243. switch (handleNumber)
  244. {
  245. case 1:
  246. left = point.X;
  247. top = point.Y;
  248. break;
  249. case 2:
  250. top = point.Y;
  251. break;
  252. case 3:
  253. right = point.X;
  254. top = point.Y;
  255. break;
  256. case 4:
  257. right = point.X;
  258. break;
  259. case 5:
  260. right = point.X;
  261. bottom = point.Y;
  262. break;
  263. case 6:
  264. bottom = point.Y;
  265. break;
  266. case 7:
  267. left = point.X;
  268. bottom = point.Y;
  269. break;
  270. case 8:
  271. left = point.X;
  272. break;
  273. }
  274. SetRectangle(left, top, right - left, bottom - top);
  275. }
  276. public override bool IntersectsWith(Rectangle rectangle)
  277. {
  278. return Rectangle.IntersectsWith(rectangle);
  279. }
  280. /// <summary>
  281. /// Move object
  282. /// </summary>
  283. /// <param name="deltaX"></param>
  284. /// <param name="deltaY"></param>
  285. public override void Move(int deltaX, int deltaY)
  286. {
  287. int x = ISurfaceBox.UnscaleScalar(deltaX);
  288. int y = ISurfaceBox.UnscaleScalar(deltaY);
  289. rectangle.X += x;
  290. rectangle.Y += y;
  291. }
  292. public override void Dump()
  293. {
  294. base.Dump();
  295. Trace.WriteLine("rectangle.X = " + rectangle.X.ToString(CultureInfo.InvariantCulture));
  296. Trace.WriteLine("rectangle.Y = " + rectangle.Y.ToString(CultureInfo.InvariantCulture));
  297. Trace.WriteLine("rectangle.Width = " + rectangle.Width.ToString(CultureInfo.InvariantCulture));
  298. Trace.WriteLine("rectangle.Height = " + rectangle.Height.ToString(CultureInfo.InvariantCulture));
  299. }
  300. /// <summary>
  301. /// Normalize rectangle
  302. /// </summary>
  303. public override void Normalize()
  304. {
  305. rectangle = DrawRectangle.GetNormalizedRectangle(rectangle);
  306. }
  307. /// <summary>
  308. /// Save objevt to serialization stream
  309. /// </summary>
  310. /// <param name="info"></param>
  311. /// <param name="orderNumber"></param>
  312. public override void SaveToStream(System.Runtime.Serialization.SerializationInfo info, int orderNumber)
  313. {
  314. info.AddValue(
  315. String.Format(CultureInfo.InvariantCulture,
  316. "{0}{1}",
  317. entryRectangle, orderNumber),
  318. rectangle);
  319. base.SaveToStream(info, orderNumber);
  320. }
  321. /// <summary>
  322. /// LOad object from serialization stream
  323. /// </summary>
  324. /// <param name="info"></param>
  325. /// <param name="orderNumber"></param>
  326. public override void LoadFromStream(SerializationInfo info, int orderNumber)
  327. {
  328. rectangle = (Rectangle)info.GetValue(
  329. String.Format(CultureInfo.InvariantCulture,
  330. "{0}{1}",
  331. entryRectangle, orderNumber),
  332. typeof(Rectangle));
  333. base.LoadFromStream(info, orderNumber);
  334. }
  335. #region Helper Functions
  336. public static Rectangle GetNormalizedRectangle(int x1, int y1, int x2, int y2)
  337. {
  338. if (x2 < x1)
  339. {
  340. int tmp = x2;
  341. x2 = x1;
  342. x1 = tmp;
  343. }
  344. if (y2 < y1)
  345. {
  346. int tmp = y2;
  347. y2 = y1;
  348. y1 = tmp;
  349. }
  350. return new Rectangle(x1, y1, x2 - x1, y2 - y1);
  351. }
  352. public static Rectangle GetNormalizedRectangle(Point p1, Point p2)
  353. {
  354. return GetNormalizedRectangle(p1.X, p1.Y, p2.X, p2.Y);
  355. }
  356. public static Rectangle GetNormalizedRectangle(Rectangle r)
  357. {
  358. return GetNormalizedRectangle(r.X, r.Y, r.X + r.Width, r.Y + r.Height);
  359. }
  360. #endregion
  361. public override RectangleF GetBoundingBox()
  362. {
  363. return rectangle;
  364. }
  365. public override List<PointF> GetPoints()
  366. {
  367. List<PointF> points = new List<PointF>();
  368. points.Add(new PointF(rectangle.X, rectangle.Y));
  369. points.Add(new PointF(rectangle.Right, rectangle.Bottom));
  370. return points;
  371. }
  372. public override ParentStyleModel GetStyle()
  373. {
  374. return labelRoundedRectStyleModel;
  375. }
  376. }
  377. }