diff --git a/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs b/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs
index 24abc2d25..3d420bfa3 100644
--- a/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs
+++ b/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs
@@ -78,6 +78,11 @@ namespace Greenshot.Base.Interfaces.Drawing
bool InitContent();
+ ///
+ /// Defines if the drawable container participates in undo / redo
+ ///
+ bool IsUndoable { get; }
+
void MakeBoundsChangeUndoable(bool allowMerge);
EditStatus DefaultEditMode { get; }
diff --git a/src/Greenshot.Base/Interfaces/Drawing/IFieldAggregator.cs b/src/Greenshot.Base/Interfaces/Drawing/IFieldAggregator.cs
index fdbf72847..5af83b39e 100644
--- a/src/Greenshot.Base/Interfaces/Drawing/IFieldAggregator.cs
+++ b/src/Greenshot.Base/Interfaces/Drawing/IFieldAggregator.cs
@@ -21,6 +21,9 @@
namespace Greenshot.Base.Interfaces.Drawing
{
+ ///
+ /// The IFieldAggregator defines the connections between fields and containers
+ ///
public interface IFieldAggregator
{
void UnbindElement(IDrawableContainer dc);
diff --git a/src/Greenshot.Base/Interfaces/ISurface.cs b/src/Greenshot.Base/Interfaces/ISurface.cs
index 85cefe452..396a5702f 100644
--- a/src/Greenshot.Base/Interfaces/ISurface.cs
+++ b/src/Greenshot.Base/Interfaces/ISurface.cs
@@ -201,8 +201,16 @@ namespace Greenshot.Base.Interfaces
/// A rectangle in the coordinate space of the surface.
Rectangle ToImageCoordinates(Rectangle rc);
+ ///
+ /// Make it possible to undo the specified IMemento
+ ///
+ /// IMemento
+ /// bool to specify if the action can be merged, e.g. we do not want an undo for every part of a resize
void MakeUndoable(IMemento memento, bool allowMerge);
+ ///
+ /// The IFieldAggregator
+ ///
IFieldAggregator FieldAggregator { get; }
///
diff --git a/src/Greenshot.Editor/Drawing/CropContainer.cs b/src/Greenshot.Editor/Drawing/CropContainer.cs
index cd924369a..936a1a2c8 100644
--- a/src/Greenshot.Editor/Drawing/CropContainer.cs
+++ b/src/Greenshot.Editor/Drawing/CropContainer.cs
@@ -36,9 +36,9 @@ namespace Greenshot.Editor.Drawing
public class CropContainer : DrawableContainer
{
///
- /// awailable modes
+ /// Available Crop modes
///
- public enum CropMode
+ public enum CropModes
{
///
/// crop all outside the selection rectangle
@@ -73,12 +73,12 @@ namespace Greenshot.Editor.Drawing
{
switch (GetFieldValue(FieldType.CROPMODE))
{
- case CropMode.Horizontal:
+ case CropModes.Horizontal:
{
InitHorizontalCropOutStyle();
break;
}
- case CropMode.Vertical:
+ case CropModes.Vertical:
{
InitVerticalCropOutStyle();
break;
@@ -119,6 +119,7 @@ namespace Greenshot.Editor.Drawing
Adorners.Add(new ResizeAdorner(this, Positions.TopCenter));
Adorners.Add(new ResizeAdorner(this, Positions.BottomCenter));
}
+
private void CreateLeftRightAdorners()
{
Adorners.Add(new ResizeAdorner(this, Positions.MiddleLeft));
@@ -128,7 +129,7 @@ namespace Greenshot.Editor.Drawing
protected override void InitializeFields()
{
AddField(GetType(), FieldType.FLAGS, FieldFlag.CONFIRMABLE);
- AddField(GetType(), FieldType.CROPMODE, CropMode.Default);
+ AddField(GetType(), FieldType.CROPMODE, CropModes.Default);
}
public override void Invalidate()
@@ -170,8 +171,8 @@ namespace Greenshot.Editor.Drawing
switch (GetFieldValue(FieldType.CROPMODE))
{
- case CropMode.Horizontal:
- case CropMode.Vertical:
+ case CropModes.Horizontal:
+ case CropModes.Vertical:
{
//draw inside
g.FillRectangle(cropBrush, cropRectangle);
@@ -205,9 +206,9 @@ namespace Greenshot.Editor.Drawing
return GetFieldValue(FieldType.CROPMODE) switch
{
//force horizontal crop to left edge
- CropMode.Horizontal => base.HandleMouseDown(0, y),
+ CropModes.Horizontal => base.HandleMouseDown(0, y),
//force vertical crop to top edge
- CropMode.Vertical => base.HandleMouseDown(x, 0),
+ CropModes.Vertical => base.HandleMouseDown(x, 0),
_ => base.HandleMouseDown(x, y),
};
}
@@ -218,7 +219,7 @@ namespace Greenshot.Editor.Drawing
switch (GetFieldValue(FieldType.CROPMODE))
{
- case CropMode.Horizontal:
+ case CropModes.Horizontal:
{
//stick on left and right
//allow only horizontal changes
@@ -231,7 +232,7 @@ namespace Greenshot.Editor.Drawing
}
break;
}
- case CropMode.Vertical:
+ case CropModes.Vertical:
{
//stick on top and bottom
//allow only vertical changes
@@ -263,5 +264,9 @@ namespace Greenshot.Editor.Drawing
Invalidate();
return true;
}
+
+ ///
+ /// Make sure this container is not undoable
+ public override bool IsUndoable => false;
}
}
diff --git a/src/Greenshot.Editor/Drawing/DrawableContainer.cs b/src/Greenshot.Editor/Drawing/DrawableContainer.cs
index 08abba3e2..b07974e61 100644
--- a/src/Greenshot.Editor/Drawing/DrawableContainer.cs
+++ b/src/Greenshot.Editor/Drawing/DrawableContainer.cs
@@ -472,13 +472,20 @@ namespace Greenshot.Editor.Drawing
g.DrawRectangle(pen, rect);
}
+ ///
+ public virtual bool IsUndoable => true;
+
///
/// Make a following bounds change on this drawablecontainer undoable!
///
/// true means allow the moves to be merged
- 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();
}
///
@@ -567,7 +573,10 @@ namespace Greenshot.Editor.Drawing
/// The new value
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();
}
diff --git a/src/Greenshot.Editor/Drawing/DrawableContainerList.cs b/src/Greenshot.Editor/Drawing/DrawableContainerList.cs
index e89b78b70..1a31de881 100644
--- a/src/Greenshot.Editor/Drawing/DrawableContainerList.cs
+++ b/src/Greenshot.Editor/Drawing/DrawableContainerList.cs
@@ -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 elements)
+ {
+ AddRange(elements);
+ }
+
public DrawableContainerList(Guid parentId)
{
ParentID = parentId;
@@ -135,12 +141,16 @@ namespace Greenshot.Editor.Drawing
/// true means allow the moves to be merged
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);
}
///
diff --git a/src/Greenshot.Editor/Drawing/Surface.cs b/src/Greenshot.Editor/Drawing/Surface.cs
index 92ffe50ae..c6b5ffe5b 100644
--- a/src/Greenshot.Editor/Drawing/Surface.cs
+++ b/src/Greenshot.Editor/Drawing/Surface.cs
@@ -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;
@@ -981,7 +982,7 @@ namespace Greenshot.Editor.Drawing
cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, conf.AutoCropDifference);
}
- if (!IsCropPossible(ref cropRectangle, CropContainer.CropMode.AutoCrop))
+ if (!IsCropPossible(ref cropRectangle, CropContainer.CropModes.AutoCrop))
{
return false;
}
@@ -1063,7 +1064,7 @@ namespace Greenshot.Editor.Drawing
/// Rectangle adapted to the dimensions of the image
///
/// true if this is possible
- public bool IsCropPossible(ref Rectangle cropRectangle, CropContainer.CropMode cropMode)
+ 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
@@ -1088,14 +1089,14 @@ namespace Greenshot.Editor.Drawing
}
// special condition for vertical
- if(cropMode == CropContainer.CropMode.Vertical && cropRectangle.Width == Image.Width)
+ if(cropMode == CropContainer.CropModes.Vertical && cropRectangle.Width == Image.Width)
{
//crop out the hole imgage is not allowed
return false;
}
// special condition for vertical
- if (cropMode == CropContainer.CropMode.Horizontal && cropRectangle.Height == Image.Height)
+ if (cropMode == CropContainer.CropModes.Horizontal && cropRectangle.Height == Image.Height)
{
//crop out the hole imgage is not allowed
return false;
@@ -1205,7 +1206,7 @@ namespace Greenshot.Editor.Drawing
///
public bool ApplyCrop(Rectangle cropRectangle)
{
- if (!IsCropPossible(ref cropRectangle, CropContainer.CropMode.Default)) return false;
+ if (!IsCropPossible(ref cropRectangle, CropContainer.CropModes.Default)) return false;
Rectangle imageRectangle = new Rectangle(Point.Empty, Image.Size);
Bitmap tmpImage;
@@ -1248,7 +1249,7 @@ namespace Greenshot.Editor.Drawing
///
public bool ApplyHorizontalCrop(Rectangle cropRectangle)
{
- if (!IsCropPossible(ref cropRectangle, CropContainer.CropMode.Horizontal)) return false;
+ 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);
@@ -1315,7 +1316,7 @@ namespace Greenshot.Editor.Drawing
///
public bool ApplyVerticalCrop(Rectangle cropRectangle)
{
- if (!IsCropPossible(ref cropRectangle, CropContainer.CropMode.Vertical)) return false;
+ 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);
@@ -1943,7 +1944,7 @@ namespace Greenshot.Editor.Drawing
element.Invalidate();
}
- if (makeUndoable)
+ if (makeUndoable && element.IsUndoable)
{
MakeUndoable(new AddElementMemento(this, element), false);
}
@@ -1959,11 +1960,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();
@@ -2011,7 +2018,7 @@ namespace Greenshot.Editor.Drawing
Invalidate();
}
- if (makeUndoable)
+ if (makeUndoable && elementToRemove.IsUndoable)
{
MakeUndoable(new DeleteElementMemento(this, elementToRemove), false);
}
@@ -2027,11 +2034,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();
@@ -2113,12 +2125,12 @@ namespace Greenshot.Editor.Drawing
{
switch (e.GetFieldValue(FieldType.CROPMODE))
{
- case CropContainer.CropMode.Horizontal:
+ case CropContainer.CropModes.Horizontal:
{
ApplyHorizontalCrop(_cropContainer.Bounds);
break;
}
- case CropContainer.CropMode.Vertical:
+ case CropContainer.CropModes.Vertical:
{
ApplyVerticalCrop(_cropContainer.Bounds);
break;
diff --git a/src/Greenshot.Editor/Drawing/TextContainer.cs b/src/Greenshot.Editor/Drawing/TextContainer.cs
index fdb718cbe..5a1f755ef 100644
--- a/src/Greenshot.Editor/Drawing/TextContainer.cs
+++ b/src/Greenshot.Editor/Drawing/TextContainer.cs
@@ -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);
diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs
index c92136179..8d8162fd9 100644
--- a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs
+++ b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs
@@ -1118,8 +1118,8 @@ namespace Greenshot.Editor.Forms {
//TODO translate
this.cropModeButton.LanguageKey = "editor_crop_mode";
this.cropModeButton.Name = "cropModeButton";
- this.cropModeButton.SelectedTag = CropContainer.CropMode.Default;
- this.cropModeButton.Tag = CropContainer.CropMode.Default;
+ this.cropModeButton.SelectedTag = CropContainer.CropModes.Default;
+ this.cropModeButton.Tag = CropContainer.CropModes.Default;
//
// defaultCropStyleToolStripMenuItem
@@ -1127,7 +1127,7 @@ namespace Greenshot.Editor.Forms {
this.defaultCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnCrop.Image")));
this.defaultCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_default";
this.defaultCropModeToolStripMenuItem.Name = "defaultCropModeToolStripMenuItem";
- this.defaultCropModeToolStripMenuItem.Tag = CropContainer.CropMode.Default;
+ this.defaultCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Default;
//
// verticalCropStyleToolStripMenuItem
@@ -1135,7 +1135,7 @@ namespace Greenshot.Editor.Forms {
this.verticalCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("CropVertical.Image")));
this.verticalCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_vertical";
this.verticalCropModeToolStripMenuItem.Name = "verticalCropModeToolStripMenuItem";
- this.verticalCropModeToolStripMenuItem.Tag = CropContainer.CropMode.Vertical;
+ this.verticalCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Vertical;
//
// horizontalCropStyleToolStripMenuItem
@@ -1143,7 +1143,7 @@ namespace Greenshot.Editor.Forms {
this.horizontalCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("CropHorizontal.Image")));
this.horizontalCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_horizontal";
this.horizontalCropModeToolStripMenuItem.Name = "horizontalCropModeToolStripMenuItem";
- this.horizontalCropModeToolStripMenuItem.Tag = CropContainer.CropMode.Horizontal;
+ this.horizontalCropModeToolStripMenuItem.Tag = CropContainer.CropModes.Horizontal;
//
// horizontalCropStyleToolStripMenuItem
@@ -1151,7 +1151,7 @@ namespace Greenshot.Editor.Forms {
this.autoCropModeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("AutoCrop.Image")));
this.autoCropModeToolStripMenuItem.LanguageKey = "editor_cropmode_auto";
this.autoCropModeToolStripMenuItem.Name = "autoCropModeToolStripMenuItem";
- this.autoCropModeToolStripMenuItem.Tag = CropContainer.CropMode.AutoCrop;
+ this.autoCropModeToolStripMenuItem.Tag = CropContainer.CropModes.AutoCrop;
//
// highlightModeButton
diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs
index 13e630727..e8a1b5bf7 100644
--- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs
+++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs
@@ -731,7 +731,7 @@ namespace Greenshot.Editor.Forms
if (_surface.DrawingMode == DrawingModes.Crop) return;
_surface.DrawingMode = DrawingModes.Crop;
- InitCropMode((CropContainer.CropMode)_surface.FieldAggregator.GetField(FieldType.CROPMODE).Value);
+ InitCropMode((CropContainer.CropModes)_surface.FieldAggregator.GetField(FieldType.CROPMODE).Value);
RefreshFieldControls();
}
@@ -1590,25 +1590,25 @@ namespace Greenshot.Editor.Forms
protected void CropStyleDropDownItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
- InitCropMode((CropContainer.CropMode)e.ClickedItem.Tag);
+ InitCropMode((CropContainer.CropModes)e.ClickedItem.Tag);
RefreshFieldControls();
Invalidate(true);
}
- private void InitCropMode(CropContainer.CropMode mode)
+ private void InitCropMode(CropContainer.CropModes mode)
{
_surface.DrawingMode = DrawingModes.None;
_surface.RemoveCropContainer();
- if (mode == CropContainer.CropMode.AutoCrop)
+ if (mode == CropContainer.CropModes.AutoCrop)
{
if (!_surface.AutoCrop())
{
//not AutoCrop possible automatic switch to default crop mode
_surface.DrawingMode = DrawingModes.Crop;
- _surface.FieldAggregator.GetField(FieldType.CROPMODE).Value = CropContainer.CropMode.Default;
- this.cropModeButton.SelectedTag = CropContainer.CropMode.Default;
+ _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);
}
}
@@ -1710,7 +1710,7 @@ namespace Greenshot.Editor.Forms
cropRectangle = ImageHelper.FindAutoCropRectangle(tmpImage, coreConfiguration.AutoCropDifference);
}
- if (_surface.IsCropPossible(ref cropRectangle, CropContainer.CropMode.AutoCrop))
+ if (_surface.IsCropPossible(ref cropRectangle, CropContainer.CropModes.AutoCrop))
{
_surface.ApplyCrop(cropRectangle);
UpdateUndoRedoSurfaceDependencies();