diff --git a/src/Greenshot.Base/Greenshot.Base.csproj b/src/Greenshot.Base/Greenshot.Base.csproj
index 169bd9395..805098491 100644
--- a/src/Greenshot.Base/Greenshot.Base.csproj
+++ b/src/Greenshot.Base/Greenshot.Base.csproj
@@ -6,15 +6,15 @@
-
-
-
-
-
-
+
+
+
+
+
+
-
+
diff --git a/src/Greenshot.Editor/Drawing/CropContainer.cs b/src/Greenshot.Editor/Drawing/CropContainer.cs
index 2aee4252f..d450e9dd2 100644
--- a/src/Greenshot.Editor/Drawing/CropContainer.cs
+++ b/src/Greenshot.Editor/Drawing/CropContainer.cs
@@ -250,7 +250,7 @@ namespace Greenshot.Editor.Drawing
break;
}
}
- _boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, x, y, GetAngleRoundProcessor());
+ _boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, Positions.TopLeft, x, y, GetAngleRoundProcessor());
// apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize);
diff --git a/src/Greenshot.Editor/Drawing/DrawableContainer.cs b/src/Greenshot.Editor/Drawing/DrawableContainer.cs
index be4638164..c9737f9e3 100644
--- a/src/Greenshot.Editor/Drawing/DrawableContainer.cs
+++ b/src/Greenshot.Editor/Drawing/DrawableContainer.cs
@@ -533,7 +533,7 @@ namespace Greenshot.Editor.Drawing
// reset "workbench" rectangle to current bounds
_boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top);
- _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y, GetAngleRoundProcessor());
+ _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Positions.TopLeft, x, y, GetAngleRoundProcessor());
// apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize);
diff --git a/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs b/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs
index 0c467c0b8..45238caaf 100644
--- a/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs
+++ b/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs
@@ -25,6 +25,7 @@ using System.Drawing.Drawing2D;
using System.Runtime.Serialization;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
+using Greenshot.Editor.Drawing.Adorners;
namespace Greenshot.Editor.Drawing
{
@@ -35,28 +36,54 @@ namespace Greenshot.Editor.Drawing
[Serializable]
public abstract class VectorGraphicsContainer : DrawableContainer
{
- protected int RotationAngle;
+ private int _rotationAngle;
+ protected int RotationAngle
+ {
+ get => _rotationAngle;
+ set => _rotationAngle = value;
+ }
///
/// This is the cached version of the bitmap, pre-rendered to save performance
- /// Do not serialized, it can be rebuild with some other information.
+ /// Do not serialized, it can be rebuild with other information.
///
[NonSerialized] private Image _cachedImage;
+ ///
+ /// Constructor takes care of calling Init
+ ///
+ /// ISurface
public VectorGraphicsContainer(ISurface parent) : base(parent)
{
Init();
}
+ ///
+ /// Make sure Init is called after deserializing
+ ///
+ /// StreamingContext
protected override void OnDeserialized(StreamingContext streamingContext)
{
base.OnDeserialized(streamingContext);
Init();
}
- private void Init()
+ ///
+ /// Init is called after creating the instance, and from OnDeserialized
+ /// This is the place to generate your adorners
+ ///
+ protected virtual void Init()
{
- CreateDefaultAdorners();
+ // Check if the adorners are already defined!
+ if (Adorners.Count > 0)
+ {
+ return;
+ }
+
+ Adorners.Add(new ResizeAdorner(this, Positions.TopLeft));
+ Adorners.Add(new ResizeAdorner(this, Positions.TopRight));
+ Adorners.Add(new ResizeAdorner(this, Positions.BottomLeft));
+ Adorners.Add(new ResizeAdorner(this, Positions.BottomRight));
}
///
@@ -96,7 +123,10 @@ namespace Greenshot.Editor.Drawing
}
_cachedImage ??= ComputeBitmap();
-
+ if (_cachedImage == null)
+ {
+ return;
+ }
graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
@@ -106,9 +136,16 @@ namespace Greenshot.Editor.Drawing
graphics.DrawImage(_cachedImage, Bounds);
}
+ ///
+ /// Implement this to compute the new bitmap according to the size of the container
+ ///
+ /// Image
protected abstract Image ComputeBitmap();
- private void ResetCachedBitmap()
+ ///
+ /// Dispose of the cached bitmap, forcing the code to regenerate it
+ ///
+ protected void ResetCachedBitmap()
{
_cachedImage?.Dispose();
_cachedImage = null;
diff --git a/src/Greenshot.Editor/Helpers/ScaleHelper.cs b/src/Greenshot.Editor/Helpers/ScaleHelper.cs
index 4f4e7dc7a..63f25d0a0 100644
--- a/src/Greenshot.Editor/Helpers/ScaleHelper.cs
+++ b/src/Greenshot.Editor/Helpers/ScaleHelper.cs
@@ -58,7 +58,7 @@ namespace Greenshot.Editor.Helpers
/// the size of the element to be resized
/// the target size of the element
/// in case the aspect ratio of currentSize and targetSize differs: shall the scaled size fit into targetSize (i.e. that one of its dimensions is smaller - false) or vice versa (true)
- /// a new SizeF object indicating the width and height the element should be scaled to
+ /// NativeSizeFloat object indicating the width and height the element should be scaled to
public static NativeSizeFloat GetScaledSize(NativeSizeFloat currentSize, NativeSizeFloat targetSize, bool crop)
{
float wFactor = targetSize.Width / currentSize.Width;
@@ -71,10 +71,10 @@ namespace Greenshot.Editor.Helpers
///
/// calculates the position of an element depending on the desired alignment within a RectangleF
///
- /// the bounds of the element to be aligned
- /// the rectangle reference for alignment of the element
+ /// NativeRectFloat the bounds of the element to be aligned
+ /// NativeRectFloat with the rectangle for alignment of the element
/// the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize
- /// a new RectangleF object with Location aligned aligned to targetRect
+ /// NativeRectFloat object with Location aligned aligned to targetRect
public static NativeRectFloat GetAlignedRectangle(NativeRectFloat currentRect, NativeRectFloat targetRect, ContentAlignment alignment)
{
var newRect = new NativeRectFloat(targetRect.Location, currentRect.Size);
@@ -96,9 +96,9 @@ namespace Greenshot.Editor.Helpers
///
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
///
- /// bounds of the current rectangle
- /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT
- /// coordinates of the used handle/gripper
+ /// NativeRectFloat bounds of the current rectangle
+ /// Positions with the position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT
+ /// NativePointFloat coordinates of the used handle/gripper
/// ScaleOptions to use when scaling
/// NativeRectFloat scaled originalRectangle
public static NativeRectFloat Scale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords, ScaleOptions? options)
@@ -134,9 +134,9 @@ namespace Greenshot.Editor.Helpers
///
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
///
- /// bounds of the current rectangle
- /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT
- /// coordinates of the used handle/gripper
+ /// NativeRectFloat bounds of the current rectangle
+ /// Positions with the position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT
+ /// NativePointFloat with coordinates of the used handle/gripper
/// NativeRectFloat with the scaled originalRectangle
private static NativeRectFloat Scale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords)
{
@@ -158,9 +158,9 @@ namespace Greenshot.Editor.Helpers
/// To avoid objects growing near infinity unexpectedly in certain combinations, the adjustment will choose the
/// option resulting in the smaller rectangle.
///
- /// bounds of the current rectangle
- /// position of the handle/gripper being used for resized, see Position
- /// coordinates of the used handle/gripper
+ /// NativeRectFloat with the bounds of the current rectangle
+ /// Positions with the position of the handle/gripper being used for resized, see Position
+ /// NativePointFloat with coordinates of the used handle/gripper
/// NativePointFloat with the adjusted coordinates
private static NativePointFloat AdjustCoordsForRationalScale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords)
{
@@ -203,7 +203,7 @@ namespace Greenshot.Editor.Helpers
///
/// NativeSizeFloat to be considered for keeping aspect ratio
/// NativeSizeFloat selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio)
- ///
+ /// NativeSizeFloat
private static NativeSizeFloat GetNewSizeForRationalScale(NativeSizeFloat originalSize, NativeSizeFloat selectedSize)
{
NativeSizeFloat newSize = selectedSize;
@@ -227,16 +227,15 @@ namespace Greenshot.Editor.Helpers
return newSize;
}
- public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY)
- {
- return Scale(boundsBeforeResize, cursorX, cursorY, null);
- }
-
- public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior)
- {
- return Scale(boundsBeforeResize, Positions.TopLeft, cursorX, cursorY, angleRoundBehavior);
- }
-
+ ///
+ /// Scale the boundsBeforeResize with the specified position and new location, using the angle angleRoundBehavior
+ ///
+ /// NativeRect
+ /// Positions
+ /// int
+ /// int
+ /// IDoubleProcessor
+ /// NativeRectFloat
public static NativeRectFloat Scale(NativeRect boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior)
{
ScaleOptions opts = GetScaleOptions();