PageRenderTime 63ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/tools/RoundedRectangleTool.cs

https://bitbucket.org/tuldok89/openpdn
C# | 222 lines | 164 code | 35 blank | 23 comment | 14 complexity | da1a4cfb6bfc25bcd2aec5bd665e8849 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Drawing;
  12. using System.Windows.Forms;
  13. using PaintDotNet.Base;
  14. namespace PaintDotNet.Tools
  15. {
  16. internal class RoundedRectangleTool
  17. : ShapeTool
  18. {
  19. private ImageResource _roundedRectangleToolIcon;
  20. private readonly string _statusTextFormat = PdnResources.GetString("RoundedRectangleTool.StatusText.Format");
  21. private Cursor _roundedRectangleCursor;
  22. protected override RectangleF[] GetOptimizedShapeOutlineRegion(PointF[] points, PdnGraphicsPath path)
  23. {
  24. return Utility.SimplifyTrace(path.PathPoints);
  25. }
  26. protected override List<PointF> TrimShapePath(List<PointF> points)
  27. {
  28. var array = new List<PointF>();
  29. if (points.Count > 0)
  30. {
  31. array.Add(points[0]);
  32. if (points.Count > 1)
  33. {
  34. array.Add(points[points.Count - 1]);
  35. }
  36. }
  37. return array;
  38. }
  39. protected override PdnGraphicsPath CreateShapePath(PointF[] points)
  40. {
  41. PointF a = points[0];
  42. PointF b = points[points.Length - 1];
  43. const float radius = 10;
  44. RectangleF rect = (ModifierKeys & Keys.Shift) != 0 ? Utility.PointsToConstrainedRectangle(a, b) : Utility.PointsToRectangle(a, b);
  45. PdnGraphicsPath path = GetRoundedRect(rect, radius);
  46. path.Flatten();
  47. if (path.PathPoints[0] != path.PathPoints[path.PathPoints.Length - 1])
  48. {
  49. path.AddLine(path.PathPoints[0], path.PathPoints[path.PathPoints.Length - 1]);
  50. path.CloseFigure();
  51. }
  52. MeasurementUnit units = AppWorkspace.Units;
  53. double widthPhysical = Math.Abs(Document.PixelToPhysicalX(rect.Width, units));
  54. double heightPhysical = Math.Abs(Document.PixelToPhysicalY(rect.Height, units));
  55. double areaPhysical = widthPhysical * heightPhysical;
  56. string numberFormat;
  57. string unitsAbbreviation;
  58. if (units != MeasurementUnit.Pixel)
  59. {
  60. string unitsAbbreviationName = "MeasurementUnit." + units + ".Abbreviation";
  61. unitsAbbreviation = PdnResources.GetString(unitsAbbreviationName);
  62. numberFormat = "F2";
  63. }
  64. else
  65. {
  66. unitsAbbreviation = string.Empty;
  67. numberFormat = "F0";
  68. }
  69. string unitsString = PdnResources.GetString("MeasurementUnit." + units + ".Plural");
  70. string statusText = string.Format(
  71. _statusTextFormat,
  72. widthPhysical.ToString(numberFormat),
  73. unitsAbbreviation,
  74. heightPhysical.ToString(numberFormat),
  75. unitsAbbreviation,
  76. areaPhysical.ToString(numberFormat),
  77. unitsString);
  78. SetStatus(_roundedRectangleToolIcon, statusText);
  79. return path;
  80. }
  81. protected override void OnActivate()
  82. {
  83. _roundedRectangleCursor = new Cursor(PdnResources.GetResourceStream("Cursors.RoundedRectangleToolCursor.cur"));
  84. Cursor = _roundedRectangleCursor;
  85. _roundedRectangleToolIcon = Image;
  86. base.OnActivate();
  87. }
  88. protected override void OnDeactivate()
  89. {
  90. if (_roundedRectangleCursor != null)
  91. {
  92. _roundedRectangleCursor.Dispose();
  93. _roundedRectangleCursor = null;
  94. }
  95. base.OnDeactivate();
  96. }
  97. public RoundedRectangleTool(DocumentWorkspace documentWorkspace)
  98. : base(documentWorkspace,
  99. PdnResources.GetImageResource("Icons.RoundedRectangleToolIcon.png"),
  100. PdnResources.GetString("RoundedRectangleTool.Name"),
  101. PdnResources.GetString("RoundedRectangleTool.HelpText"))
  102. {
  103. }
  104. // credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp
  105. protected PdnGraphicsPath GetRoundedRect(RectangleF baseRect, float radius)
  106. {
  107. // if corner radius is less than or equal to zero,
  108. // return the original rectangle
  109. if (radius <= 0.0f)
  110. {
  111. var mPath = new PdnGraphicsPath();
  112. mPath.AddRectangle(baseRect);
  113. mPath.CloseFigure();
  114. return mPath;
  115. }
  116. // if the corner radius is greater than or equal to
  117. // half the width, or height (whichever is shorter)
  118. // then return a capsule instead of a lozenge
  119. if (radius >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0)
  120. {
  121. return GetCapsule(baseRect);
  122. }
  123. // create the arc for the rectangle sides and declare
  124. // a graphics path object for the drawing
  125. float diameter = radius * 2.0f;
  126. var sizeF = new SizeF(diameter, diameter);
  127. var arc = new RectangleF(baseRect.Location, sizeF);
  128. var path = new PdnGraphicsPath();
  129. // top left arc
  130. path.AddArc (arc, 180, 90);
  131. // top right arc
  132. arc.X = baseRect.Right - diameter;
  133. path.AddArc (arc, 270, 90);
  134. // bottom right arc
  135. arc.Y = baseRect.Bottom - diameter;
  136. path.AddArc (arc, 0, 90);
  137. // bottom left arc
  138. arc.X = baseRect.Left;
  139. path.AddArc (arc, 90, 90);
  140. path.CloseFigure();
  141. return path;
  142. }
  143. // credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp
  144. private static PdnGraphicsPath GetCapsule(RectangleF baseRect)
  145. {
  146. RectangleF arc;
  147. var path = new PdnGraphicsPath();
  148. try
  149. {
  150. float diameter;
  151. if (baseRect.Width>baseRect.Height)
  152. {
  153. // return horizontal capsule
  154. diameter = baseRect.Height;
  155. var sizeF = new SizeF(diameter, diameter);
  156. arc = new RectangleF(baseRect.Location, sizeF);
  157. path.AddArc(arc, 90, 180);
  158. arc.X = baseRect.Right-diameter;
  159. path.AddArc(arc, 270, 180);
  160. }
  161. else if (baseRect.Width < baseRect.Height)
  162. {
  163. // return vertical capsule
  164. diameter = baseRect.Width;
  165. var sizeF = new SizeF(diameter, diameter);
  166. arc = new RectangleF(baseRect.Location, sizeF);
  167. path.AddArc(arc, 180, 180);
  168. arc.Y = baseRect.Bottom-diameter;
  169. path.AddArc(arc, 0, 180);
  170. }
  171. else
  172. { // return circle
  173. path.AddEllipse(baseRect);
  174. }
  175. }
  176. catch (Exception)
  177. {
  178. path.AddEllipse(baseRect);
  179. }
  180. finally
  181. {
  182. path.CloseFigure();
  183. }
  184. return path;
  185. }
  186. }
  187. }