Enhanced ability to crop an image vertically and horizontally. #249 (#388)

Co-authored-by: Robin Krom <robin@getgreenshot.org>
This commit is contained in:
Christian Schulz 2022-03-22 11:57:01 +01:00 committed by GitHub
parent 4a66a4dbe2
commit 56c26ac038
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 865 additions and 310 deletions

View file

@ -190,12 +190,14 @@ namespace Greenshot.Base.Core
/// <summary>
/// Private helper method for the FindAutoCropRectangle
/// </summary>
/// <param name="fastBitmap"></param>
/// <param name="colorPoint"></param>
/// <param name="cropDifference"></param>
/// <param name="fastBitmap">IFastBitmap</param>
/// <param name="colorPoint">Point</param>
/// <param name="cropDifference">int</param>
/// <param name="area">Rectangle with optional area to scan in</param>
/// <returns>Rectangle</returns>
private static Rectangle FindAutoCropRectangle(IFastBitmap fastBitmap, Point colorPoint, int cropDifference)
private static Rectangle FindAutoCropRectangle(IFastBitmap fastBitmap, Point colorPoint, int cropDifference, Rectangle? area = null)
{
area ??= new Rectangle(0, 0, fastBitmap.Width, fastBitmap.Height);
Rectangle cropRectangle = Rectangle.Empty;
Color referenceColor = fastBitmap.GetColorAt(colorPoint.X, colorPoint.Y);
Point min = new Point(int.MaxValue, int.MaxValue);
@ -203,9 +205,9 @@ namespace Greenshot.Base.Core
if (cropDifference > 0)
{
for (int y = 0; y < fastBitmap.Height; y++)
for (int y = area.Value.Top; y < area.Value.Bottom; y++)
{
for (int x = 0; x < fastBitmap.Width; x++)
for (int x = area.Value.Left; x < area.Value.Right; x++)
{
Color currentColor = fastBitmap.GetColorAt(x, y);
int diffR = Math.Abs(currentColor.R - referenceColor.R);
@ -225,9 +227,9 @@ namespace Greenshot.Base.Core
}
else
{
for (int y = 0; y < fastBitmap.Height; y++)
for (int y = area.Value.Top; y < area.Value.Bottom; y++)
{
for (int x = 0; x < fastBitmap.Width; x++)
for (int x = area.Value.Left; x < area.Value.Right; x++)
{
Color currentColor = fastBitmap.GetColorAt(x, y);
if (!referenceColor.Equals(currentColor))
@ -243,7 +245,7 @@ namespace Greenshot.Base.Core
}
}
if (!(Point.Empty.Equals(min) && max.Equals(new Point(fastBitmap.Width - 1, fastBitmap.Height - 1))))
if (!(Point.Empty.Equals(min) && max.Equals(new Point(area.Value.Width - 1, area.Value.Height - 1))))
{
if (!(min.X == int.MaxValue || min.Y == int.MaxValue || max.X == int.MinValue || min.X == int.MinValue))
{
@ -257,18 +259,20 @@ namespace Greenshot.Base.Core
/// <summary>
/// Get a rectangle for the image which crops the image of all colors equal to that on 0,0
/// </summary>
/// <param name="image"></param>
/// <param name="cropDifference"></param>
/// <param name="image">Image</param>
/// <param name="cropDifference">int</param>
/// <param name="area">Rectangle with optional area</param>
/// <returns>Rectangle</returns>
public static Rectangle FindAutoCropRectangle(Image image, int cropDifference)
public static Rectangle FindAutoCropRectangle(Image image, int cropDifference, Rectangle? area = null)
{
area ??= new Rectangle(0, 0, image.Width, image.Height);
Rectangle cropRectangle = Rectangle.Empty;
var checkPoints = new List<Point>
{
new Point(0, 0),
new Point(0, image.Height - 1),
new Point(image.Width - 1, 0),
new Point(image.Width - 1, image.Height - 1)
new Point(area.Value.Left, area.Value.Top),
new Point(area.Value.Left, area.Value.Bottom - 1),
new Point(area.Value.Right - 1, area.Value.Top),
new Point(area.Value.Right - 1, area.Value.Bottom - 1)
};
// Top Left
// Bottom Left
@ -279,7 +283,7 @@ namespace Greenshot.Base.Core
// find biggest area
foreach (Point checkPoint in checkPoints)
{
var currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference);
var currentRectangle = FindAutoCropRectangle(fastBitmap, checkPoint, cropDifference, area);
if (currentRectangle.Width * currentRectangle.Height > cropRectangle.Width * cropRectangle.Height)
{
cropRectangle = currentRectangle;
@ -295,7 +299,7 @@ namespace Greenshot.Base.Core
/// </summary>
/// <param name="sourceImage">Bitmap</param>
/// <param name="effect">IEffect</param>
/// <param name="matrix"></param>
/// <param name="matrix">Matrix</param>
/// <returns>Bitmap</returns>
public static Image ApplyEffect(Image sourceImage, IEffect effect, Matrix matrix)
{

View file

@ -78,6 +78,11 @@ namespace Greenshot.Base.Interfaces.Drawing
bool InitContent();
/// <summary>
/// Defines if the drawable container participates in undo / redo
/// </summary>
bool IsUndoable { get; }
void MakeBoundsChangeUndoable(bool allowMerge);
EditStatus DefaultEditMode { get; }

View file

@ -21,6 +21,9 @@
namespace Greenshot.Base.Interfaces.Drawing
{
/// <summary>
/// The IFieldAggregator defines the connections between fields and containers
/// </summary>
public interface IFieldAggregator
{
void UnbindElement(IDrawableContainer dc);

View file

@ -201,8 +201,16 @@ namespace Greenshot.Base.Interfaces
/// <param name="rc">A rectangle in the coordinate space of the surface.</param>
Rectangle ToImageCoordinates(Rectangle rc);
/// <summary>
/// Make it possible to undo the specified IMemento
/// </summary>
/// <param name="memento">IMemento</param>
/// <param name="allowMerge">bool to specify if the action can be merged, e.g. we do not want an undo for every part of a resize</param>
void MakeUndoable(IMemento memento, bool allowMerge);
/// <summary>
/// The IFieldAggregator
/// </summary>
IFieldAggregator FieldAggregator { get; }
/// <summary>

View file

@ -33,6 +33,7 @@ namespace Greenshot.Editor.Configuration
contextmenu_capturefullscreen_right,
contextmenu_capturefullscreen_bottom,
contextmenu_captureie,
editor_autocrop_not_possible,
editor_clipboardfailed,
editor_close_on_save,
editor_close_on_save_title,

View file

@ -19,10 +19,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
using System.Drawing;
using System.Runtime.Serialization;
using Greenshot.Base.Interfaces;
using Greenshot.Base.Interfaces.Drawing;
using Greenshot.Editor.Drawing.Adorners;
using Greenshot.Editor.Drawing.Fields;
using Greenshot.Editor.Helpers;
@ -33,6 +35,29 @@ namespace Greenshot.Editor.Drawing
/// </summary>
public class CropContainer : DrawableContainer
{
/// <summary>
/// Available Crop modes
/// </summary>
public enum CropModes
{
/// <summary>
/// crop all outside the selection rectangle
/// </summary>
Default,
/// <summary>
/// like default, but initially creates the selection rectangle
/// </summary>
AutoCrop,
/// <summary>
/// crop all inside the selection, anchors the selection to the top and bottom edges
/// </summary>
Vertical,
/// <summary>
/// crop all inside the selection, anchors the selection to the left and right edges
/// </summary>
Horizontal
}
public CropContainer(ISurface parent) : base(parent)
{
Init();
@ -46,12 +71,65 @@ namespace Greenshot.Editor.Drawing
private void Init()
{
CreateDefaultAdorners();
switch (GetFieldValue(FieldType.CROPMODE))
{
case CropModes.Horizontal:
{
InitHorizontalCropOutStyle();
break;
}
case CropModes.Vertical:
{
InitVerticalCropOutStyle();
break;
}
default:
{
CreateDefaultAdorners();
break;
}
}
}
private void InitHorizontalCropOutStyle()
{
const int defaultHeight = 25;
if (_parent?.Image is { } image)
{
Size = new Size(image.Width, defaultHeight);
}
CreateTopBottomAdorners();
}
private void InitVerticalCropOutStyle()
{
const int defaultWidth = 25;
if (_parent?.Image is { } image)
{
Size = new Size(defaultWidth, image.Height);
}
CreateLeftRightAdorners();
}
private void CreateTopBottomAdorners()
{
Adorners.Add(new ResizeAdorner(this, Positions.TopCenter));
Adorners.Add(new ResizeAdorner(this, Positions.BottomCenter));
}
private void CreateLeftRightAdorners()
{
Adorners.Add(new ResizeAdorner(this, Positions.MiddleLeft));
Adorners.Add(new ResizeAdorner(this, Positions.MiddleRight));
}
protected override void InitializeFields()
{
AddField(GetType(), FieldType.FLAGS, FieldFlag.CONFIRMABLE);
AddField(GetType(), FieldType.CROPMODE, CropModes.Default);
}
public override void Invalidate()
@ -83,6 +161,7 @@ namespace Greenshot.Editor.Drawing
return;
}
using Brush cropBrush = new SolidBrush(Color.FromArgb(100, 150, 150, 100));
Rectangle cropRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
Rectangle selectionRect = new Rectangle(cropRectangle.Left - 1, cropRectangle.Top - 1, cropRectangle.Width + 1, cropRectangle.Height + 1);
@ -90,20 +169,104 @@ namespace Greenshot.Editor.Drawing
DrawSelectionBorder(g, selectionRect);
// top
g.FillRectangle(cropBrush, new Rectangle(0, 0, imageSize.Width, cropRectangle.Top));
// left
g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top, cropRectangle.Left, cropRectangle.Height));
// right
g.FillRectangle(cropBrush,
new Rectangle(cropRectangle.Left + cropRectangle.Width, cropRectangle.Top, imageSize.Width - (cropRectangle.Left + cropRectangle.Width), cropRectangle.Height));
// bottom
g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top + cropRectangle.Height, imageSize.Width, imageSize.Height - (cropRectangle.Top + cropRectangle.Height)));
switch (GetFieldValue(FieldType.CROPMODE))
{
case CropModes.Horizontal:
case CropModes.Vertical:
{
//draw inside
g.FillRectangle(cropBrush, cropRectangle);
break;
}
default:
{
//draw outside
// top
g.FillRectangle(cropBrush, new Rectangle(0, 0, imageSize.Width, cropRectangle.Top));
// left
g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top, cropRectangle.Left, cropRectangle.Height));
// right
g.FillRectangle(cropBrush, new Rectangle(cropRectangle.Left + cropRectangle.Width, cropRectangle.Top, imageSize.Width - (cropRectangle.Left + cropRectangle.Width), cropRectangle.Height));
// bottom
g.FillRectangle(cropBrush, new Rectangle(0, cropRectangle.Top + cropRectangle.Height, imageSize.Width, imageSize.Height - (cropRectangle.Top + cropRectangle.Height)));
break;
}
}
}
/// <summary>
/// No context menu for the CropContainer
/// </summary>
public override bool HasContextMenu => false;
public override bool HandleMouseDown(int x, int y)
{
return GetFieldValue(FieldType.CROPMODE) switch
{
//force horizontal crop to left edge
CropModes.Horizontal => base.HandleMouseDown(0, y),
//force vertical crop to top edge
CropModes.Vertical => base.HandleMouseDown(x, 0),
_ => base.HandleMouseDown(x, y),
};
}
public override bool HandleMouseMove(int x, int y)
{
Invalidate();
switch (GetFieldValue(FieldType.CROPMODE))
{
case CropModes.Horizontal:
{
//stick on left and right
//allow only horizontal changes
if (_parent?.Image is { } image)
{
_boundsAfterResize.X = 0;
_boundsAfterResize.Y = _boundsBeforeResize.Top;
_boundsAfterResize.Width = image.Width;
_boundsAfterResize.Height = y - _boundsAfterResize.Top;
}
break;
}
case CropModes.Vertical:
{
//stick on top and bottom
//allow only vertical changes
if (_parent?.Image is { } image)
{
_boundsAfterResize.X = _boundsBeforeResize.Left;
_boundsAfterResize.Y = 0;
_boundsAfterResize.Width = x - _boundsAfterResize.Left;
_boundsAfterResize.Height = image.Height;
}
break;
}
default:
{
// reset "workbench" rectangle to current bounds
_boundsAfterResize.X = _boundsBeforeResize.Left;
_boundsAfterResize.Y = _boundsBeforeResize.Top;
_boundsAfterResize.Width = x - _boundsAfterResize.Left;
_boundsAfterResize.Height = y - _boundsAfterResize.Top;
break;
}
}
ScaleHelper.Scale(_boundsBeforeResize, x, y, ref _boundsAfterResize, GetAngleRoundProcessor());
// apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize);
Invalidate();
return true;
}
/// <inheritdoc cref="IDrawableContainer"/>
/// Make sure this container is not undoable
public override bool IsUndoable => false;
}
}
}

View file

@ -472,13 +472,20 @@ namespace Greenshot.Editor.Drawing
g.DrawRectangle(pen, rect);
}
/// <inheritdoc cref="IDrawableContainer"/>
public virtual bool IsUndoable => true;
/// <summary>
/// Make a following bounds change on this drawablecontainer undoable!
/// </summary>
/// <param name="allowMerge">true means allow the moves to be merged</param>
public void MakeBoundsChangeUndoable(bool allowMerge)
public virtual void MakeBoundsChangeUndoable(bool allowMerge)
{
_parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(this), allowMerge);
if (!IsUndoable)
{
return;
}
_parent?.MakeUndoable(new DrawableContainerBoundsChangeMemento(this), allowMerge);
}
public void MoveBy(int dx, int dy)
@ -552,11 +559,10 @@ namespace Greenshot.Editor.Drawing
protected void OnPropertyChanged(string propertyName)
{
if (_propertyChanged != null)
{
_propertyChanged(this, new PropertyChangedEventArgs(propertyName));
Invalidate();
}
if (_propertyChanged == null) return;
_propertyChanged(this, new PropertyChangedEventArgs(propertyName));
Invalidate();
}
/// <summary>
@ -567,7 +573,10 @@ namespace Greenshot.Editor.Drawing
/// <param name="newValue">The new value</param>
public virtual void BeforeFieldChange(IField fieldToBeChanged, object newValue)
{
_parent?.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true);
if (IsUndoable)
{
_parent?.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true);
}
Invalidate();
}

View file

@ -24,6 +24,7 @@ using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Greenshot.Base.Core;
@ -50,6 +51,11 @@ namespace Greenshot.Editor.Drawing
{
}
public DrawableContainerList(IEnumerable<IDrawableContainer> elements)
{
AddRange(elements);
}
public DrawableContainerList(Guid parentId)
{
ParentID = parentId;
@ -130,17 +136,21 @@ namespace Greenshot.Editor.Drawing
}
/// <summary>
/// Make a following bounds change on this containerlist undoable!
/// Make a following bounds change on this DrawableContainerList undoable!
/// </summary>
/// <param name="allowMerge">true means allow the moves to be merged</param>
public void MakeBoundsChangeUndoable(bool allowMerge)
{
if (Count > 0 && Parent != null)
if (Count <= 0 || Parent == null) return;
// Take all containers to make undoable
var containersToClone = this.Where(c => c.IsUndoable).ToList();
if (!containersToClone.Any())
{
var clone = new DrawableContainerList();
clone.AddRange(this);
Parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(clone), allowMerge);
return;
}
var clone = new DrawableContainerList();
clone.AddRange(containersToClone);
Parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(clone), allowMerge);
}
/// <summary>
@ -291,16 +301,14 @@ namespace Greenshot.Editor.Drawing
{
return Rectangle.Empty;
}
else
{
var result = this[0].DrawingBounds;
for (int i = 1; i < Count; i++)
{
result = Rectangle.Union(result, this[i].DrawingBounds);
}
return result;
var result = this[0].DrawingBounds;
for (int i = 1; i < Count; i++)
{
result = Rectangle.Union(result, this[i].DrawingBounds);
}
return result;
}
}
@ -309,7 +317,7 @@ namespace Greenshot.Editor.Drawing
/// </summary>
/// <param name="g">the to the bitmap related Graphics object</param>
/// <param name="bitmap">Bitmap to draw</param>
/// <param name="renderMode">the rendermode in which the element is to be drawn</param>
/// <param name="renderMode">the RenderMode in which the element is to be drawn</param>
/// <param name="clipRectangle"></param>
public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle)
{
@ -574,9 +582,7 @@ namespace Greenshot.Editor.Drawing
return;
}
var dc = this[index1];
this[index1] = this[index2];
this[index2] = dc;
(this[index1], this[index2]) = (this[index2], this[index1]);
Parent.Modified = true;
}

View file

@ -31,31 +31,33 @@ namespace Greenshot.Editor.Drawing.Fields
[Serializable]
public class FieldType : IFieldType
{
public static readonly IFieldType ARROWHEADS = new FieldType("ARROWHEADS");
public static readonly IFieldType BLUR_RADIUS = new FieldType("BLUR_RADIUS");
public static readonly IFieldType BRIGHTNESS = new FieldType("BRIGHTNESS");
public static readonly IFieldType FILL_COLOR = new FieldType("FILL_COLOR");
public static readonly IFieldType FONT_BOLD = new FieldType("FONT_BOLD");
public static readonly IFieldType FONT_FAMILY = new FieldType("FONT_FAMILY");
public static readonly IFieldType FONT_ITALIC = new FieldType("FONT_ITALIC");
public static readonly IFieldType FONT_SIZE = new FieldType("FONT_SIZE");
public static readonly IFieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType("TEXT_HORIZONTAL_ALIGNMENT");
public static readonly IFieldType TEXT_VERTICAL_ALIGNMENT = new FieldType("TEXT_VERTICAL_ALIGNMENT");
public static readonly IFieldType HIGHLIGHT_COLOR = new FieldType("HIGHLIGHT_COLOR");
public static readonly IFieldType LINE_COLOR = new FieldType("LINE_COLOR");
public static readonly IFieldType LINE_THICKNESS = new FieldType("LINE_THICKNESS");
public static readonly IFieldType MAGNIFICATION_FACTOR = new FieldType("MAGNIFICATION_FACTOR");
public static readonly IFieldType PIXEL_SIZE = new FieldType("PIXEL_SIZE");
public static readonly IFieldType PREVIEW_QUALITY = new FieldType("PREVIEW_QUALITY");
public static readonly IFieldType SHADOW = new FieldType("SHADOW");
public static readonly IFieldType PREPARED_FILTER_OBFUSCATE = new FieldType("PREPARED_FILTER_OBFUSCATE");
public static readonly IFieldType PREPARED_FILTER_HIGHLIGHT = new FieldType("PREPARED_FILTER_HIGHLIGHT");
public static readonly IFieldType FLAGS = new FieldType("FLAGS");
public static readonly IFieldType ARROWHEADS = new FieldType(nameof(ARROWHEADS));
public static readonly IFieldType BLUR_RADIUS = new FieldType(nameof(BLUR_RADIUS));
public static readonly IFieldType BRIGHTNESS = new FieldType(nameof(BRIGHTNESS));
public static readonly IFieldType FILL_COLOR = new FieldType(nameof(FILL_COLOR));
public static readonly IFieldType FONT_BOLD = new FieldType(nameof(FONT_BOLD));
public static readonly IFieldType FONT_FAMILY = new FieldType(nameof(FONT_FAMILY));
public static readonly IFieldType FONT_ITALIC = new FieldType(nameof(FONT_ITALIC));
public static readonly IFieldType FONT_SIZE = new FieldType(nameof(FONT_SIZE));
public static readonly IFieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType(nameof(TEXT_HORIZONTAL_ALIGNMENT));
public static readonly IFieldType TEXT_VERTICAL_ALIGNMENT = new FieldType(nameof(TEXT_VERTICAL_ALIGNMENT));
public static readonly IFieldType HIGHLIGHT_COLOR = new FieldType(nameof(HIGHLIGHT_COLOR));
public static readonly IFieldType LINE_COLOR = new FieldType(nameof(LINE_COLOR));
public static readonly IFieldType LINE_THICKNESS = new FieldType(nameof(LINE_THICKNESS));
public static readonly IFieldType MAGNIFICATION_FACTOR = new FieldType(nameof(MAGNIFICATION_FACTOR));
public static readonly IFieldType PIXEL_SIZE = new FieldType(nameof(PIXEL_SIZE));
public static readonly IFieldType PREVIEW_QUALITY = new FieldType(nameof(PREVIEW_QUALITY));
public static readonly IFieldType SHADOW = new FieldType(nameof(SHADOW));
public static readonly IFieldType PREPARED_FILTER_OBFUSCATE = new FieldType(nameof(PREPARED_FILTER_OBFUSCATE));
public static readonly IFieldType PREPARED_FILTER_HIGHLIGHT = new FieldType(nameof(PREPARED_FILTER_HIGHLIGHT));
public static readonly IFieldType FLAGS = new FieldType(nameof(FLAGS));
public static readonly IFieldType CROPMODE = new FieldType(nameof(CROPMODE));
public static IFieldType[] Values =
{
ARROWHEADS, BLUR_RADIUS, BRIGHTNESS, FILL_COLOR, FONT_BOLD, FONT_FAMILY, FONT_ITALIC, FONT_SIZE, TEXT_HORIZONTAL_ALIGNMENT, TEXT_VERTICAL_ALIGNMENT, HIGHLIGHT_COLOR,
LINE_COLOR, LINE_THICKNESS, MAGNIFICATION_FACTOR, PIXEL_SIZE, PREVIEW_QUALITY, SHADOW, PREPARED_FILTER_OBFUSCATE, PREPARED_FILTER_HIGHLIGHT, FLAGS
LINE_COLOR, LINE_THICKNESS, MAGNIFICATION_FACTOR, PIXEL_SIZE, PREVIEW_QUALITY, SHADOW, PREPARED_FILTER_OBFUSCATE, PREPARED_FILTER_HIGHLIGHT, FLAGS, CROPMODE
};
public string Name { get; set; }

View file

@ -26,6 +26,7 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;
using Greenshot.Base.Controls;
@ -710,7 +711,7 @@ namespace Greenshot.Editor.Drawing
BinaryFormatter binaryRead = new BinaryFormatter();
IDrawableContainerList loadedElements = (IDrawableContainerList) binaryRead.Deserialize(streamRead);
loadedElements.Parent = this;
// Make sure the steplabels are sorted accoring to their number
// Make sure the steplabels are sorted according to their number
_stepLabels.Sort((p1, p2) => p1.Number.CompareTo(p2.Number));
DeselectAllElements();
AddElements(loadedElements);
@ -972,16 +973,17 @@ namespace Greenshot.Editor.Drawing
/// <summary>
/// Auto crop the image
/// </summary>
/// <param name="cropArea">Rectangle with optional area to find a crop region</param>
/// <returns>true if cropped</returns>
public bool AutoCrop()
public bool AutoCrop(Rectangle? cropArea = null)
{
Rectangle cropRectangle;
using (Image tmpImage = GetImageForExport())
{
cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, conf.AutoCropDifference);
cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, conf.AutoCropDifference, cropArea);
}
if (!IsCropPossible(ref cropRectangle))
if (!IsCropPossible(ref cropRectangle, CropContainer.CropModes.AutoCrop))
{
return false;
}
@ -1060,11 +1062,13 @@ namespace Greenshot.Editor.Drawing
/// <summary>
/// check if a crop is possible
/// </summary>
/// <param name="cropRectangle"></param>
/// <param name="cropRectangle">Rectangle adapted to the dimensions of the image</param>
/// <param name="cropMode">CropModes</param>
/// <returns>true if this is possible</returns>
public bool IsCropPossible(ref Rectangle cropRectangle)
public bool IsCropPossible(ref Rectangle cropRectangle, CropContainer.CropModes cropMode)
{
cropRectangle = GuiRectangle.GetGuiRectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, cropRectangle.Height);
//Fitting the rectangle to the dimensions of the image
if (cropRectangle.Left < 0)
{
cropRectangle = new Rectangle(0, cropRectangle.Top, cropRectangle.Width + cropRectangle.Left, cropRectangle.Height);
@ -1085,6 +1089,21 @@ namespace Greenshot.Editor.Drawing
cropRectangle = new Rectangle(cropRectangle.Left, cropRectangle.Top, cropRectangle.Width, Image.Height - cropRectangle.Top);
}
// special condition for vertical
if(cropMode == CropContainer.CropModes.Vertical && cropRectangle.Width == Image.Width)
{
//crop out the hole image is not allowed
return false;
}
// special condition for vertical
if (cropMode == CropContainer.CropModes.Horizontal && cropRectangle.Height == Image.Height)
{
//crop out the hole image is not allowed
return false;
}
//condition for all other crop modes
if (cropRectangle.Height > 0 && cropRectangle.Width > 0)
{
return true;
@ -1101,16 +1120,15 @@ namespace Greenshot.Editor.Drawing
/// <param name="message">Message itself</param>
public void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message)
{
if (_surfaceMessage != null)
if (_surfaceMessage == null) return;
var eventArgs = new SurfaceMessageEventArgs
{
var eventArgs = new SurfaceMessageEventArgs
{
Message = message,
MessageType = messageType,
Surface = this
};
_surfaceMessage(source, eventArgs);
}
Message = message,
MessageType = messageType,
Surface = this
};
_surfaceMessage(source, eventArgs);
}
/// <summary>
@ -1118,16 +1136,15 @@ namespace Greenshot.Editor.Drawing
/// </summary>
/// <param name="source">Who send</param>
/// <param name="color">new color</param>
public void UpdateForegroundColorEvent(object source, Color color)
private void UpdateForegroundColorEvent(object source, Color color)
{
if (_foregroundColorChanged != null)
if (_foregroundColorChanged == null) return;
var eventArgs = new SurfaceForegroundColorEventArgs
{
var eventArgs = new SurfaceForegroundColorEventArgs
{
Color = color,
};
_foregroundColorChanged(source, eventArgs);
}
Color = color,
};
_foregroundColorChanged(source, eventArgs);
}
/// <summary>
@ -1135,16 +1152,15 @@ namespace Greenshot.Editor.Drawing
/// </summary>
/// <param name="source">Who send</param>
/// <param name="color">new color</param>
public void UpdateBackgroundColorEvent(object source, Color color)
private void UpdateBackgroundColorEvent(object source, Color color)
{
if (_lineThicknessChanged != null)
if (_lineThicknessChanged == null) return;
var eventArgs = new SurfaceBackgroundColorEventArgs
{
var eventArgs = new SurfaceBackgroundColorEventArgs
{
Color = color,
};
_backgroundColorChanged(source, eventArgs);
}
Color = color,
};
_backgroundColorChanged(source, eventArgs);
}
/// <summary>
@ -1152,16 +1168,15 @@ namespace Greenshot.Editor.Drawing
/// </summary>
/// <param name="source">Who send</param>
/// <param name="thickness">new thickness</param>
public void UpdateLineThicknessEvent(object source, int thickness)
private void UpdateLineThicknessEvent(object source, int thickness)
{
if (_lineThicknessChanged != null)
if (_lineThicknessChanged == null) return;
var eventArgs = new SurfaceLineThicknessEventArgs
{
var eventArgs = new SurfaceLineThicknessEventArgs
{
Thickness = thickness,
};
_lineThicknessChanged(source, eventArgs);
}
Thickness = thickness,
};
_lineThicknessChanged(source, eventArgs);
}
/// <summary>
@ -1169,61 +1184,173 @@ namespace Greenshot.Editor.Drawing
/// </summary>
/// <param name="source">Who send</param>
/// <param name="hasShadow">has shadow</param>
public void UpdateShadowEvent(object source, bool hasShadow)
private void UpdateShadowEvent(object source, bool hasShadow)
{
if (_shadowChanged != null)
{
var eventArgs = new SurfaceShadowEventArgs
{
HasShadow = hasShadow,
};
_shadowChanged(source, eventArgs);
}
if (_shadowChanged == null) return;
var eventArgs = new SurfaceShadowEventArgs
{
HasShadow = hasShadow,
};
_shadowChanged(source, eventArgs);
}
/// <summary>
/// Crop the surface
/// </summary>
/// <param name="cropRectangle"></param>
/// <returns></returns>
/// <param name="cropRectangle">rectangle that remains</param>
/// <returns>bool</returns>
public bool ApplyCrop(Rectangle cropRectangle)
{
if (IsCropPossible(ref cropRectangle))
if (!IsCropPossible(ref cropRectangle, CropContainer.CropModes.Default)) return false;
Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
Bitmap tmpImage;
// Make sure we have information, this this fails
try
{
Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
Bitmap tmpImage;
// Make sure we have information, this this fails
try
{
tmpImage = ImageHelper.CloneArea(Image, cropRectangle, PixelFormat.DontCare);
}
catch (Exception ex)
{
ex.Data.Add("CropRectangle", cropRectangle);
ex.Data.Add("Width", Image.Width);
ex.Data.Add("Height", Image.Height);
ex.Data.Add("Pixelformat", Image.PixelFormat);
throw;
}
Matrix matrix = new Matrix();
matrix.Translate(-cropRectangle.Left, -cropRectangle.Top, MatrixOrder.Append);
// Make undoable
MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false);
// Do not dispose otherwise we can't undo the image!
SetImage(tmpImage, false);
_elements.Transform(matrix);
if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, tmpImage.Size)))
{
_surfaceSizeChanged(this, null);
}
Invalidate();
return true;
tmpImage = ImageHelper.CloneArea(Image, cropRectangle, PixelFormat.DontCare);
}
catch (Exception ex)
{
ex.Data.Add("CropRectangle", cropRectangle);
ex.Data.Add("Width", Image.Width);
ex.Data.Add("Height", Image.Height);
ex.Data.Add("Pixelformat", Image.PixelFormat);
throw;
}
return false;
var matrix = new Matrix();
matrix.Translate(-cropRectangle.Left, -cropRectangle.Top, MatrixOrder.Append);
// Make undoable
MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false);
// Do not dispose otherwise we can't undo the image!
SetImage(tmpImage, false);
_elements.Transform(matrix);
if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, tmpImage.Size)))
{
_surfaceSizeChanged(this, null);
}
Invalidate();
return true;
}
/// <summary>
/// Crop out the surface
/// Splits the image in 3 parts(top, middle, bottom). Crop out the middle and joins top and bottom.
/// </summary>
/// <param name="cropRectangle">rectangle of the middle part</param>
/// <returns>bool</returns>
private bool ApplyHorizontalCrop(Rectangle cropRectangle)
{
if (!IsCropPossible(ref cropRectangle, CropContainer.CropModes.Horizontal)) return false;
var imageRectangle = new Rectangle(Point.Empty, Image.Size);
var topRectangle = new Rectangle(0, 0, Image.Size.Width, cropRectangle.Top);
var bottomRectangle = new Rectangle(0, cropRectangle.Top + cropRectangle.Height, Image.Size.Width, Image.Size.Height - cropRectangle.Top - cropRectangle.Height);
Bitmap newImage;
try
{
newImage = new Bitmap(Image.Size.Width, Image.Size.Height - cropRectangle.Height);
using var graphics = Graphics.FromImage(newImage);
var insertPositionTop = 0;
if (topRectangle.Height > 0)
{
graphics.DrawImage(Image, new Rectangle(0, insertPositionTop, topRectangle.Width, topRectangle.Height), topRectangle, GraphicsUnit.Pixel);
insertPositionTop += topRectangle.Height;
}
if (bottomRectangle.Height > 0)
{
graphics.DrawImage(Image, new Rectangle(0, insertPositionTop, bottomRectangle.Width, bottomRectangle.Height), bottomRectangle, GraphicsUnit.Pixel);
}
}
catch (Exception ex)
{
ex.Data.Add("CropRectangle", cropRectangle);
ex.Data.Add("Width", Image.Width);
ex.Data.Add("Height", Image.Height);
ex.Data.Add("Pixelformat", Image.PixelFormat);
throw;
}
var matrix = new Matrix();
matrix.Translate(0, -(cropRectangle.Top + cropRectangle.Height), MatrixOrder.Append);
// Make undoable
MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false);
// Do not dispose otherwise we can't undo the image!
SetImage(newImage, false);
_elements.Transform(matrix);
if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size)))
{
_surfaceSizeChanged(this, null);
}
Invalidate();
return true;
}
/// <summary>
/// Crop out the surface
/// Splits the image in 3 parts(left, middle, right). Crop out the middle and joins top and bottom.
/// </summary>
/// <param name="cropRectangle">rectangle of the middle part</param>
/// <returns>bool</returns>
private bool ApplyVerticalCrop(Rectangle cropRectangle)
{
if (!IsCropPossible(ref cropRectangle, CropContainer.CropModes.Vertical)) return false;
var imageRectangle = new Rectangle(Point.Empty, Image.Size);
var leftRectangle = new Rectangle(0, 0, cropRectangle.Left, Image.Size.Height);
var rightRectangle = new Rectangle(cropRectangle.Left + cropRectangle.Width, 0, Image.Size.Width - cropRectangle.Width - cropRectangle.Left, Image.Size.Height);
Bitmap newImage;
try
{
newImage = new Bitmap(Image.Size.Width - cropRectangle.Width, Image.Size.Height);
using var graphics = Graphics.FromImage(newImage);
var insertPositionLeft = 0;
if (leftRectangle.Width > 0)
{
graphics.DrawImage(Image, new Rectangle(insertPositionLeft, 0, leftRectangle.Width, leftRectangle.Height), leftRectangle , GraphicsUnit.Pixel);
insertPositionLeft += leftRectangle.Width;
}
if (rightRectangle.Width > 0)
{
graphics.DrawImage(Image, new Rectangle(insertPositionLeft, 0, rightRectangle.Width, rightRectangle.Height), rightRectangle, GraphicsUnit.Pixel);
}
}
catch (Exception ex)
{
ex.Data.Add("CropRectangle", cropRectangle);
ex.Data.Add("Width", Image.Width);
ex.Data.Add("Height", Image.Height);
ex.Data.Add("Pixelformat", Image.PixelFormat);
throw;
}
var matrix = new Matrix();
matrix.Translate(-cropRectangle.Left - cropRectangle.Width, 0, MatrixOrder.Append);
// Make undoable
MakeUndoable(new SurfaceBackgroundChangeMemento(this, matrix), false);
// Do not dispose otherwise we can't undo the image!
SetImage(newImage, false);
_elements.Transform(matrix);
if (_surfaceSizeChanged != null && !imageRectangle.Equals(new Rectangle(Point.Empty, newImage.Size)))
{
_surfaceSizeChanged(this, null);
}
Invalidate();
return true;
}
/// <summary>
@ -1255,15 +1382,14 @@ namespace Greenshot.Editor.Drawing
{
foreach (IAdorner adorner in drawableContainer.Adorners)
{
if (adorner.IsActive || adorner.HitTest(mouseEventArgs.Location))
if (!adorner.IsActive && !adorner.HitTest(mouseEventArgs.Location)) continue;
if (adorner.Cursor != null)
{
if (adorner.Cursor != null)
{
Cursor = adorner.Cursor;
}
return adorner;
Cursor = adorner.Cursor;
}
return adorner;
}
}
@ -1494,48 +1620,47 @@ namespace Greenshot.Editor.Drawing
Cursor = DrawingMode != DrawingModes.None ? Cursors.Cross : Cursors.Default;
if (_mouseDown)
if (!_mouseDown) return;
if (_mouseDownElement != null)
{
if (_mouseDownElement != null)
// an element is currently dragged
_mouseDownElement.Invalidate();
selectedElements.Invalidate();
// Move the element
if (_mouseDownElement.Selected)
{
// an element is currently dragged
_mouseDownElement.Invalidate();
selectedElements.Invalidate();
// Move the element
if (_mouseDownElement.Selected)
if (!_isSurfaceMoveMadeUndoable)
{
if (!_isSurfaceMoveMadeUndoable)
{
// Only allow one undoable per mouse-down/move/up "cycle"
_isSurfaceMoveMadeUndoable = true;
selectedElements.MakeBoundsChangeUndoable(false);
}
// dragged element has been selected before -> move all
selectedElements.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y);
}
else
{
if (!_isSurfaceMoveMadeUndoable)
{
// Only allow one undoable per mouse-down/move/up "cycle"
_isSurfaceMoveMadeUndoable = true;
_mouseDownElement.MakeBoundsChangeUndoable(false);
}
// dragged element is not among selected elements -> just move dragged one
_mouseDownElement.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y);
// Only allow one undoable per mouse-down/move/up "cycle"
_isSurfaceMoveMadeUndoable = true;
selectedElements.MakeBoundsChangeUndoable(false);
}
_mouseStart = currentMouse;
_mouseDownElement.Invalidate();
_modified = true;
// dragged element has been selected before -> move all
selectedElements.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y);
}
else if (_drawingElement != null)
else
{
_drawingElement.HandleMouseMove(currentMouse.X, currentMouse.Y);
_modified = true;
if (!_isSurfaceMoveMadeUndoable)
{
// Only allow one undoable per mouse-down/move/up "cycle"
_isSurfaceMoveMadeUndoable = true;
_mouseDownElement.MakeBoundsChangeUndoable(false);
}
// dragged element is not among selected elements -> just move dragged one
_mouseDownElement.MoveBy(currentMouse.X - _mouseStart.X, currentMouse.Y - _mouseStart.Y);
}
_mouseStart = currentMouse;
_mouseDownElement.Invalidate();
_modified = true;
}
else if (_drawingElement != null)
{
_drawingElement.HandleMouseMove(currentMouse.X, currentMouse.Y);
_modified = true;
}
}
@ -1795,7 +1920,7 @@ namespace Greenshot.Editor.Drawing
element.Invalidate();
}
if (makeUndoable)
if (makeUndoable && element.IsUndoable)
{
MakeUndoable(new AddElementMemento(this, element), false);
}
@ -1811,11 +1936,17 @@ namespace Greenshot.Editor.Drawing
public void RemoveElements(IDrawableContainerList elementsToRemove, bool makeUndoable = true)
{
// fix potential issues with iterating a changing list
DrawableContainerList cloned = new DrawableContainerList();
cloned.AddRange(elementsToRemove);
DrawableContainerList cloned = new DrawableContainerList(elementsToRemove);
if (makeUndoable)
{
MakeUndoable(new DeleteElementsMemento(this, cloned), false);
// Take all containers to make undoable
var undoableContainers = elementsToRemove.Where(c => c.IsUndoable).ToList();
if (undoableContainers.Any())
{
var undoableContainerList = new DrawableContainerList(undoableContainers);
MakeUndoable(new DeleteElementsMemento(this, undoableContainerList), false);
}
}
SuspendLayout();
@ -1863,7 +1994,7 @@ namespace Greenshot.Editor.Drawing
Invalidate();
}
if (makeUndoable)
if (makeUndoable && elementToRemove is { IsUndoable: true })
{
MakeUndoable(new DeleteElementMemento(this, elementToRemove), false);
}
@ -1879,11 +2010,16 @@ namespace Greenshot.Editor.Drawing
public void AddElements(IDrawableContainerList elementsToAdd, bool makeUndoable = true)
{
// fix potential issues with iterating a changing list
DrawableContainerList cloned = new DrawableContainerList();
cloned.AddRange(elementsToAdd);
DrawableContainerList cloned = new DrawableContainerList(elementsToAdd);
if (makeUndoable)
{
MakeUndoable(new AddElementsMemento(this, cloned), false);
// Take all containers to make undoable
var undoableContainers = elementsToAdd.Where(c => c.IsUndoable).ToList();
if (undoableContainers.Any())
{
var undoableContainerList = new DrawableContainerList(undoableContainers);
MakeUndoable(new AddElementsMemento(this, undoableContainerList), false);
}
}
SuspendLayout();
@ -1925,11 +2061,9 @@ namespace Greenshot.Editor.Drawing
/// </summary>
public void CutSelectedElements()
{
if (HasSelectedElements)
{
ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements);
RemoveSelectedElements();
}
if (!HasSelectedElements) return;
ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements);
RemoveSelectedElements();
}
/// <summary>
@ -1937,38 +2071,96 @@ namespace Greenshot.Editor.Drawing
/// </summary>
public void CopySelectedElements()
{
if (HasSelectedElements)
if (!HasSelectedElements) return;
ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements);
}
/// <summary>
/// This method is called to confirm/cancel.
/// Called when pressing enter or using the "check" in the editor.
/// redirects to the specialized confirm/cancel method
/// </summary>
/// <param name="confirm">bool</param>
public void Confirm(bool confirm)
{
if (DrawingMode == DrawingModes.Crop)
{
ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), selectedElements);
ConfirmCrop(confirm);
}
else
{
ConfirmSelectedConfirmableElements(confirm);
}
}
/// <summary>
/// This method is called to confirm/cancel "confirmable" elements, like the crop-container.
/// This method is called to confirm/cancel "confirmable" elements
/// Called when pressing enter or using the "check" in the editor.
/// <br/>
/// For crop-container there is a dedicated method <see cref="ConfirmCrop(bool)"/>.
/// </summary>
/// <param name="confirm"></param>
/// <param name="confirm">bool</param>
public void ConfirmSelectedConfirmableElements(bool confirm)
{
// create new collection so that we can iterate safely (selectedElements might change due with confirm/cancel)
List<IDrawableContainer> selectedDCs = new List<IDrawableContainer>(selectedElements);
foreach (IDrawableContainer dc in selectedDCs)
{
if (dc.Equals(_cropContainer))
{
DrawingMode = DrawingModes.None;
// No undo memento for the cropcontainer itself, only for the effect
RemoveElement(_cropContainer, false);
if (confirm)
{
ApplyCrop(_cropContainer.Bounds);
}
_cropContainer.Dispose();
_cropContainer = null;
break;
}
{
throw new NotImplementedException($"No confirm/cancel defined for Container type {dc.GetType()}");
}
// maybe the undo button has to be enabled
if (_movingElementChanged != null)
{
_movingElementChanged(this, new SurfaceElementEventArgs());
}
}
/// <summary>
/// This method is called to confirm/cancel the crop-container.
/// Called when pressing enter or using the "check" in the editor.
/// </summary>
/// <param name="confirm">bool</param>
public void ConfirmCrop(bool confirm)
{
if (_cropContainer is not CropContainer e) return;
if (confirm && selectedElements.Count > 0)
{
// No undo memento for the cropcontainer itself, only for the effect
RemoveElement(_cropContainer, false);
_ = e.GetFieldValue(FieldType.CROPMODE) switch
{
CropContainer.CropModes.Horizontal => ApplyHorizontalCrop(_cropContainer.Bounds),
CropContainer.CropModes.Vertical => ApplyVerticalCrop(_cropContainer.Bounds),
_ => ApplyCrop(_cropContainer.Bounds)
};
_cropContainer.Dispose();
_cropContainer = null;
}
else
{
RemoveCropContainer();
}
DrawingMode = DrawingModes.None;
// maybe the undo button has to be enabled
if (_movingElementChanged != null)
{
_movingElementChanged(this, new SurfaceElementEventArgs());
}
}
public void RemoveCropContainer()
{
if (_cropContainer == null) return;
RemoveElement(_cropContainer, false);
_cropContainer.Dispose();
_cropContainer = null;
}
/// <summary>
@ -2144,13 +2336,13 @@ namespace Greenshot.Editor.Drawing
/// <summary>
/// Get the rectangle bounding all selected elements (in surface coordinates space),
/// or empty rectangle if nothing is selcted.
/// or empty rectangle if nothing is selected.
/// </summary>
public Rectangle GetSelectionRectangle()
=> ToSurfaceCoordinates(selectedElements.DrawingBounds);
/// <summary>
/// Duplicate all the selecteded elements
/// Duplicate all the selected elements
/// </summary>
public void DuplicateSelectedElements()
{
@ -2289,7 +2481,7 @@ namespace Greenshot.Editor.Drawing
/// <returns>false if no keys were processed</returns>
public bool ProcessCmdKey(Keys k)
{
if (selectedElements.Count <= 0) return false;
if (selectedElements.Count <= 0 && k != Keys.Escape) return false;
bool shiftModifier = (ModifierKeys & Keys.Shift) == Keys.Shift;
int px = shiftModifier ? 10 : 1;
@ -2325,10 +2517,10 @@ namespace Greenshot.Editor.Drawing
PushElementsToBottom();
break;
case Keys.Enter:
ConfirmSelectedConfirmableElements(true);
Confirm(true);
break;
case Keys.Escape:
ConfirmSelectedConfirmableElements(false);
Confirm(false);
break;
case Keys.D0 | Keys.Control:
case Keys.D0 | Keys.Shift | Keys.Control:
@ -2487,7 +2679,7 @@ namespace Greenshot.Editor.Drawing
return _elements.CanPushDown(selectedElements);
}
public void Element_FieldChanged(object sender, FieldChangedEventArgs e)
private void Element_FieldChanged(object sender, FieldChangedEventArgs e)
{
selectedElements.HandleFieldChangedEvent(sender, e);
}
@ -2545,20 +2737,18 @@ namespace Greenshot.Editor.Drawing
{
return rc;
}
else
Point[] points =
{
Point[] points =
{
rc.Location, rc.Location + rc.Size
};
_inverseZoomMatrix.TransformPoints(points);
return new Rectangle(
points[0].X,
points[0].Y,
points[1].X - points[0].X,
points[1].Y - points[0].Y
);
}
rc.Location, rc.Location + rc.Size
};
_inverseZoomMatrix.TransformPoints(points);
return new Rectangle(
points[0].X,
points[0].Y,
points[1].X - points[0].X,
points[1].Y - points[0].Y
);
}
}
}

View file

@ -74,7 +74,7 @@ namespace Greenshot.Editor.Drawing
{
if ((text != null || newText == null) && string.Equals(text, newText)) return;
if (makeUndoable && allowUndoable)
if (makeUndoable && allowUndoable && IsUndoable)
{
makeUndoable = false;
_parent.MakeUndoable(new TextChangeMemento(this), false);

View file

@ -98,8 +98,6 @@ namespace Greenshot.Editor.Forms {
this.toolStripSeparator12 = new System.Windows.Forms.ToolStripSeparator();
this.preferencesToolStripMenuItem = new GreenshotToolStripMenuItem();
this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator();
this.autoCropToolStripMenuItem = new GreenshotToolStripMenuItem();
this.toolStripSeparator17 = new System.Windows.Forms.ToolStripSeparator();
this.insert_window_toolstripmenuitem = new GreenshotToolStripMenuItem();
this.objectToolStripMenuItem = new GreenshotToolStripMenuItem();
this.addRectangleToolStripMenuItem = new GreenshotToolStripMenuItem();
@ -144,8 +142,13 @@ namespace Greenshot.Editor.Forms {
this.btnHelp = new GreenshotToolStripButton();
this.propertiesToolStrip = new ToolStripEx();
this.obfuscateModeButton = new BindableToolStripDropDownButton();
this.cropModeButton = new BindableToolStripDropDownButton();
this.pixelizeToolStripMenuItem = new GreenshotToolStripMenuItem();
this.blurToolStripMenuItem = new GreenshotToolStripMenuItem();
this.defaultCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
this.verticalCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
this.horizontalCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
this.autoCropModeToolStripMenuItem = new GreenshotToolStripMenuItem();
this.highlightModeButton = new BindableToolStripDropDownButton();
this.textHighlightMenuItem = new GreenshotToolStripMenuItem();
this.areaHighlightMenuItem = new GreenshotToolStripMenuItem();
@ -593,8 +596,6 @@ namespace Greenshot.Editor.Forms {
this.toolStripSeparator12,
this.preferencesToolStripMenuItem,
this.toolStripSeparator5,
this.autoCropToolStripMenuItem,
this.toolStripSeparator17,
this.insert_window_toolstripmenuitem});
this.editToolStripMenuItem.LanguageKey = "editor_edit";
this.editToolStripMenuItem.Name = "editToolStripMenuItem";
@ -678,16 +679,6 @@ namespace Greenshot.Editor.Forms {
//
this.toolStripSeparator5.Name = "toolStripSeparator5";
//
// autoCropToolStripMenuItem
//
this.autoCropToolStripMenuItem.LanguageKey = "editor_autocrop";
this.autoCropToolStripMenuItem.Name = "autoCropToolStripMenuItem";
this.autoCropToolStripMenuItem.Click += new System.EventHandler(this.AutoCropToolStripMenuItemClick);
//
// toolStripSeparator17
//
this.toolStripSeparator17.Name = "toolStripSeparator17";
//
// insert_window_toolstripmenuitem
//
this.insert_window_toolstripmenuitem.LanguageKey = "editor_insertwindow";
@ -1082,6 +1073,7 @@ namespace Greenshot.Editor.Forms {
this.toolStripSeparator10,
this.btnConfirm,
this.btnCancel,
this.cropModeButton,
this.counterLabel,
this.counterUpDown});
//
@ -1098,6 +1090,7 @@ namespace Greenshot.Editor.Forms {
this.obfuscateModeButton.SelectedTag = FilterContainer.PreparedFilter.BLUR;
this.obfuscateModeButton.Tag = FilterContainer.PreparedFilter.BLUR;
//
this.obfuscateModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
// pixelizeToolStripMenuItem
//
this.pixelizeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("pixelizeToolStripMenuItem.Image")));
@ -1111,6 +1104,55 @@ namespace Greenshot.Editor.Forms {
this.blurToolStripMenuItem.LanguageKey = "editor_obfuscate_blur";
this.blurToolStripMenuItem.Name = "blurToolStripMenuItem";
this.blurToolStripMenuItem.Tag = FilterContainer.PreparedFilter.BLUR;
//
// cropModeButton
//
this.cropModeButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
this.cropModeButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
this.defaultCropModeToolStripMenuItem,
this.verticalCropModeToolStripMenuItem,
this.horizontalCropModeToolStripMenuItem,
this.autoCropModeToolStripMenuItem});
this.cropModeButton.Image = ((System.Drawing.Image)(resources.GetObject("btnCrop.Image")));
this.cropModeButton.ImageTransparentColor = System.Drawing.Color.Magenta;
this.cropModeButton.LanguageKey = "editor_crop_mode";
this.cropModeButton.Name = "cropModeButton";
this.cropModeButton.SelectedTag = CropContainer.CropModes.Default;
this.cropModeButton.Tag = CropContainer.CropModes.Default;
this.cropModeButton.DropDownItemClicked += CropStyleDropDownItemClicked;
//
// defaultCropStyleToolStripMenuItem
//
this.defaultCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnCrop.Image")));
this.defaultCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_default";
this.defaultCropModeToolStripMenuItem.Name = "defaultCropModeToolStripMenuItem";
this.defaultCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Default;
//
// verticalCropStyleToolStripMenuItem
//
this.verticalCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("CropVertical.Image")));
this.verticalCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_vertical";
this.verticalCropModeToolStripMenuItem.Name = "verticalCropModeToolStripMenuItem";
this.verticalCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Vertical;
//
// horizontalCropStyleToolStripMenuItem
//
this.horizontalCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("CropHorizontal.Image")));
this.horizontalCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_horizontal";
this.horizontalCropModeToolStripMenuItem.Name = "horizontalCropModeToolStripMenuItem";
this.horizontalCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Horizontal;
//
// autoCropModeToolStripMenuItem
//
this.autoCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("AutoCrop.Image")));
this.autoCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_auto";
this.autoCropModeToolStripMenuItem.Name = "autoCropModeToolStripMenuItem";
this.autoCropModeToolStripMenuItem.Tag = CropContainer.CropModes.AutoCrop;
//
// highlightModeButton
//
@ -1126,6 +1168,7 @@ namespace Greenshot.Editor.Forms {
this.highlightModeButton.Name = "highlightModeButton";
this.highlightModeButton.SelectedTag = FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
this.highlightModeButton.Tag = FilterContainer.PreparedFilter.TEXT_HIGHTLIGHT;
this.highlightModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
//
// textHighlightMenuItem
//
@ -1233,6 +1276,7 @@ namespace Greenshot.Editor.Forms {
this.fontFamilyComboBox.Padding = new System.Windows.Forms.Padding(2,0,0,2);
this.fontFamilyComboBox.GotFocus += new System.EventHandler(this.ToolBarFocusableElementGotFocus);
this.fontFamilyComboBox.LostFocus += new System.EventHandler(this.ToolBarFocusableElementLostFocus);
this.fontFamilyComboBox.PropertyChanged += FontPropertyChanged;
//
// fontSizeLabel
//
@ -1873,6 +1917,11 @@ namespace Greenshot.Editor.Forms {
private BindableToolStripButton btnConfirm;
private GreenshotToolStripMenuItem selectAllToolStripMenuItem;
private BindableToolStripDropDownButton highlightModeButton;
private BindableToolStripDropDownButton cropModeButton;
private GreenshotToolStripMenuItem defaultCropModeToolStripMenuItem;
private GreenshotToolStripMenuItem verticalCropModeToolStripMenuItem;
private GreenshotToolStripMenuItem horizontalCropModeToolStripMenuItem;
private GreenshotToolStripMenuItem autoCropModeToolStripMenuItem;
private GreenshotToolStripMenuItem pixelizeToolStripMenuItem;
private GreenshotToolStripMenuItem blurToolStripMenuItem;
private BindableToolStripDropDownButton obfuscateModeButton;

View file

@ -25,6 +25,7 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows.Forms;
using Greenshot.Base;
@ -181,6 +182,9 @@ namespace Greenshot.Editor.Forms
UpdateUi();
// Workaround: for the MouseWheel event which doesn't get to the panel
MouseWheel += PanelMouseWheel;
// Use best fit, for those capture modes where we can get huge images
bool useBestFit = _surface.CaptureDetails.CaptureMode switch
{
@ -280,11 +284,6 @@ namespace Greenshot.Editor.Forms
// a smaller size than the initial panel size (as set by the forms designer)
panel1.Height = 10;
fontFamilyComboBox.PropertyChanged += FontPropertyChanged;
obfuscateModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
highlightModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked;
_toolbarButtons = new[]
{
btnCursor, btnRect, btnEllipse, btnText, btnLine, btnArrow, btnFreehand, btnHighlight, btnObfuscate, btnCrop, btnStepLabel, btnSpeechBubble
@ -293,9 +292,6 @@ namespace Greenshot.Editor.Forms
pluginToolStripMenuItem.Visible = pluginToolStripMenuItem.DropDownItems.Count > 0;
// Workaround: for the MouseWheel event which doesn't get to the panel
MouseWheel += PanelMouseWheel;
// Make sure the value is set correctly when starting
if (Surface != null)
{
@ -727,7 +723,10 @@ namespace Greenshot.Editor.Forms
private void BtnCropClick(object sender, EventArgs e)
{
if (_surface.DrawingMode == DrawingModes.Crop) return;
_surface.DrawingMode = DrawingModes.Crop;
InitCropMode((CropContainer.CropModes)_surface.FieldAggregator.GetField(FieldType.CROPMODE).Value);
RefreshFieldControls();
}
@ -1292,6 +1291,7 @@ namespace Greenshot.Editor.Forms
new BidirectionalBinding(previewQualityUpDown, "Value", _surface.FieldAggregator.GetField(FieldType.PREVIEW_QUALITY), "Value",
DecimalDoublePercentageConverter.GetInstance(), NotNullValidator.GetInstance());
new BidirectionalBinding(obfuscateModeButton, "SelectedTag", _surface.FieldAggregator.GetField(FieldType.PREPARED_FILTER_OBFUSCATE), "Value");
new BidirectionalBinding(cropModeButton, "SelectedTag", _surface.FieldAggregator.GetField(FieldType.CROPMODE), "Value");
new BidirectionalBinding(highlightModeButton, "SelectedTag", _surface.FieldAggregator.GetField(FieldType.PREPARED_FILTER_HIGHLIGHT), "Value");
new BidirectionalBinding(counterUpDown, "Value", _surface, "CounterStart", DecimalIntConverter.GetInstance(), NotNullValidator.GetInstance());
}
@ -1321,12 +1321,13 @@ namespace Greenshot.Editor.Forms
textHorizontalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_HORIZONTAL_ALIGNMENT);
textVerticalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
shadowButton.Visible = props.HasFieldValue(FieldType.SHADOW);
counterLabel.Visible = counterUpDown.Visible = props.HasFieldValue(FieldType.FLAGS)
&& ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.COUNTER) == FieldFlag.COUNTER;
btnConfirm.Visible = btnCancel.Visible = props.HasFieldValue(FieldType.FLAGS)
&& ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE;
counterLabel.Visible = counterUpDown.Visible = props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS)).HasFlag(FieldFlag.COUNTER);
btnConfirm.Visible = btnCancel.Visible = props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS)).HasFlag(FieldFlag.CONFIRMABLE);
btnConfirm.Enabled = _surface.HasSelectedElements;
obfuscateModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE);
cropModeButton.Visible = props.HasFieldValue(FieldType.CROPMODE);
highlightModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT);
}
else
@ -1582,6 +1583,39 @@ namespace Greenshot.Editor.Forms
Invalidate(true);
}
protected void CropStyleDropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
InitCropMode((CropContainer.CropModes)e.ClickedItem.Tag);
RefreshFieldControls();
Invalidate(true);
}
private void InitCropMode(CropContainer.CropModes mode)
{
var cropArea = _surface.Elements.FirstOrDefault(c => c is CropContainer)?.Bounds;
_surface.DrawingMode = DrawingModes.None;
_surface.RemoveCropContainer();
if (mode == CropContainer.CropModes.AutoCrop)
{
if (!_surface.AutoCrop(cropArea))
{
//not AutoCrop possible automatic switch to default crop mode
_surface.DrawingMode = DrawingModes.Crop;
_surface.FieldAggregator.GetField(FieldType.CROPMODE).Value = CropContainer.CropModes.Default;
this.cropModeButton.SelectedTag = CropContainer.CropModes.Default;
this.statusLabel.Text = Language.GetString(LangKey.editor_autocrop_not_possible);
}
}
else
{
_surface.DrawingMode = DrawingModes.Crop;
}
RefreshEditorControls();
}
private void SelectAllToolStripMenuItemClick(object sender, EventArgs e)
{
_surface.SelectAllElements();
@ -1590,14 +1624,14 @@ namespace Greenshot.Editor.Forms
private void BtnConfirmClick(object sender, EventArgs e)
{
_surface.ConfirmSelectedConfirmableElements(true);
RefreshFieldControls();
_surface.Confirm(true);
RefreshEditorControls();
}
private void BtnCancelClick(object sender, EventArgs e)
{
_surface.ConfirmSelectedConfirmableElements(false);
RefreshFieldControls();
_surface.Confirm(false);
RefreshEditorControls();
}
private void Insert_window_toolstripmenuitemMouseEnter(object sender, EventArgs e)
@ -1643,14 +1677,6 @@ namespace Greenshot.Editor.Forms
}
}
private void AutoCropToolStripMenuItemClick(object sender, EventArgs e)
{
if (_surface.AutoCrop())
{
RefreshFieldControls();
}
}
private void AddBorderToolStripMenuItemClick(object sender, EventArgs e)
{
_surface.ApplyBitmapEffect(new BorderEffect());
@ -1681,7 +1707,7 @@ namespace Greenshot.Editor.Forms
cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, coreConfiguration.AutoCropDifference);
}
if (_surface.IsCropPossible(ref cropRectangle))
if (_surface.IsCropPossible(ref cropRectangle, CropContainer.CropModes.AutoCrop))
{
_surface.ApplyCrop(cropRectangle);
UpdateUndoRedoSurfaceDependencies();

View file

@ -1107,4 +1107,13 @@
<metadata name="zoomMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>782, 17</value>
</metadata>
<data name="AutoCrop.Image" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\AutoCrop.Image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CropHorizontal.Image" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\CropHorizontal.Image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="CropVertical.Image" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\CropVertical.Image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -44,7 +44,7 @@ namespace Greenshot.Editor.Memento
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
//if (disposing) { }
_drawableContainer = null;

View file

@ -43,7 +43,7 @@ namespace Greenshot.Editor.Memento
Dispose(true);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposing)
{

View file

@ -44,7 +44,7 @@ namespace Greenshot.Editor.Memento
Dispose(true);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposing)
{

View file

@ -45,7 +45,7 @@ namespace Greenshot.Editor.Memento
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (!disposing) return;

View file

@ -43,7 +43,7 @@ namespace Greenshot.Editor.Memento
Dispose(true);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposing)
{

View file

@ -34,30 +34,30 @@ namespace Greenshot.Editor.Memento
{
private readonly List<Point> _points = new();
private readonly List<Size> _sizes = new();
private IDrawableContainerList _listOfdrawableContainer;
private IDrawableContainerList _listOfDrawableContainer;
private void StoreBounds()
{
foreach (IDrawableContainer drawableContainer in _listOfdrawableContainer)
foreach (IDrawableContainer drawableContainer in _listOfDrawableContainer)
{
_points.Add(drawableContainer.Location);
_sizes.Add(drawableContainer.Size);
}
}
public DrawableContainerBoundsChangeMemento(IDrawableContainerList listOfdrawableContainer)
public DrawableContainerBoundsChangeMemento(IDrawableContainerList listOfDrawableContainer)
{
_listOfdrawableContainer = listOfdrawableContainer;
_listOfDrawableContainer = listOfDrawableContainer;
StoreBounds();
}
public DrawableContainerBoundsChangeMemento(IDrawableContainer drawableContainer)
{
_listOfdrawableContainer = new DrawableContainerList
_listOfDrawableContainer = new DrawableContainerList
{
drawableContainer
};
_listOfdrawableContainer.Parent = drawableContainer.Parent;
_listOfDrawableContainer.Parent = drawableContainer.Parent;
StoreBounds();
}
@ -66,21 +66,21 @@ namespace Greenshot.Editor.Memento
Dispose(true);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposing)
{
_listOfdrawableContainer?.Dispose();
_listOfDrawableContainer?.Dispose();
}
_listOfdrawableContainer = null;
_listOfDrawableContainer = null;
}
public bool Merge(IMemento otherMemento)
{
if (otherMemento is not DrawableContainerBoundsChangeMemento other) return false;
if (ObjectExtensions.CompareLists(_listOfdrawableContainer, other._listOfdrawableContainer))
if (ObjectExtensions.CompareLists(_listOfDrawableContainer, other._listOfDrawableContainer))
{
// Lists are equal, as we have the state already we can ignore the new memento
return true;
@ -91,10 +91,10 @@ namespace Greenshot.Editor.Memento
public IMemento Restore()
{
var oldState = new DrawableContainerBoundsChangeMemento(_listOfdrawableContainer);
for (int index = 0; index < _listOfdrawableContainer.Count; index++)
var oldState = new DrawableContainerBoundsChangeMemento(_listOfDrawableContainer);
for (int index = 0; index < _listOfDrawableContainer.Count; index++)
{
IDrawableContainer drawableContainer = _listOfdrawableContainer[index];
IDrawableContainer drawableContainer = _listOfDrawableContainer[index];
// Before
drawableContainer.Invalidate();
drawableContainer.Left = _points[index].X;

View file

@ -52,7 +52,7 @@ namespace Greenshot.Editor.Memento
Dispose(true);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (!disposing) return;

View file

@ -43,7 +43,7 @@ namespace Greenshot.Editor.Memento
Dispose(true);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposing)
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -62,6 +62,7 @@
<resource name="editor_copypathtoclipboard">انسخ المسار الي الذاكرة</resource>
<resource name="editor_copytoclipboard">نسخ</resource>
<resource name="editor_crop">قص (C)</resource>
<resource name="editor_cropmode_default">قص</resource>
<resource name="editor_cursortool">اداة التحديد (ESC)</resource>
<resource name="editor_cuttoclipboard">قص</resource>
<resource name="editor_deleteelement">احذف</resource>

View file

@ -92,6 +92,8 @@ Abans de crear un nou informe d'error, us agrairem que comproveu que l'error no
<resource name="editor_copypathtoclipboard">Copia el camí al porta-retalls</resource>
<resource name="editor_copytoclipboard">Copia</resource>
<resource name="editor_crop">Retalla(C)</resource>
<resource name="editor_cropmode_default">Retalla</resource>
<resource name="editor_cropmode_auto">Autorretalla</resource>
<resource name="editor_cursortool">Eina de selecció (ESC)</resource>
<resource name="editor_cuttoclipboard">Retalla</resource>
<resource name="editor_deleteelement">Esborra</resource>

View file

@ -93,6 +93,8 @@ Také bychom velmi ocenili, kdybyste zkontrolovali, zda tato chyba již není ev
<resource name="editor_copypathtoclipboard">Kopírovat cestu do schránky</resource>
<resource name="editor_copytoclipboard">Kopírovat</resource>
<resource name="editor_crop">Oříznout (C)</resource>
<resource name="editor_cropmode_default">Oříznout</resource>
<resource name="editor_cropmode_auto">Automatické oříznutí</resource>
<resource name="editor_cursortool">Výběr objektů (ESC)</resource>
<resource name="editor_cuttoclipboard">Vystřihnout</resource>
<resource name="editor_deleteelement">Odstranit</resource>

View file

@ -469,6 +469,9 @@ tidspunktet, fx 11_58_32 (plus filendelsen angivet i indstillingerne).
<resource name="editor_crop">
Beskær (C)
</resource>
<resource name="editor_cropmode_default">
Beskær
</resource>
<resource name="contextmenu_captureclipboard">
Åbn billede fra udklipsholder
</resource>

View file

@ -77,6 +77,7 @@ schnell zu finden. Vielen Dank :)</resource>
<resource name="editor_arrowheads_none">Keine</resource>
<resource name="editor_arrowheads_start">Anfangspunkt</resource>
<resource name="editor_autocrop">Automatisch zuschneiden</resource>
<resource name="editor_autocrop_not_possible">Automatisches Zuschneiden nicht möglich</resource>
<resource name="editor_backcolor">Hintergrundfarbe (0-9)</resource>
<resource name="editor_blur_radius">Weichzeichner-Radius</resource>
<resource name="editor_bold">Fett</resource>
@ -92,6 +93,11 @@ schnell zu finden. Vielen Dank :)</resource>
<resource name="editor_copypathtoclipboard">Pfad in Zwischenablage kopieren</resource>
<resource name="editor_copytoclipboard">Kopieren</resource>
<resource name="editor_crop">Zuschneiden (C)</resource>
<resource name="editor_crop_mode">Zuschneiden - Modus</resource>
<resource name="editor_cropmode_default">Zuschneiden</resource>
<resource name="editor_cropmode_vertical">Vertikal ausschneiden</resource>
<resource name="editor_cropmode_horizontal">Horizontal ausschneiden</resource>
<resource name="editor_cropmode_auto">Automatisch zuschneiden</resource>
<resource name="editor_cursortool">Auswahlwerkzeug (Esc)</resource>
<resource name="editor_cuttoclipboard">Ausschneiden</resource>
<resource name="editor_deleteelement">Gewähltes Element löschen</resource>

View file

@ -88,6 +88,8 @@ Dangschee, wassd scho :)</resource>
<resource name="editor_copypathtoclipboard">Bfad in däi Zwischnblach nei</resource>
<resource name="editor_copytoclipboard">Kobiern</resource>
<resource name="editor_crop">Zamschneidn (C)</resource>
<resource name="editor_cropmode_default">Zamschneidn</resource>
<resource name="editor_cropmode_auto">Audomadisch zamschneidn</resource>
<resource name="editor_cursortool">Angriffln (ESC)</resource>
<resource name="editor_cuttoclipboard">Ausschneidn</resource>
<resource name="editor_deleteelement">Wech mid dem Ding!</resource>

View file

@ -93,6 +93,8 @@
<resource name="editor_copypathtoclipboard">Αντιγραφή της θέσης του αρχείου στο πρόχειρο</resource>
<resource name="editor_copytoclipboard">Αντιγραφή</resource>
<resource name="editor_crop">Περικοπή (C)</resource>
<resource name="editor_cropmode_default">Περικοπή</resource>
<resource name="editor_cropmode_auto">Αυτόματη Περικοπή</resource>
<resource name="editor_cursortool">Εργαλείο Επιλογής (ESC)</resource>
<resource name="editor_cuttoclipboard">Αποκοπή</resource>
<resource name="editor_deleteelement">Διαγραφή</resource>

View file

@ -78,6 +78,7 @@ Also, we would highly appreciate if you checked whether a tracker item already e
<resource name="editor_arrowheads_none">None</resource>
<resource name="editor_arrowheads_start">Start point</resource>
<resource name="editor_autocrop">Auto crop</resource>
<resource name="editor_autocrop_not_possible">Auto crop not possible</resource>
<resource name="editor_backcolor">Fill color (0-9)</resource>
<resource name="editor_blur_radius">Blur radius</resource>
<resource name="editor_bold">Bold</resource>
@ -93,6 +94,11 @@ Also, we would highly appreciate if you checked whether a tracker item already e
<resource name="editor_copypathtoclipboard">Copy path to clipboard</resource>
<resource name="editor_copytoclipboard">Copy</resource>
<resource name="editor_crop">Crop (C)</resource>
<resource name="editor_crop_mode">Crop mode</resource>
<resource name="editor_cropmode_default">Crop</resource>
<resource name="editor_cropmode_vertical">Crop out vertically</resource>
<resource name="editor_cropmode_horizontal">Crop out horizontally</resource>
<resource name="editor_cropmode_auto">Auto crop</resource>
<resource name="editor_cursortool">Selection Tool (ESC)</resource>
<resource name="editor_cuttoclipboard">Cut</resource>
<resource name="editor_deleteelement">Delete</resource>

View file

@ -80,6 +80,8 @@ Antes de crear un nuevo informe de error, te agradeceríamos que comprobaras que
<resource name="editor_copypathtoclipboard">Copiar ruta al portapapeles</resource>
<resource name="editor_copytoclipboard">Copiar</resource>
<resource name="editor_crop">Recortar(C)</resource>
<resource name="editor_cropmode_default">Recortar</resource>
<resource name="editor_cropmode_auto">Autorrecortar</resource>
<resource name="editor_cursortool">Herramienta de selección (ESC)</resource>
<resource name="editor_cuttoclipboard">Cortar</resource>
<resource name="editor_deleteelement">Borrar</resource>

View file

@ -92,6 +92,8 @@ Me oleksime väga tänulik, kui te enne kontrolliksite, ega sellest veast pole j
<resource name="editor_copypathtoclipboard">Kopeerige asukoht lõikelauale</resource>
<resource name="editor_copytoclipboard">Kopeeri</resource>
<resource name="editor_crop">Lõika (C)</resource>
<resource name="editor_cropmode_default">Lõika</resource>
<resource name="editor_cropmode_auto">Automaatne lõikus</resource>
<resource name="editor_cursortool">Valiku tööriist (ESC)</resource>
<resource name="editor_cuttoclipboard">Lõika</resource>
<resource name="editor_deleteelement">Kustuta</resource>

View file

@ -67,6 +67,7 @@ Could not save Greenshot's configuration file. Please check access permissions f
<resource name="editor_copytoclipboard">رونویس</resource>
<resource name="editor_crop">چیدن
(C دکمه)</resource>
<resource name="editor_cropmode_default">چیدن</resource>
<resource name="editor_cursortool">انتخابگر
(ESC دکمه)</resource>
<resource name="editor_cuttoclipboard">برش</resource>

View file

@ -62,6 +62,7 @@ Olisi myös hyvä jos voisit tarkistaa onko virhe jo raportoitu aikaisemmin (voi
<resource name="editor_copypathtoclipboard">Kopioi tiedostopolku leikepöydälle</resource>
<resource name="editor_copytoclipboard">Kopioi</resource>
<resource name="editor_crop">Rajaa (C)</resource>
<resource name="editor_cropmode_default">Rajaa</resource>
<resource name="editor_cursortool">Valintatyökalu (ESC)</resource>
<resource name="editor_cuttoclipboard">Leikkaa</resource>
<resource name="editor_deleteelement">Poista</resource>

View file

@ -93,6 +93,8 @@ De plus, nous apprécierions beaucoup que vous preniez la peine de vérifier si
<resource name="editor_copytoclipboard">Copier</resource>
<resource name="editor_counter">Ajouter un compteur</resource>
<resource name="editor_crop">Recadrer (C)</resource>
<resource name="editor_cropmode_default">Recadrer</resource>
<resource name="editor_cropmode_auto">Cadrage automatique</resource>
<resource name="editor_cursortool">Outil de sélection (ESC)</resource>
<resource name="editor_cuttoclipboard">Couper</resource>
<resource name="editor_deleteelement">Supprimer</resource>

View file

@ -78,6 +78,8 @@ De plus, nous apprécierions beaucoup que vous preniez la peine de vérifier si
<resource name="editor_copypathtoclipboard">Copier le chemin vers le presse-papier</resource>
<resource name="editor_copytoclipboard">Copier</resource>
<resource name="editor_crop">Rogner (C)</resource>
<resource name="editor_cropmode_default">Rogner</resource>
<resource name="editor_cropmode_auto">Rognage automatique</resource>
<resource name="editor_cursortool">Outil de sélection (ESC)</resource>
<resource name="editor_cuttoclipboard">Couper</resource>
<resource name="editor_deleteelement">Supprimer</resource>

View file

@ -63,6 +63,7 @@ Details about the GNU General Public License:</resource>
<resource name="editor_copypathtoclipboard">העתק נתיב אל הלוח</resource>
<resource name="editor_copytoclipboard">העתקה</resource>
<resource name="editor_crop">חתוך (C)</resource>
<resource name="editor_cropmode_default">חתוך</resource>
<resource name="editor_cursortool">כלי בחירה (ESC)</resource>
<resource name="editor_cuttoclipboard">חיתוך</resource>
<resource name="editor_deleteelement">מחיקה</resource>

View file

@ -63,6 +63,7 @@ Kérjük adjon összefoglaló leírást és csatoljon minden olyan információt
<resource name="editor_copypathtoclipboard">Másolja a vágólapra</resource>
<resource name="editor_copytoclipboard">Másolás</resource>
<resource name="editor_crop">Vágás eszköz (C)</resource>
<resource name="editor_cropmode_default">Vágás eszköz</resource>
<resource name="editor_cursortool">Kiválasztó eszköz (ESC)</resource>
<resource name="editor_cuttoclipboard">Kivágás</resource>
<resource name="editor_deleteelement">Törlés</resource>

View file

@ -93,6 +93,8 @@ Juga, kami sangat terbantu apabila anda mengecek laporan lain yang sama dengan k
<resource name="editor_copytoclipboard">Kopi</resource>
<resource name="editor_counter">Buat penomor</resource>
<resource name="editor_crop">Potong (C)</resource>
<resource name="editor_cropmode_default">Potong</resource>
<resource name="editor_cropmode_auto">Auto potong</resource>
<resource name="editor_cursortool">Alat seleksi (ESC)</resource>
<resource name="editor_cuttoclipboard">Gunting</resource>
<resource name="editor_deleteelement">Hapus</resource>

View file

@ -98,6 +98,8 @@ Controlla i permessi di accesso per '{0}'.</resource>
<resource name="editor_copypathtoclipboard">Copia percorso negli appunti</resource>
<resource name="editor_copytoclipboard">Copia</resource>
<resource name="editor_crop">Ritaglia (C)</resource>
<resource name="editor_cropmode_default">Ritaglia</resource>
<resource name="editor_cropmode_auto">Ritaglia Automaticamente</resource>
<resource name="editor_cursortool">Strumento di selezione (ESC)</resource>
<resource name="editor_cuttoclipboard">Taglia</resource>
<resource name="editor_deleteelement">Elimina</resource>

View file

@ -92,6 +92,8 @@ Greenshot には一切の保障がありません。GNU General Public License
<resource name="editor_copytoclipboard">コピー</resource>
<resource name="editor_counter">カウンターを挿入する (I)</resource>
<resource name="editor_crop">切り抜き (C)</resource>
<resource name="editor_cropmode_default">切り抜き</resource>
<resource name="editor_cropmode_auto">自動切り抜き</resource>
<resource name="editor_cursortool">選択ツール (ESC)</resource>
<resource name="editor_cuttoclipboard">切り取り</resource>
<resource name="editor_deleteelement">削除</resource>

View file

@ -93,6 +93,8 @@ Rnu ɣur-s, nḥemmel aṭas ma yella tesneqdeḍ aneqqis igebren ugur-agi. (Tze
<resource name="editor_copytoclipboard">Nɣel</resource>
<resource name="editor_counter">Rnu Amesmiḍan</resource>
<resource name="editor_crop">Seggem (C)</resource>
<resource name="editor_cropmode_default">Seggem</resource>
<resource name="editor_cropmode_auto">Aseggem awurman</resource>
<resource name="editor_cursortool">Afecku n ufran (ESC)</resource>
<resource name="editor_cuttoclipboard">Gzem</resource>
<resource name="editor_deleteelement">Kkes</resource>

View file

@ -92,6 +92,8 @@ Also, we would highly appreciate if you checked whether a tracker item already e
<resource name="editor_copypathtoclipboard">경로를 클립보드로 복사</resource>
<resource name="editor_copytoclipboard">복사</resource>
<resource name="editor_crop">잘라내기 (C)</resource>
<resource name="editor_cropmode_default">잘라내기</resource>
<resource name="editor_cropmode_auto">자동 잘라내기</resource>
<resource name="editor_cursortool">선택도구 (ESC)</resource>
<resource name="editor_cuttoclipboard">잘라내기</resource>
<resource name="editor_deleteelement">삭제</resource>

View file

@ -61,6 +61,7 @@ Dėkojame už pagalbą :)</resource>
<resource name="editor_copypathtoclipboard">Kopijuoti pilną failo vardą</resource>
<resource name="editor_copytoclipboard">Коpijuoti</resource>
<resource name="editor_crop">Iškirpti (C)</resource>
<resource name="editor_cropmode_default">Iškirpti</resource>
<resource name="editor_cursortool">Objektų pasirinkimas (ESC)</resource>
<resource name="editor_cuttoclipboard">Apkirpti</resource>
<resource name="editor_deleteelement">Naikinti</resource>

View file

@ -92,6 +92,8 @@ Mēs būtu Tev pateicīgi, ja Tu vispirms pārbaudītu, vai kāds cits jau nav z
<resource name="editor_copypathtoclipboard">Ievietot ceļu starpliktuvē</resource>
<resource name="editor_copytoclipboard">Kopēt</resource>
<resource name="editor_crop">Apcirst (C)</resource>
<resource name="editor_cropmode_default">Apcirst</resource>
<resource name="editor_cropmode_auto">Automātiski apcirst</resource>
<resource name="editor_cursortool">Atlases rīks (ESC)</resource>
<resource name="editor_cuttoclipboard">Izgriezt</resource>
<resource name="editor_deleteelement">Izdzēst</resource>

View file

@ -93,6 +93,8 @@ Controleer ook even of dit probleem mogelijk al gemeld is! Gebruik de zoekfuncti
<resource name="editor_copypathtoclipboard">Locatie naar klembord kopiëren</resource>
<resource name="editor_copytoclipboard">Kopiëren</resource>
<resource name="editor_crop">Bijsnijden (C)</resource>
<resource name="editor_cropmode_default">Bijsnijden</resource>
<resource name="editor_cropmode_auto">Automatisch bijsnijden</resource>
<resource name="editor_cursortool">Selectiegereedschap (ESC)</resource>
<resource name="editor_cuttoclipboard">Knippen</resource>
<resource name="editor_deleteelement">Verwijderen</resource>

View file

@ -80,6 +80,8 @@ Me sett òg pris på om du ved hjelp av søkefunksjonen på sida kan sjekke om d
<resource name="editor_copypathtoclipboard">Kopier filstigen til utklyppstavla</resource>
<resource name="editor_copytoclipboard">Kopier</resource>
<resource name="editor_crop">Skjer bildet [C]</resource>
<resource name="editor_cropmode_default">Skjer bildet</resource>
<resource name="editor_cropmode_auto">Auto-skjer</resource>
<resource name="editor_cursortool">Peikarverktøy [Esc]</resource>
<resource name="editor_cuttoclipboard">Klypp ut</resource>
<resource name="editor_deleteelement">Slett</resource>

View file

@ -93,6 +93,8 @@ Będziemy wdzięczni, jeśli najpierw sprawdzisz, czy takie zdarzenie nie zosta
<resource name="editor_copypathtoclipboard">Kopiuj ścieżkę do schowka</resource>
<resource name="editor_copytoclipboard">Kopiuj</resource>
<resource name="editor_crop">Przytnij (C)</resource>
<resource name="editor_cropmode_default">Przytnij (C)</resource>
<resource name="editor_cropmode_auto">Przytnij automatycznie</resource>
<resource name="editor_cursortool">Narzędzie wyboru (ESC)</resource>
<resource name="editor_cuttoclipboard">Wytnij</resource>
<resource name="editor_deleteelement">Usuń</resource>

View file

@ -89,6 +89,7 @@
<resource name="editor_copypathtoclipboard">Copiar o caminho da pasta atual do arquivo para a Área de transferência</resource>
<resource name="editor_copytoclipboard">Copiar</resource>
<resource name="editor_crop">Cortar (C)</resource>
<resource name="editor_cropmode_default">Cortar</resource>
<resource name="editor_cursortool">Ferramenta de Seleção (ESC)</resource>
<resource name="editor_cuttoclipboard">Cortar</resource>
<resource name="editor_deleteelement">Apagar</resource>

View file

@ -92,6 +92,8 @@ Também apreciaremos muito se puder verificar se não existe já um relatório d
<resource name="editor_copypathtoclipboard">Copiar atalho para a Área de transferência</resource>
<resource name="editor_copytoclipboard">Copiar</resource>
<resource name="editor_crop">Recortar (C)</resource>
<resource name="editor_cropmode_default">Recortar</resource>
<resource name="editor_cropmode_auto">Recortar auto</resource>
<resource name="editor_cursortool">Ferramenta de Selecção (ESC)</resource>
<resource name="editor_cuttoclipboard">Cortar</resource>
<resource name="editor_deleteelement">Eliminar</resource>

View file

@ -471,6 +471,9 @@ timpul curent, ex. 11_58_32 (plus extensia fișierului definită în setări)
<resource name="editor_crop">
Taie (C)
</resource>
<resource name="editor_cropmode_default">
Taie
</resource>
<resource name="contextmenu_captureclipboard">
Deschide imaginea din clipboard
</resource>

View file

@ -93,6 +93,8 @@ Greenshot поставляется БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
<resource name="editor_copypathtoclipboard">Копировать путь в буфер обмена</resource>
<resource name="editor_copytoclipboard">Копировать</resource>
<resource name="editor_crop">Обрезка (C)</resource>
<resource name="editor_cropmode_default">Обрезка</resource>
<resource name="editor_cropmode_auto">Автообрезка</resource>
<resource name="editor_cursortool">Инструмент «Выделение» (ESC)</resource>
<resource name="editor_cuttoclipboard">Вырезать</resource>
<resource name="editor_deleteelement">Удалить</resource>

View file

@ -80,6 +80,8 @@ Tiež by sme velmi ocenili, keby ste najskôr skontrolovali, či už neexistuje
<resource name="editor_copypathtoclipboard">Kopírovať cestu do schránky</resource>
<resource name="editor_copytoclipboard">Kopírovať</resource>
<resource name="editor_crop">Orezať (C)</resource>
<resource name="editor_cropmode_default">Orezať</resource>
<resource name="editor_cropmode_auto">Automatické orezanie</resource>
<resource name="editor_cursortool">Nástroj pre výber (ESC)</resource>
<resource name="editor_cuttoclipboard">Vystrihnúť</resource>
<resource name="editor_deleteelement">Zmazať</resource>

View file

@ -78,6 +78,8 @@ Pred objavo preverite tudi ali je napaka že prijavlja s strani kakšnega drugeg
<resource name="editor_copypathtoclipboard">Kopiraj pot na odložišče</resource>
<resource name="editor_copytoclipboard">Kopiraj</resource>
<resource name="editor_crop">Obreži (C)</resource>
<resource name="editor_cropmode_default">Obreži</resource>
<resource name="editor_cropmode_auto">Samodejno obreži</resource>
<resource name="editor_cursortool">Orodje za izbor (ESC)</resource>
<resource name="editor_cuttoclipboard">Kopiraj</resource>
<resource name="editor_deleteelement">Briši</resource>

View file

@ -78,6 +78,8 @@
<resource name="editor_copypathtoclipboard">Умножи путању</resource>
<resource name="editor_copytoclipboard">Умножи</resource>
<resource name="editor_crop">Опсеци (C)</resource>
<resource name="editor_cropmode_default">Опсеци</resource>
<resource name="editor_cropmode_auto">Аутоматско опсецање</resource>
<resource name="editor_cursortool">Алатка за одабир (ESC)</resource>
<resource name="editor_cuttoclipboard">Исеци</resource>
<resource name="editor_deleteelement">Обриши</resource>

View file

@ -93,6 +93,8 @@ Innan du skickar uppskattar vi verkligen om du kontrollerar om felet redan blivi
<resource name="editor_copypathtoclipboard">Kopiera sökväg till urklipp</resource>
<resource name="editor_copytoclipboard">Kopiera</resource>
<resource name="editor_crop">Beskär (C)</resource>
<resource name="editor_cropmode_default">Beskär</resource>
<resource name="editor_cropmode_auto">Autobeskärning</resource>
<resource name="editor_cursortool">Markeringsverktyg (ESC)</resource>
<resource name="editor_cuttoclipboard">Klipp ut</resource>
<resource name="editor_deleteelement">Radera</resource>

View file

@ -78,6 +78,8 @@ Ayrıca bu hata için bir izleyici kaydının açılmış olup olmadığını da
<resource name="editor_copypathtoclipboard">Yolu panoya kopyala</resource>
<resource name="editor_copytoclipboard">Kopyala</resource>
<resource name="editor_crop">Kırp (C)</resource>
<resource name="editor_cropmode_default">Kırp</resource>
<resource name="editor_cropmode_auto">Otomatik kırpma</resource>
<resource name="editor_cursortool">Seçim Aracı (ESC)</resource>
<resource name="editor_cuttoclipboard">Kes</resource>
<resource name="editor_deleteelement">Sil</resource>

View file

@ -92,6 +92,8 @@ Greenshot постачається АБСОЛЮТНО БЕЗ ГАРАНТІЇ.
<resource name="editor_copypathtoclipboard">Копіювати шлях у буфер обміну</resource>
<resource name="editor_copytoclipboard">Копіювати</resource>
<resource name="editor_crop">Обрізати (С)</resource>
<resource name="editor_cropmode_default">Обрізати</resource>
<resource name="editor_cropmode_auto">Автоматичне обрізання</resource>
<resource name="editor_cursortool">Інструмент вибору (Esc)</resource>
<resource name="editor_cuttoclipboard">Вирізати</resource>
<resource name="editor_deleteelement">Видалити</resource>

View file

@ -58,6 +58,7 @@
<resource name="editor_copypathtoclipboard">Chép đuờng dẫn tới clipboard.</resource>
<resource name="editor_copytoclipboard">Chép</resource>
<resource name="editor_crop">Cắt (C)</resource>
<resource name="editor_cropmode_default">Cắt</resource>
<resource name="editor_cursortool">Công cụ chọn (ESC)</resource>
<resource name="editor_cuttoclipboard">Cắt</resource>
<resource name="editor_deleteelement">Xóa</resource>

View file

@ -84,6 +84,8 @@
<resource name="editor_copypathtoclipboard">复制路径到剪贴板</resource>
<resource name="editor_copytoclipboard">复制</resource>
<resource name="editor_crop">裁剪 (C)</resource>
<resource name="editor_cropmode_default">裁剪</resource>
<resource name="editor_cropmode_auto">自动裁剪</resource>
<resource name="editor_cursortool">选择工具 (ESC)</resource>
<resource name="editor_cuttoclipboard">剪切</resource>
<resource name="editor_deleteelement">刪除物件</resource>

View file

@ -93,6 +93,8 @@ Greenshot 不對這個程式做任何擔保。這個程式是自由軟體,您
<resource name="editor_copypathtoclipboard">複製路徑到剪貼簿</resource>
<resource name="editor_copytoclipboard">複製</resource>
<resource name="editor_crop">裁剪 (C)</resource>
<resource name="editor_cropmode_default">裁剪</resource>
<resource name="editor_cropmode_auto">自動裁剪</resource>
<resource name="editor_cursortool">選取工具 (ESC)</resource>
<resource name="editor_cuttoclipboard">剪下</resource>
<resource name="editor_deleteelement">刪除</resource>