/src/tools/RoundedRectangleTool.cs
C# | 222 lines | 164 code | 35 blank | 23 comment | 14 complexity | da1a4cfb6bfc25bcd2aec5bd665e8849 MD5 | raw file
- /////////////////////////////////////////////////////////////////////////////////
- // Paint.NET //
- // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
- // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
- // See src/Resources/Files/License.txt for full licensing and attribution //
- // details. //
- // . //
- /////////////////////////////////////////////////////////////////////////////////
-
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.Windows.Forms;
- using PaintDotNet.Base;
-
- namespace PaintDotNet.Tools
- {
- internal class RoundedRectangleTool
- : ShapeTool
- {
- private ImageResource _roundedRectangleToolIcon;
- private readonly string _statusTextFormat = PdnResources.GetString("RoundedRectangleTool.StatusText.Format");
- private Cursor _roundedRectangleCursor;
-
- protected override RectangleF[] GetOptimizedShapeOutlineRegion(PointF[] points, PdnGraphicsPath path)
- {
- return Utility.SimplifyTrace(path.PathPoints);
- }
-
- protected override List<PointF> TrimShapePath(List<PointF> points)
- {
- var array = new List<PointF>();
-
- if (points.Count > 0)
- {
- array.Add(points[0]);
-
- if (points.Count > 1)
- {
- array.Add(points[points.Count - 1]);
- }
- }
-
- return array;
- }
-
- protected override PdnGraphicsPath CreateShapePath(PointF[] points)
- {
- PointF a = points[0];
- PointF b = points[points.Length - 1];
- const float radius = 10;
-
- RectangleF rect = (ModifierKeys & Keys.Shift) != 0 ? Utility.PointsToConstrainedRectangle(a, b) : Utility.PointsToRectangle(a, b);
-
- PdnGraphicsPath path = GetRoundedRect(rect, radius);
- path.Flatten();
-
- if (path.PathPoints[0] != path.PathPoints[path.PathPoints.Length - 1])
- {
- path.AddLine(path.PathPoints[0], path.PathPoints[path.PathPoints.Length - 1]);
- path.CloseFigure();
- }
-
- MeasurementUnit units = AppWorkspace.Units;
- double widthPhysical = Math.Abs(Document.PixelToPhysicalX(rect.Width, units));
- double heightPhysical = Math.Abs(Document.PixelToPhysicalY(rect.Height, units));
- double areaPhysical = widthPhysical * heightPhysical;
-
- string numberFormat;
- string unitsAbbreviation;
-
- if (units != MeasurementUnit.Pixel)
- {
- string unitsAbbreviationName = "MeasurementUnit." + units + ".Abbreviation";
- unitsAbbreviation = PdnResources.GetString(unitsAbbreviationName);
- numberFormat = "F2";
- }
- else
- {
- unitsAbbreviation = string.Empty;
- numberFormat = "F0";
- }
-
- string unitsString = PdnResources.GetString("MeasurementUnit." + units + ".Plural");
-
- string statusText = string.Format(
- _statusTextFormat,
- widthPhysical.ToString(numberFormat),
- unitsAbbreviation,
- heightPhysical.ToString(numberFormat),
- unitsAbbreviation,
- areaPhysical.ToString(numberFormat),
- unitsString);
-
- SetStatus(_roundedRectangleToolIcon, statusText);
-
- return path;
- }
-
- protected override void OnActivate()
- {
- _roundedRectangleCursor = new Cursor(PdnResources.GetResourceStream("Cursors.RoundedRectangleToolCursor.cur"));
- Cursor = _roundedRectangleCursor;
- _roundedRectangleToolIcon = Image;
- base.OnActivate();
- }
-
- protected override void OnDeactivate()
- {
- if (_roundedRectangleCursor != null)
- {
- _roundedRectangleCursor.Dispose();
- _roundedRectangleCursor = null;
- }
-
- base.OnDeactivate();
- }
-
- public RoundedRectangleTool(DocumentWorkspace documentWorkspace)
- : base(documentWorkspace,
- PdnResources.GetImageResource("Icons.RoundedRectangleToolIcon.png"),
- PdnResources.GetString("RoundedRectangleTool.Name"),
- PdnResources.GetString("RoundedRectangleTool.HelpText"))
- {
- }
-
- // credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp
- protected PdnGraphicsPath GetRoundedRect(RectangleF baseRect, float radius)
- {
- // if corner radius is less than or equal to zero,
- // return the original rectangle
- if (radius <= 0.0f)
- {
- var mPath = new PdnGraphicsPath();
- mPath.AddRectangle(baseRect);
- mPath.CloseFigure();
- return mPath;
- }
-
- // if the corner radius is greater than or equal to
- // half the width, or height (whichever is shorter)
- // then return a capsule instead of a lozenge
- if (radius >= (Math.Min(baseRect.Width, baseRect.Height)) / 2.0)
- {
- return GetCapsule(baseRect);
- }
-
- // create the arc for the rectangle sides and declare
- // a graphics path object for the drawing
- float diameter = radius * 2.0f;
- var sizeF = new SizeF(diameter, diameter);
- var arc = new RectangleF(baseRect.Location, sizeF);
- var path = new PdnGraphicsPath();
-
- // top left arc
- path.AddArc (arc, 180, 90);
-
- // top right arc
- arc.X = baseRect.Right - diameter;
- path.AddArc (arc, 270, 90);
-
- // bottom right arc
- arc.Y = baseRect.Bottom - diameter;
- path.AddArc (arc, 0, 90);
-
- // bottom left arc
- arc.X = baseRect.Left;
- path.AddArc (arc, 90, 90);
-
- path.CloseFigure();
- return path;
- }
-
- // credit for the this function is given to Aaron Reginald http://www.codeproject.com/cs/media/ExtendedGraphics.asp
- private static PdnGraphicsPath GetCapsule(RectangleF baseRect)
- {
- RectangleF arc;
- var path = new PdnGraphicsPath();
-
- try
- {
- float diameter;
- if (baseRect.Width>baseRect.Height)
- {
- // return horizontal capsule
- diameter = baseRect.Height;
- var sizeF = new SizeF(diameter, diameter);
- arc = new RectangleF(baseRect.Location, sizeF);
- path.AddArc(arc, 90, 180);
- arc.X = baseRect.Right-diameter;
- path.AddArc(arc, 270, 180);
- }
- else if (baseRect.Width < baseRect.Height)
- {
- // return vertical capsule
- diameter = baseRect.Width;
- var sizeF = new SizeF(diameter, diameter);
- arc = new RectangleF(baseRect.Location, sizeF);
- path.AddArc(arc, 180, 180);
- arc.Y = baseRect.Bottom-diameter;
- path.AddArc(arc, 0, 180);
- }
- else
- { // return circle
- path.AddEllipse(baseRect);
- }
- }
-
- catch (Exception)
- {
- path.AddEllipse(baseRect);
- }
-
- finally
- {
- path.CloseFigure();
- }
-
- return path;
- }
- }
- }