Fixed merge conflict, and merged the EmojiContainer and VectorGraphicsContainer

This commit is contained in:
Robin Krom 2022-04-14 12:17:24 +02:00
commit 8e6a13f00a
No known key found for this signature in database
GPG key ID: BCC01364F1371490
7 changed files with 144 additions and 171 deletions

View file

@ -6,12 +6,12 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Dapplo.HttpExtensions.JsonNet" Version="1.0.18" /> <PackageReference Include="Dapplo.HttpExtensions.JsonNet" Version="1.0.18" />
<PackageReference Include="Dapplo.Windows.Clipboard" Version="1.0.22" /> <PackageReference Include="Dapplo.Windows.Clipboard" Version="1.0.25" />
<PackageReference Include="Dapplo.Windows.Dpi" Version="1.0.22" /> <PackageReference Include="Dapplo.Windows.Dpi" Version="1.0.25" />
<PackageReference Include="Dapplo.Windows.Gdi32" Version="1.0.22" /> <PackageReference Include="Dapplo.Windows.Gdi32" Version="1.0.25" />
<PackageReference Include="Dapplo.Windows.Icons" Version="1.0.22" /> <PackageReference Include="Dapplo.Windows.Icons" Version="1.0.25" />
<PackageReference Include="Dapplo.Windows.Kernel32" Version="1.0.22" /> <PackageReference Include="Dapplo.Windows.Kernel32" Version="1.0.25" />
<PackageReference Include="Dapplo.Windows.Multimedia" Version="1.0.22" /> <PackageReference Include="Dapplo.Windows.Multimedia" Version="1.0.25" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.42" /> <PackageReference Include="HtmlAgilityPack" Version="1.11.42" />
<PackageReference Include="log4net" version="2.0.14" /> <PackageReference Include="log4net" version="2.0.14" />
<PackageReference Include="Svg" Version="3.4.2" /> <PackageReference Include="Svg" Version="3.4.2" />

View file

@ -20,6 +20,9 @@ using System.Windows.Input;
namespace Greenshot.Editor.Controls namespace Greenshot.Editor.Controls
{ {
/// <summary>
/// The event which is created when the emoji is picked
/// </summary>
public class EmojiPickedEventArgs : EventArgs public class EmojiPickedEventArgs : EventArgs
{ {
public EmojiPickedEventArgs() { } public EmojiPickedEventArgs() { }
@ -61,8 +64,7 @@ namespace Greenshot.Editor.Controls
public event EmojiPickedEventHandler Picked; public event EmojiPickedEventHandler Picked;
private static void OnSelectionPropertyChanged(DependencyObject source, private static void OnSelectionPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
DependencyPropertyChangedEventArgs e)
{ {
(source as EmojiPicker)?.OnSelectionChanged(e.NewValue as string); (source as EmojiPicker)?.OnSelectionChanged(e.NewValue as string);
} }
@ -75,24 +77,21 @@ namespace Greenshot.Editor.Controls
private void OnSelectionChanged(string s) private void OnSelectionChanged(string s)
{ {
var is_disabled = string.IsNullOrEmpty(s); var isDisabled = string.IsNullOrEmpty(s);
Image.Emoji = is_disabled ? "???" : s; Image.Emoji = isDisabled ? "???" : s;
Image.Opacity = is_disabled ? 0.3 : 1.0; Image.Opacity = isDisabled ? 0.3 : 1.0;
SelectionChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Selection))); SelectionChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Selection)));
} }
private void OnEmojiPicked(object sender, RoutedEventArgs e) private void OnEmojiPicked(object sender, RoutedEventArgs e)
{ {
if (sender is Control control && control.DataContext is EmojiData.Emoji emoji) if (sender is not Control { DataContext: EmojiData.Emoji emoji }) return;
{ if (emoji.VariationList.Count != 0 && sender is not Button) return;
if (emoji.VariationList.Count == 0 || sender is Button)
{ Selection = emoji.Text;
Selection = emoji.Text; Button_INTERNAL.IsChecked = false;
Button_INTERNAL.IsChecked = false; e.Handled = true;
e.Handled = true; Picked?.Invoke(this, new EmojiPickedEventArgs(Selection));
Picked?.Invoke(this, new EmojiPickedEventArgs(Selection));
}
}
} }
public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register( public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register(
@ -101,31 +100,37 @@ namespace Greenshot.Editor.Controls
private void OnPopupKeyDown(object sender, KeyEventArgs e) private void OnPopupKeyDown(object sender, KeyEventArgs e)
{ {
if (e.Key == Key.Escape && sender is Popup popup) if (e.Key != Key.Escape || sender is not Popup popup) return;
{ popup.IsOpen = false;
popup.IsOpen = false; e.Handled = true;
e.Handled = true;
}
} }
private void OnPopupLoaded(object sender, RoutedEventArgs e) private void OnPopupLoaded(object sender, RoutedEventArgs e)
{ {
if (!(sender is Popup popup)) if (sender is not Popup popup) return;
return;
var child = popup.Child; var child = popup.Child;
IInputElement old_focus = null; IInputElement oldFocus = null;
child.Focusable = true; child.Focusable = true;
child.IsVisibleChanged += (o, ea) => child.IsVisibleChanged += (o, ea) =>
{ {
if (child.IsVisible) if (!child.IsVisible) return;
{ oldFocus = Keyboard.FocusedElement;
old_focus = Keyboard.FocusedElement; Keyboard.Focus(child);
Keyboard.Focus(child);
}
}; };
popup.Closed += (o, ea) => Keyboard.Focus(old_focus); popup.Closed += (o, ea) => Keyboard.Focus(oldFocus);
}
public void ShowPopup(bool show)
{
foreach (var child in Children)
{
if (child is ToggleButton button)
{
button.IsChecked = show;
}
}
} }
} }
} }

View file

@ -250,8 +250,7 @@ namespace Greenshot.Editor.Drawing
break; break;
} }
} }
var scaleOptions = (this as IHaveScaleOptions)?.GetScaleOptions(); _boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, Positions.TopLeft, x, y, GetAngleRoundProcessor());
_boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, x, y, GetAngleRoundProcessor(), scaleOptions);
// apply scaled bounds to this DrawableContainer // apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize); ApplyBounds(_boundsAfterResize);

View file

@ -534,7 +534,7 @@ namespace Greenshot.Editor.Drawing
_boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); _boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top);
var scaleOptions = (this as IHaveScaleOptions)?.GetScaleOptions(); var scaleOptions = (this as IHaveScaleOptions)?.GetScaleOptions();
_boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y, GetAngleRoundProcessor(), scaleOptions); _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Positions.TopLeft, x, y,GetAngleRoundProcessor(), scaleOptions);
// apply scaled bounds to this DrawableContainer // apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize); ApplyBounds(_boundsAfterResize);

View file

@ -20,11 +20,9 @@
*/ */
using System; using System;
using System.Drawing; using System.ComponentModel;
using System.Drawing.Drawing2D;
using System.Linq; using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Windows.Controls.Primitives;
using System.Windows.Forms; using System.Windows.Forms;
using System.Windows.Forms.Integration; using System.Windows.Forms.Integration;
using Greenshot.Base.Core; using Greenshot.Base.Core;
@ -33,7 +31,6 @@ using Greenshot.Editor.Controls;
using Greenshot.Editor.Drawing.Adorners; using Greenshot.Editor.Drawing.Adorners;
using Greenshot.Editor.Helpers; using Greenshot.Editor.Helpers;
using Image = System.Drawing.Image; using Image = System.Drawing.Image;
using Matrix = System.Drawing.Drawing2D.Matrix;
namespace Greenshot.Editor.Drawing namespace Greenshot.Editor.Drawing
{ {
@ -41,17 +38,15 @@ namespace Greenshot.Editor.Drawing
/// Description of EmojiContainer. /// Description of EmojiContainer.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class EmojiContainer : DrawableContainer, IEmojiContainer, IHaveScaleOptions public class EmojiContainer : VectorGraphicsContainer, IEmojiContainer, IHaveScaleOptions
{ {
[NonSerialized] private static EmojiContainer _currentContainer; [NonSerialized] private static EmojiContainer _currentContainer;
[NonSerialized] private static ElementHost _emojiPickerHost; [NonSerialized] private static ElementHost _emojiPickerHost;
[NonSerialized] private static EmojiPicker _emojiPicker; [NonSerialized] private static EmojiPicker _emojiPicker;
[NonSerialized] private bool _justCreated = true; [NonSerialized] private bool _justCreated = true;
[NonSerialized] private Image _cachedImage = null;
private string _emoji; private string _emoji;
private int _rotationAngle;
private bool _useSystemFont; private bool _useSystemFont;
public string Emoji public string Emoji
@ -111,7 +106,7 @@ namespace Greenshot.Editor.Drawing
private void GetOrCreatePickerControl() private void GetOrCreatePickerControl()
{ {
// Create one picker control by surface // Create one picker control by surface
// TODO: This is not ideal, replace with a different solution. // TODO: This is not ideal, as we need to controls from the surface, should replace this with a different solution.
_emojiPickerHost = _parent.Controls.Find("EmojiPickerHost", false).OfType<ElementHost>().FirstOrDefault(); _emojiPickerHost = _parent.Controls.Find("EmojiPickerHost", false).OfType<ElementHost>().FirstOrDefault();
if (_emojiPickerHost != null) return; if (_emojiPickerHost != null) return;
@ -123,10 +118,12 @@ namespace Greenshot.Editor.Drawing
_currentContainer.Invalidate(); _currentContainer.Invalidate();
}; };
_emojiPickerHost = new ElementHost(); _emojiPickerHost = new ElementHost
_emojiPickerHost.Dock = DockStyle.None; {
_emojiPickerHost.Child = _emojiPicker; Dock = DockStyle.None,
_emojiPickerHost.Name = "EmojiPickerHost"; Child = _emojiPicker,
Name = "EmojiPickerHost"
};
_parent.Controls.Add(_emojiPickerHost); _parent.Controls.Add(_emojiPickerHost);
} }
@ -136,91 +133,46 @@ namespace Greenshot.Editor.Drawing
_emojiPicker?.ShowPopup(false); _emojiPicker?.ShowPopup(false);
} }
protected override void OnDeserialized(StreamingContext streamingContext) /// <summary>
/// Make sure we register the property changed, to manage the state of the picker
/// </summary>
protected override void Init()
{ {
base.OnDeserialized(streamingContext); base.Init();
Init();
}
private void Init()
{
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));
PropertyChanged += OnPropertyChanged; PropertyChanged += OnPropertyChanged;
} }
protected override void Dispose(bool disposing)
/// <summary>
/// Handle the state of the Emoji Picker
/// </summary>
/// <param name="sender">object</param>
/// <param name="e">PropertyChangedEventArgs</param>
private void OnPropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (disposing) if (!e.PropertyName.Equals(nameof(Selected))) return;
if (!Selected)
{ {
ResetCachedBitmap(); HideEmojiPicker();
} }
else if (Status == EditStatus.IDLE && _justCreated)
base.Dispose(disposing);
}
public override void Transform(Matrix matrix)
{
_rotationAngle += CalculateAngle(matrix);
_rotationAngle %= 360;
ResetCachedBitmap();
base.Transform(matrix);
}
private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
if (e.PropertyName.Equals(nameof(Selected)))
{ {
if (!Selected) // Show picker just after creation
{ ShowEmojiPicker();
HideEmojiPicker(); _justCreated = false;
}
else if (Status == EditStatus.IDLE && _justCreated)
{
// Show picker just after creation
ShowEmojiPicker();
_justCreated = false;
}
} }
} }
public override void Draw(Graphics graphics, RenderMode rm) protected override Image ComputeBitmap()
{ {
graphics.SmoothingMode = SmoothingMode.HighQuality; var iconSize = Math.Min(Bounds.Width, Bounds.Height);
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; if (iconSize <= 0) return null;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
var rect = Bounds;
var iconSize = Math.Min(rect.Width, rect.Height);
if (iconSize <= 0) return;
if (_cachedImage == null)
{
// First draw or cache was invalidated
_cachedImage = ComputeBitmap(iconSize);
}
else if (iconSize != _cachedImage.Width)
{
// The elements was resized => recompute
_cachedImage.Dispose();
_cachedImage = ComputeBitmap(iconSize);
}
graphics.DrawImage(_cachedImage, Bounds);
}
private Image ComputeBitmap(int iconSize)
{
var image = EmojiRenderer.GetBitmap(Emoji, iconSize, useSystemFont: _useSystemFont); var image = EmojiRenderer.GetBitmap(Emoji, iconSize, useSystemFont: _useSystemFont);
if (_rotationAngle != 0) if (RotationAngle != 0)
{ {
var newImage = image.Rotate(_rotationAngle); var newImage = image.Rotate(RotationAngle);
image.Dispose(); image.Dispose();
return newImage; return newImage;
} }
@ -228,29 +180,9 @@ namespace Greenshot.Editor.Drawing
return image; return image;
} }
private void ResetCachedBitmap()
{
_cachedImage?.Dispose();
_cachedImage = null;
}
public ScaleHelper.ScaleOptions GetScaleOptions() public ScaleHelper.ScaleOptions GetScaleOptions()
{ {
return ScaleHelper.ScaleOptions.Rational; return ScaleHelper.ScaleOptions.Rational;
} }
} }
internal static class PickerExtensions
{
public static void ShowPopup(this EmojiPicker emojiPicker, bool show)
{
foreach (var child in emojiPicker.Children)
{
if (child is ToggleButton button)
{
button.IsChecked = show;
}
}
}
}
} }

View file

@ -25,6 +25,7 @@ using System.Drawing.Drawing2D;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Greenshot.Base.Interfaces; using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing; using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Drawing.Adorners;
namespace Greenshot.Editor.Drawing namespace Greenshot.Editor.Drawing
{ {
@ -35,28 +36,54 @@ namespace Greenshot.Editor.Drawing
[Serializable] [Serializable]
public abstract class VectorGraphicsContainer : DrawableContainer public abstract class VectorGraphicsContainer : DrawableContainer
{ {
protected int RotationAngle; private int _rotationAngle;
protected int RotationAngle
{
get => _rotationAngle;
set => _rotationAngle = value;
}
/// <summary> /// <summary>
/// This is the cached version of the bitmap, pre-rendered to save performance /// 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.
/// </summary> /// </summary>
[NonSerialized] private Image _cachedImage; [NonSerialized] private Image _cachedImage;
/// <summary>
/// Constructor takes care of calling Init
/// </summary>
/// <param name="parent">ISurface</param>
public VectorGraphicsContainer(ISurface parent) : base(parent) public VectorGraphicsContainer(ISurface parent) : base(parent)
{ {
Init(); Init();
} }
/// <summary>
/// Make sure Init is called after deserializing
/// </summary>
/// <param name="streamingContext">StreamingContext</param>
protected override void OnDeserialized(StreamingContext streamingContext) protected override void OnDeserialized(StreamingContext streamingContext)
{ {
base.OnDeserialized(streamingContext); base.OnDeserialized(streamingContext);
Init(); Init();
} }
private void Init() /// <summary>
/// Init is called after creating the instance, and from OnDeserialized
/// This is the place to generate your adorners
/// </summary>
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));
} }
/// <summary> /// <summary>
@ -96,7 +123,10 @@ namespace Greenshot.Editor.Drawing
} }
_cachedImage ??= ComputeBitmap(); _cachedImage ??= ComputeBitmap();
if (_cachedImage == null)
{
return;
}
graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality; graphics.CompositingQuality = CompositingQuality.HighQuality;
@ -106,9 +136,16 @@ namespace Greenshot.Editor.Drawing
graphics.DrawImage(_cachedImage, Bounds); graphics.DrawImage(_cachedImage, Bounds);
} }
/// <summary>
/// Implement this to compute the new bitmap according to the size of the container
/// </summary>
/// <returns>Image</returns>
protected abstract Image ComputeBitmap(); protected abstract Image ComputeBitmap();
private void ResetCachedBitmap() /// <summary>
/// Dispose of the cached bitmap, forcing the code to regenerate it
/// </summary>
protected void ResetCachedBitmap()
{ {
_cachedImage?.Dispose(); _cachedImage?.Dispose();
_cachedImage = null; _cachedImage = null;

View file

@ -58,7 +58,7 @@ namespace Greenshot.Editor.Helpers
/// <param name="currentSize">the size of the element to be resized</param> /// <param name="currentSize">the size of the element to be resized</param>
/// <param name="targetSize">the target size of the element</param> /// <param name="targetSize">the target size of the element</param>
/// <param name="crop">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)</param> /// <param name="crop">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)</param>
/// <returns>a new SizeF object indicating the width and height the element should be scaled to</returns> /// <returns>NativeSizeFloat object indicating the width and height the element should be scaled to</returns>
public static NativeSizeFloat GetScaledSize(NativeSizeFloat currentSize, NativeSizeFloat targetSize, bool crop) public static NativeSizeFloat GetScaledSize(NativeSizeFloat currentSize, NativeSizeFloat targetSize, bool crop)
{ {
float wFactor = targetSize.Width / currentSize.Width; float wFactor = targetSize.Width / currentSize.Width;
@ -71,10 +71,10 @@ namespace Greenshot.Editor.Helpers
/// <summary> /// <summary>
/// calculates the position of an element depending on the desired alignment within a RectangleF /// calculates the position of an element depending on the desired alignment within a RectangleF
/// </summary> /// </summary>
/// <param name="currentRect">the bounds of the element to be aligned</param> /// <param name="currentRect">NativeRectFloat the bounds of the element to be aligned</param>
/// <param name="targetRect">the rectangle reference for alignment of the element</param> /// <param name="targetRect">NativeRectFloat with the rectangle for alignment of the element</param>
/// <param name="alignment">the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize</param> /// <param name="alignment">the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize</param>
/// <returns>a new RectangleF object with Location aligned aligned to targetRect</returns> /// <returns>NativeRectFloat object with Location aligned aligned to targetRect</returns>
public static NativeRectFloat GetAlignedRectangle(NativeRectFloat currentRect, NativeRectFloat targetRect, ContentAlignment alignment) public static NativeRectFloat GetAlignedRectangle(NativeRectFloat currentRect, NativeRectFloat targetRect, ContentAlignment alignment)
{ {
var newRect = new NativeRectFloat(targetRect.Location, currentRect.Size); var newRect = new NativeRectFloat(targetRect.Location, currentRect.Size);
@ -96,9 +96,9 @@ namespace Greenshot.Editor.Helpers
/// <summary> /// <summary>
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
/// </summary> /// </summary>
/// <param name="originalRectangle">bounds of the current rectangle</param> /// <param name="originalRectangle">NativeRectFloat bounds of the current rectangle</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param> /// <param name="resizeHandlePosition">Positions with the position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param> /// <param name="resizeHandleCoords">NativePointFloat coordinates of the used handle/gripper</param>
/// <param name="options">ScaleOptions to use when scaling</param> /// <param name="options">ScaleOptions to use when scaling</param>
/// <returns>NativeRectFloat scaled originalRectangle</returns> /// <returns>NativeRectFloat scaled originalRectangle</returns>
public static NativeRectFloat Scale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords, ScaleOptions? options) public static NativeRectFloat Scale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords, ScaleOptions? options)
@ -134,9 +134,9 @@ namespace Greenshot.Editor.Helpers
/// <summary> /// <summary>
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
/// </summary> /// </summary>
/// <param name="originalRectangle">bounds of the current rectangle</param> /// <param name="originalRectangle">NativeRectFloat bounds of the current rectangle</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param> /// <param name="resizeHandlePosition">Positions with the position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param> /// <param name="resizeHandleCoords">NativePointFloat with coordinates of the used handle/gripper</param>
/// <returns>NativeRectFloat with the scaled originalRectangle</returns> /// <returns>NativeRectFloat with the scaled originalRectangle</returns>
private static NativeRectFloat Scale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords) 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 /// To avoid objects growing near infinity unexpectedly in certain combinations, the adjustment will choose the
/// option resulting in the smaller rectangle. /// option resulting in the smaller rectangle.
/// </summary> /// </summary>
/// <param name="originalRectangle">bounds of the current rectangle</param> /// <param name="originalRectangle">NativeRectFloat with the bounds of the current rectangle</param>
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see Position</param> /// <param name="resizeHandlePosition">Positions with the position of the handle/gripper being used for resized, see Position</param>
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param> /// <param name="resizeHandleCoords">NativePointFloat with coordinates of the used handle/gripper</param>
/// <returns>NativePointFloat with the adjusted coordinates</returns> /// <returns>NativePointFloat with the adjusted coordinates</returns>
private static NativePointFloat AdjustCoordsForRationalScale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords) private static NativePointFloat AdjustCoordsForRationalScale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords)
{ {
@ -203,7 +203,7 @@ namespace Greenshot.Editor.Helpers
/// </summary> /// </summary>
/// <param name="originalSize">NativeSizeFloat to be considered for keeping aspect ratio</param> /// <param name="originalSize">NativeSizeFloat to be considered for keeping aspect ratio</param>
/// <param name="selectedSize">NativeSizeFloat selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio)</param> /// <param name="selectedSize">NativeSizeFloat selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio)</param>
/// <returns></returns> /// <returns>NativeSizeFloat</returns>
private static NativeSizeFloat GetNewSizeForRationalScale(NativeSizeFloat originalSize, NativeSizeFloat selectedSize) private static NativeSizeFloat GetNewSizeForRationalScale(NativeSizeFloat originalSize, NativeSizeFloat selectedSize)
{ {
NativeSizeFloat newSize = selectedSize; NativeSizeFloat newSize = selectedSize;
@ -227,17 +227,17 @@ namespace Greenshot.Editor.Helpers
return newSize; return newSize;
} }
public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, ScaleOptions? options) /// <summary>
{ /// Scale the boundsBeforeResize with the specified position and new location, using the angle angleRoundBehavior
return Scale(boundsBeforeResize, cursorX, cursorY, null, options); /// </summary>
} /// <param name="boundsBeforeResize">NativeRect</param>
/// <param name="gripperPosition">Positions</param>
public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? options) /// <param name="cursorX">int</param>
{ /// <param name="cursorY">int</param>
return Scale(boundsBeforeResize, Positions.TopLeft, cursorX, cursorY, angleRoundBehavior, options); /// <param name="angleRoundBehavior">IDoubleProcessor</param>
} /// <param name="options">ScaleOptionsProcessor</param>
/// <returns>NativeRectFloat</returns>
public static NativeRectFloat Scale(NativeRect boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? options) public static NativeRectFloat Scale(NativeRect boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? options = null)
{ {
options ??= GetScaleOptions(); options ??= GetScaleOptions();