Made the re/undo code from the branch work in this, this is a manual copy as something went horribly wrong with the repository. Before building I first want to check if everything is there.[skip ci]

This commit is contained in:
Robin 2016-05-24 12:48:11 +02:00
commit 45615275cf
35 changed files with 1890 additions and 922 deletions

View file

@ -26,6 +26,7 @@ using Greenshot.Drawing.Fields;
using GreenshotPlugin.UnmanagedHelpers; using GreenshotPlugin.UnmanagedHelpers;
using Greenshot.IniFile; using Greenshot.IniFile;
using Greenshot.Core; using Greenshot.Core;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Configuration { namespace Greenshot.Configuration {
/// <summary> /// <summary>
@ -75,7 +76,8 @@ namespace Greenshot.Configuration {
/// <param name="fieldType">FieldType of the field to construct</param> /// <param name="fieldType">FieldType of the field to construct</param>
/// <param name="preferredDefaultValue"></param> /// <param name="preferredDefaultValue"></param>
/// <returns>a new Field of the given fieldType, with the scope of it's value being restricted to the Type scope</returns> /// <returns>a new Field of the given fieldType, with the scope of it's value being restricted to the Type scope</returns>
public Field CreateField(Type requestingType, FieldType fieldType, object preferredDefaultValue) { public IField CreateField(Type requestingType, IFieldType fieldType, object preferredDefaultValue)
{
string requestingTypeName = requestingType.Name; string requestingTypeName = requestingType.Name;
string requestedField = requestingTypeName + "." + fieldType.Name; string requestedField = requestingTypeName + "." + fieldType.Name;
object fieldValue = preferredDefaultValue; object fieldValue = preferredDefaultValue;
@ -102,7 +104,8 @@ namespace Greenshot.Configuration {
return returnField; return returnField;
} }
public void UpdateLastFieldValue(Field field) { public void UpdateLastFieldValue(IField field)
{
string requestedField = field.Scope + "." + field.FieldType.Name; string requestedField = field.Scope + "." + field.FieldType.Name;
// Check if the configuration exists // Check if the configuration exists
if (LastUsedFieldValues == null) { if (LastUsedFieldValues == null) {
@ -110,9 +113,9 @@ namespace Greenshot.Configuration {
} }
// check if settings for the requesting type exist, if not create! // check if settings for the requesting type exist, if not create!
if (LastUsedFieldValues.ContainsKey(requestedField)) { if (LastUsedFieldValues.ContainsKey(requestedField)) {
LastUsedFieldValues[requestedField] = field.myValue; LastUsedFieldValues[requestedField] = field.Value;
} else { } else {
LastUsedFieldValues.Add(requestedField, field.myValue); LastUsedFieldValues.Add(requestedField, field.Value);
} }
} }

View file

@ -24,6 +24,7 @@ using System.Runtime.Serialization;
using Greenshot.Drawing.Fields; using Greenshot.Drawing.Fields;
using Greenshot.Helpers; using Greenshot.Helpers;
using Greenshot.Plugin.Drawing; using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Drawing { namespace Greenshot.Drawing {
/// <summary> /// <summary>
@ -45,10 +46,14 @@ namespace Greenshot.Drawing {
CreateDefaultAdorners(); CreateDefaultAdorners();
} }
protected override void InitializeFields() { protected override void InitializeFields() {
AddField(GetType(), FieldType.FLAGS, FieldType.Flag.CONFIRMABLE); AddField(GetType(), FieldType.FLAGS, FieldFlag.CONFIRMABLE);
} }
public override void Invalidate() { public override void Invalidate() {
if (_parent == null)
{
return;
}
_parent.Invalidate(); _parent.Invalidate();
} }

View file

@ -29,6 +29,7 @@ using Greenshot.Memento;
using Greenshot.Plugin; using Greenshot.Plugin;
using Greenshot.Plugin.Drawing; using Greenshot.Plugin.Drawing;
using Greenshot.Plugin.Drawing.Adorners; using Greenshot.Plugin.Drawing.Adorners;
using GreenshotPlugin.Interfaces.Drawing;
using log4net; using log4net;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -104,7 +105,7 @@ namespace Greenshot.Drawing
remove{ _propertyChanged -= value; } remove{ _propertyChanged -= value; }
} }
public List<IFilter> Filters { public IList<IFilter> Filters {
get { get {
List<IFilter> ret = new List<IFilter>(); List<IFilter> ret = new List<IFilter>();
foreach(IFieldHolder c in Children) { foreach(IFieldHolder c in Children) {
@ -124,10 +125,10 @@ namespace Greenshot.Drawing
} }
[NonSerialized] [NonSerialized]
private TargetAdorner _targetGripper; private TargetAdorner _targetAdorner;
public TargetAdorner TargetGripper { public TargetAdorner TargetAdorner {
get { get {
return _targetGripper; return _targetAdorner;
} }
} }
@ -305,7 +306,10 @@ namespace Greenshot.Drawing
} }
public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) { public void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment) {
if (_parent == null)
{
return;
}
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
if (horizontalAlignment == HorizontalAlignment.Left) { if (horizontalAlignment == HorizontalAlignment.Left) {
Left = lineThickness/2; Left = lineThickness/2;
@ -335,9 +339,9 @@ namespace Greenshot.Drawing
/// <summary> /// <summary>
/// Initialize a target gripper /// Initialize a target gripper
/// </summary> /// </summary>
protected void InitTargetGripper(Color gripperColor, Point location) { protected void InitAdorner(Color gripperColor, Point location) {
_targetGripper = new TargetAdorner(this, location); _targetAdorner = new TargetAdorner(this, location);
Adorners.Add(_targetGripper); Adorners.Add(_targetAdorner);
} }
/// <summary> /// <summary>
@ -478,6 +482,19 @@ namespace Greenshot.Drawing
} }
protected virtual void SwitchParent(Surface newParent) { protected virtual void SwitchParent(Surface newParent) {
if (newParent == Parent)
{
return;
}
if (_parent != null)
{
// Remove FieldAggregator
FieldAggregator fieldAggregator = _parent.FieldAggregator;
if (fieldAggregator != null)
{
fieldAggregator.UnbindElement(this);
}
}
_parent = newParent; _parent = newParent;
foreach(IFilter filter in Filters) { foreach(IFilter filter in Filters) {
@ -485,24 +502,6 @@ namespace Greenshot.Drawing
} }
} }
// drawablecontainers are regarded equal if they are of the same type and their bounds are equal. this should be sufficient.
public override bool Equals(object obj) {
bool ret = false;
if (obj != null && GetType() == obj.GetType()) {
DrawableContainer other = obj as DrawableContainer;
if (other != null && left==other.left && top==other.top && width==other.width && height==other.height) {
ret = true;
}
}
return ret;
}
public override int GetHashCode() {
// TODO: This actually doesn't make sense...
// Place the container in a list, and you can't find it :)
return left.GetHashCode() ^ top.GetHashCode() ^ width.GetHashCode() ^ height.GetHashCode() ^ GetFields().GetHashCode();
}
protected void OnPropertyChanged(string propertyName) { protected void OnPropertyChanged(string propertyName) {
if (_propertyChanged != null) { if (_propertyChanged != null) {
_propertyChanged(this, new PropertyChangedEventArgs(propertyName)); _propertyChanged(this, new PropertyChangedEventArgs(propertyName));
@ -516,7 +515,7 @@ namespace Greenshot.Drawing
/// </summary> /// </summary>
/// <param name="fieldToBeChanged">The field to be changed</param> /// <param name="fieldToBeChanged">The field to be changed</param>
/// <param name="newValue">The new value</param> /// <param name="newValue">The new value</param>
public virtual void BeforeFieldChange(Field fieldToBeChanged, object newValue) { public virtual void BeforeFieldChange(IField fieldToBeChanged, object newValue) {
_parent.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true); _parent.MakeUndoable(new ChangeFieldHolderMemento(this, fieldToBeChanged), true);
Invalidate(); Invalidate();
} }
@ -531,7 +530,6 @@ namespace Greenshot.Drawing
if (e.Field.FieldType == FieldType.SHADOW) { if (e.Field.FieldType == FieldType.SHADOW) {
accountForShadowChange = true; accountForShadowChange = true;
} }
Invalidate();
} }
/// <summary> /// <summary>

View file

@ -25,6 +25,7 @@ using Greenshot.Memento;
using Greenshot.Plugin; using Greenshot.Plugin;
using Greenshot.Plugin.Drawing; using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces.Drawing;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@ -38,7 +39,8 @@ namespace Greenshot.Drawing {
/// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers. /// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class DrawableContainerList : List<IDrawableContainer> { public class DrawableContainerList : List<IDrawableContainer>, IDrawableContainerList
{
private static readonly ComponentResourceManager editorFormResources = new ComponentResourceManager(typeof(ImageEditorForm)); private static readonly ComponentResourceManager editorFormResources = new ComponentResourceManager(typeof(ImageEditorForm));
public Guid ParentID { public Guid ParentID {
@ -116,14 +118,11 @@ namespace Greenshot.Drawing {
/// </summary> /// </summary>
/// <param name="allowMerge">true means allow the moves to be merged</param> /// <param name="allowMerge">true means allow the moves to be merged</param>
public void MakeBoundsChangeUndoable(bool allowMerge) { public void MakeBoundsChangeUndoable(bool allowMerge) {
List<IDrawableContainer> movingList = new List<IDrawableContainer>(); if (Count > 0 && Parent != null)
Surface surface = null; {
foreach(DrawableContainer dc in this) { var clone = new DrawableContainerList();
movingList.Add(dc); clone.AddRange(this);
surface = dc._parent; Parent.MakeUndoable(new DrawableContainerBoundsChangeMemento(clone), allowMerge);
}
if (movingList.Count > 0 && surface != null) {
surface.MakeUndoable(new DrawableContainerBoundsChangeMemento(movingList), allowMerge);
} }
} }
@ -246,9 +245,19 @@ namespace Greenshot.Drawing {
/// <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> /// <param name="clipRectangle"></param>
public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle) { public void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle) {
foreach(var drawableContainer in this) { if (Parent == null)
var dc = (DrawableContainer) drawableContainer; {
if (dc.DrawingBounds.IntersectsWith(clipRectangle)) { return;
}
foreach (var drawableContainer in this)
{
var dc = (DrawableContainer)drawableContainer;
if (dc.Parent == null)
{
continue;
}
if (dc.DrawingBounds.IntersectsWith(clipRectangle))
{
dc.DrawContent(g, bitmap, renderMode, clipRectangle); dc.DrawContent(g, bitmap, renderMode, clipRectangle);
} }
} }
@ -270,9 +279,16 @@ namespace Greenshot.Drawing {
/// Invalidate the bounds of all the DC's in this list /// Invalidate the bounds of all the DC's in this list
/// </summary> /// </summary>
public void Invalidate() { public void Invalidate() {
foreach(var dc in this) { if (Parent == null)
dc.Invalidate(); {
return;
} }
Rectangle region = Rectangle.Empty;
foreach (var dc in this)
{
region = Rectangle.Union(region, dc.DrawingBounds);
}
Parent.Invalidate(region);
} }
/// <summary> /// <summary>
/// Indicates whether the given list of elements can be pulled up, /// Indicates whether the given list of elements can be pulled up,
@ -280,7 +296,7 @@ namespace Greenshot.Drawing {
/// </summary> /// </summary>
/// <param name="elements">list of elements to pull up</param> /// <param name="elements">list of elements to pull up</param>
/// <returns>true if the elements could be pulled up</returns> /// <returns>true if the elements could be pulled up</returns>
public bool CanPullUp(DrawableContainerList elements) { public bool CanPullUp(IDrawableContainerList elements) {
if (elements.Count == 0 || elements.Count == Count) { if (elements.Count == 0 || elements.Count == Count) {
return false; return false;
} }
@ -296,7 +312,7 @@ namespace Greenshot.Drawing {
/// Pulls one or several elements up one level in hierarchy (z-index). /// Pulls one or several elements up one level in hierarchy (z-index).
/// </summary> /// </summary>
/// <param name="elements">list of elements to pull up</param> /// <param name="elements">list of elements to pull up</param>
public void PullElementsUp(DrawableContainerList elements) { public void PullElementsUp(IDrawableContainerList elements) {
for(int i=Count-1; i>=0; i--) { for(int i=Count-1; i>=0; i--) {
var dc = this[i]; var dc = this[i];
if (!elements.Contains(dc)) { if (!elements.Contains(dc)) {
@ -312,7 +328,7 @@ namespace Greenshot.Drawing {
/// Pulls one or several elements up to the topmost level(s) in hierarchy (z-index). /// Pulls one or several elements up to the topmost level(s) in hierarchy (z-index).
/// </summary> /// </summary>
/// <param name="elements">of elements to pull to top</param> /// <param name="elements">of elements to pull to top</param>
public void PullElementsToTop(DrawableContainerList elements) { public void PullElementsToTop(IDrawableContainerList elements) {
var dcs = ToArray(); var dcs = ToArray();
for(int i=0; i<dcs.Length; i++) { for(int i=0; i<dcs.Length; i++) {
var dc = dcs[i]; var dc = dcs[i];
@ -331,7 +347,7 @@ namespace Greenshot.Drawing {
/// </summary> /// </summary>
/// <param name="elements">list of elements to push down</param> /// <param name="elements">list of elements to push down</param>
/// <returns>true if the elements could be pushed down</returns> /// <returns>true if the elements could be pushed down</returns>
public bool CanPushDown(DrawableContainerList elements) { public bool CanPushDown(IDrawableContainerList elements) {
if (elements.Count == 0 || elements.Count == Count) { if (elements.Count == 0 || elements.Count == Count) {
return false; return false;
} }
@ -347,7 +363,7 @@ namespace Greenshot.Drawing {
/// Pushes one or several elements down one level in hierarchy (z-index). /// Pushes one or several elements down one level in hierarchy (z-index).
/// </summary> /// </summary>
/// <param name="elements">list of elements to push down</param> /// <param name="elements">list of elements to push down</param>
public void PushElementsDown(DrawableContainerList elements) { public void PushElementsDown(IDrawableContainerList elements) {
for(int i=0; i<Count; i++) { for(int i=0; i<Count; i++) {
var dc = this[i]; var dc = this[i];
if (!elements.Contains(dc)) { if (!elements.Contains(dc)) {
@ -363,7 +379,7 @@ namespace Greenshot.Drawing {
/// Pushes one or several elements down to the bottommost level(s) in hierarchy (z-index). /// Pushes one or several elements down to the bottommost level(s) in hierarchy (z-index).
/// </summary> /// </summary>
/// <param name="elements">of elements to push to bottom</param> /// <param name="elements">of elements to push to bottom</param>
public void PushElementsToBottom(DrawableContainerList elements) { public void PushElementsToBottom(IDrawableContainerList elements) {
var dcs = ToArray(); var dcs = ToArray();
for(int i=dcs.Length-1; i>=0; i--) { for(int i=dcs.Length-1; i>=0; i--) {
var dc = dcs[i]; var dc = dcs[i];
@ -397,7 +413,7 @@ namespace Greenshot.Drawing {
/// </summary> /// </summary>
/// <param name="menu"></param> /// <param name="menu"></param>
/// <param name="surface"></param> /// <param name="surface"></param>
public virtual void AddContextMenuItems(ContextMenuStrip menu, Surface surface) { public virtual void AddContextMenuItems(ContextMenuStrip menu, ISurface surface) {
bool push = surface.Elements.CanPushDown(this); bool push = surface.Elements.CanPushDown(this);
bool pull = surface.Elements.CanPullUp(this); bool pull = surface.Elements.CanPullUp(this);
@ -437,7 +453,7 @@ namespace Greenshot.Drawing {
// Duplicate // Duplicate
item = new ToolStripMenuItem(Language.GetString(LangKey.editor_duplicate)); item = new ToolStripMenuItem(Language.GetString(LangKey.editor_duplicate));
item.Click += delegate { item.Click += delegate {
DrawableContainerList dcs = this.Clone(); IDrawableContainerList dcs = this.Clone();
dcs.Parent = surface; dcs.Parent = surface;
dcs.MoveBy(10, 10); dcs.MoveBy(10, 10);
surface.AddElements(dcs); surface.AddElements(dcs);
@ -448,48 +464,36 @@ namespace Greenshot.Drawing {
// Copy // Copy
item = new ToolStripMenuItem(Language.GetString(LangKey.editor_copytoclipboard)); item = new ToolStripMenuItem(Language.GetString(LangKey.editor_copytoclipboard));
item.Image = (Image)editorFormResources.GetObject("copyToolStripMenuItem.Image"); item.Image = ((Image)(editorFormResources.GetObject("copyToolStripMenuItem.Image")));
item.Click += delegate { item.Click += delegate {
ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this); ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), this);
}; };
menu.Items.Add(item); menu.Items.Add(item);
// Cut // Cut
item = new ToolStripMenuItem(Language.GetString(LangKey.editor_cuttoclipboard)); item = new ToolStripMenuItem(Language.GetString(LangKey.editor_cuttoclipboard));
item.Image = (Image)editorFormResources.GetObject("btnCut.Image"); item.Image = ((Image)(editorFormResources.GetObject("btnCut.Image")));
item.Click += delegate { item.Click += delegate {
ClipboardHelper.SetClipboardData(typeof(DrawableContainerList), this); ClipboardHelper.SetClipboardData(typeof(IDrawableContainerList), this);
List<DrawableContainer> containersToDelete = new List<DrawableContainer>(); surface.RemoveElements(this, true);
foreach (var drawableContainer in this) {
var container = (DrawableContainer) drawableContainer;
containersToDelete.Add(container);
}
foreach (var container in containersToDelete) {
surface.RemoveElement(container, true);
}
}; };
menu.Items.Add(item); menu.Items.Add(item);
// Delete // Delete
item = new ToolStripMenuItem(Language.GetString(LangKey.editor_deleteelement)); item = new ToolStripMenuItem(Language.GetString(LangKey.editor_deleteelement));
item.Image = (Image)editorFormResources.GetObject("removeObjectToolStripMenuItem.Image"); item.Image = ((Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image")));
item.Click += delegate { item.Click += delegate {
List<DrawableContainer> containersToDelete = new List<DrawableContainer>(); surface.RemoveElements(this, true);
foreach(var drawableContainer in this) {
var container = (DrawableContainer) drawableContainer;
containersToDelete.Add(container);
}
foreach (DrawableContainer container in containersToDelete) {
surface.RemoveElement(container, true);
}
}; };
menu.Items.Add(item); menu.Items.Add(item);
// Reset // Reset
bool canReset = false; bool canReset = false;
foreach (var drawableContainer in this) { foreach (var drawableContainer in this)
var container = (DrawableContainer) drawableContainer; {
if (container.HasDefaultSize) { var container = (DrawableContainer)drawableContainer;
if (container.HasDefaultSize)
{
canReset = true; canReset = true;
} }
} }
@ -497,24 +501,29 @@ namespace Greenshot.Drawing {
item = new ToolStripMenuItem(Language.GetString(LangKey.editor_resetsize)); item = new ToolStripMenuItem(Language.GetString(LangKey.editor_resetsize));
//item.Image = ((System.Drawing.Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image"))); //item.Image = ((System.Drawing.Image)(editorFormResources.GetObject("removeObjectToolStripMenuItem.Image")));
item.Click += delegate { item.Click += delegate {
MakeBoundsChangeUndoable(false);
foreach (var drawableContainer in this) { foreach (var drawableContainer in this) {
var container = (DrawableContainer) drawableContainer; var container = (DrawableContainer) drawableContainer;
if (!container.HasDefaultSize) { if (!container.HasDefaultSize) {
continue; continue;
} }
Size defaultSize = container.DefaultSize; Size defaultSize = container.DefaultSize;
container.Invalidate();
container.MakeBoundsChangeUndoable(false); container.MakeBoundsChangeUndoable(false);
container.Width = defaultSize.Width; container.Width = defaultSize.Width;
container.Height = defaultSize.Height; container.Height = defaultSize.Height;
container.Invalidate();
} }
surface.Invalidate();
}; };
menu.Items.Add(item); menu.Items.Add(item);
} }
} }
public virtual void ShowContextMenu(MouseEventArgs e, Surface surface) { public virtual void ShowContextMenu(MouseEventArgs e, ISurface surface)
{
if (!(surface is Surface))
{
return;
}
bool hasMenu = false; bool hasMenu = false;
foreach (var drawableContainer in this) { foreach (var drawableContainer in this) {
var container = (DrawableContainer) drawableContainer; var container = (DrawableContainer) drawableContainer;
@ -528,7 +537,8 @@ namespace Greenshot.Drawing {
ContextMenuStrip menu = new ContextMenuStrip(); ContextMenuStrip menu = new ContextMenuStrip();
AddContextMenuItems(menu, surface); AddContextMenuItems(menu, surface);
if (menu.Items.Count > 0) { if (menu.Items.Count > 0) {
menu.Show(surface, e.Location); // TODO: cast should be somehow avoided
menu.Show((Surface)surface, e.Location);
while (true) { while (true) {
if (menu.Visible) { if (menu.Visible) {
Application.DoEvents(); Application.DoEvents();
@ -541,5 +551,32 @@ namespace Greenshot.Drawing {
} }
} }
} }
#region IDisposable Support
private bool _disposedValue = false; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (!_disposedValue)
{
if (disposing)
{
foreach (var drawableContainer in this)
{
drawableContainer.Dispose();
}
}
_disposedValue = true;
}
}
// This code added to correctly implement the disposable pattern.
public void Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
}
#endregion
} }
} }

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -26,39 +26,48 @@ using System.Runtime.Serialization;
using Greenshot.Configuration; using Greenshot.Configuration;
using Greenshot.IniFile; using Greenshot.IniFile;
using log4net; using log4net;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Drawing.Fields { namespace Greenshot.Drawing.Fields
{
/// <summary> /// <summary>
/// Basic IFieldHolder implementation, providing access to a set of fields /// Basic IFieldHolder implementation, providing access to a set of fields
/// </summary> /// </summary>
[Serializable] [Serializable]
public abstract class AbstractFieldHolder : IFieldHolder { public abstract class AbstractFieldHolder : IFieldHolder
{
private static readonly ILog LOG = LogManager.GetLogger(typeof(AbstractFieldHolder)); private static readonly ILog LOG = LogManager.GetLogger(typeof(AbstractFieldHolder));
private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>(); private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
/// <summary> /// <summary>
/// called when a field's value has changed /// called when a field's value has changed
/// </summary> /// </summary>
[NonSerialized] [NonSerialized]
private FieldChangedEventHandler fieldChanged; private FieldChangedEventHandler fieldChanged;
public event FieldChangedEventHandler FieldChanged { public event FieldChangedEventHandler FieldChanged
{
add { fieldChanged += value; } add { fieldChanged += value; }
remove{ fieldChanged -= value; } remove { fieldChanged -= value; }
} }
// we keep two Collections of our fields, dictionary for quick access, list for serialization // we keep two Collections of our fields, dictionary for quick access, list for serialization
// this allows us to use default serialization // this allows us to use default serialization
[NonSerialized] [NonSerialized]
private Dictionary<FieldType, Field> fieldsByType = new Dictionary<FieldType, Field>(); private IDictionary<IFieldType, IField> fieldsByType = new Dictionary<IFieldType, IField>();
private readonly List<Field> fields = new List<Field>(); private IList<IField> fields = new List<IField>();
public AbstractFieldHolder() { }
[OnDeserialized] [OnDeserialized]
private void OnFieldHolderDeserialized(StreamingContext context) { private void OnDeserialized(StreamingContext context)
fieldsByType = new Dictionary<FieldType, Field>(); {
fieldsByType = new Dictionary<IFieldType, IField>();
// listen to changing properties // listen to changing properties
foreach(Field field in fields) { foreach (Field field in fields)
{
field.PropertyChanged += delegate { field.PropertyChanged += delegate {
if (fieldChanged != null) { if (fieldChanged != null)
{
fieldChanged(this, new FieldChangedEventArgs(field)); fieldChanged(this, new FieldChangedEventArgs(field));
} }
}; };
@ -66,97 +75,124 @@ namespace Greenshot.Drawing.Fields {
} }
} }
public void AddField(Type requestingType, FieldType fieldType, object fieldValue) { public void AddField(Type requestingType, IFieldType fieldType, object fieldValue)
{
AddField(editorConfiguration.CreateField(requestingType, fieldType, fieldValue)); AddField(editorConfiguration.CreateField(requestingType, fieldType, fieldValue));
} }
public virtual void AddField(Field field) { public virtual void AddField(IField field)
if (fieldsByType != null && fieldsByType.ContainsKey(field.FieldType)) { {
if (LOG.IsDebugEnabled) { if (fieldsByType != null && fieldsByType.ContainsKey(field.FieldType))
{
if (LOG.IsDebugEnabled)
{
LOG.DebugFormat("A field with of type '{0}' already exists in this {1}, will overwrite.", field.FieldType, GetType()); LOG.DebugFormat("A field with of type '{0}' already exists in this {1}, will overwrite.", field.FieldType, GetType());
} }
} }
fields.Add(field); fields.Add(field);
fieldsByType[field.FieldType] = field; fieldsByType[field.FieldType] = field;
field.PropertyChanged += delegate { if(fieldChanged != null) fieldChanged(this, new FieldChangedEventArgs(field)); }; field.PropertyChanged += delegate { if (fieldChanged != null) fieldChanged(this, new FieldChangedEventArgs(field)); };
} }
public void RemoveField(Field field) { public void RemoveField(IField field)
{
fields.Remove(field); fields.Remove(field);
fieldsByType.Remove(field.FieldType); fieldsByType.Remove(field.FieldType);
field.PropertyChanged -= delegate { field.PropertyChanged -= delegate {
if (fieldChanged != null) { if (fieldChanged != null)
{
fieldChanged(this, new FieldChangedEventArgs(field)); fieldChanged(this, new FieldChangedEventArgs(field));
} }
}; };
} }
public List<Field> GetFields() { public IList<IField> GetFields()
{
return fields; return fields;
} }
public Field GetField(FieldType fieldType) { public IField GetField(IFieldType fieldType)
try { {
try
{
return fieldsByType[fieldType]; return fieldsByType[fieldType];
} catch(KeyNotFoundException e) { }
catch (KeyNotFoundException e)
{
throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e); throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e);
} }
} }
public object GetFieldValue(FieldType fieldType) { public object GetFieldValue(IFieldType fieldType)
{
return GetField(fieldType).Value; return GetField(fieldType).Value;
} }
#region convenience methods to save us some casts outside #region convenience methods to save us some casts outside
public string GetFieldValueAsString(FieldType fieldType) { public string GetFieldValueAsString(IFieldType fieldType)
{
return Convert.ToString(GetFieldValue(fieldType)); return Convert.ToString(GetFieldValue(fieldType));
} }
public int GetFieldValueAsInt(FieldType fieldType) { public int GetFieldValueAsInt(IFieldType fieldType)
{
return Convert.ToInt32(GetFieldValue(fieldType)); return Convert.ToInt32(GetFieldValue(fieldType));
} }
public decimal GetFieldValueAsDecimal(FieldType fieldType) { public decimal GetFieldValueAsDecimal(IFieldType fieldType)
{
return Convert.ToDecimal(GetFieldValue(fieldType)); return Convert.ToDecimal(GetFieldValue(fieldType));
} }
public double GetFieldValueAsDouble(FieldType fieldType) { public double GetFieldValueAsDouble(IFieldType fieldType)
{
return Convert.ToDouble(GetFieldValue(fieldType)); return Convert.ToDouble(GetFieldValue(fieldType));
} }
public float GetFieldValueAsFloat(FieldType fieldType) { public float GetFieldValueAsFloat(IFieldType fieldType)
{
return Convert.ToSingle(GetFieldValue(fieldType)); return Convert.ToSingle(GetFieldValue(fieldType));
} }
public bool GetFieldValueAsBool(FieldType fieldType) { public bool GetFieldValueAsBool(IFieldType fieldType)
{
return Convert.ToBoolean(GetFieldValue(fieldType)); return Convert.ToBoolean(GetFieldValue(fieldType));
} }
public Color GetFieldValueAsColor(FieldType fieldType) { public Color GetFieldValueAsColor(IFieldType fieldType)
{
return (Color)GetFieldValue(fieldType); return (Color)GetFieldValue(fieldType);
} }
#endregion #endregion
public bool HasField(FieldType fieldType) { public bool HasField(IFieldType fieldType)
{
return fieldsByType.ContainsKey(fieldType); return fieldsByType.ContainsKey(fieldType);
} }
public bool HasFieldValue(FieldType fieldType) { public bool HasFieldValue(IFieldType fieldType)
{
return HasField(fieldType) && fieldsByType[fieldType].HasValue; return HasField(fieldType) && fieldsByType[fieldType].HasValue;
} }
public void SetFieldValue(FieldType fieldType, object value) { public void SetFieldValue(IFieldType fieldType, object value)
try { {
try
{
fieldsByType[fieldType].Value = value; fieldsByType[fieldType].Value = value;
} catch(KeyNotFoundException e) { }
throw new ArgumentException("Field '"+fieldType+"' does not exist in " + GetType(), e); catch (KeyNotFoundException e)
{
throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType(), e);
} }
} }
protected void OnFieldChanged(object sender, FieldChangedEventArgs e){ protected void OnFieldChanged(object sender, FieldChangedEventArgs e)
if (fieldChanged != null) { {
if (fieldChanged != null)
{
fieldChanged(sender, e); fieldChanged(sender, e);
} }
} }

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,86 +18,110 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using GreenshotPlugin.Interfaces.Drawing;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.Serialization; using System.Runtime.Serialization;
namespace Greenshot.Drawing.Fields { namespace Greenshot.Drawing.Fields
{
/// <summary> /// <summary>
/// Basic IFieldHolderWithChildren implementation. Similar to IFieldHolder, /// Basic IFieldHolderWithChildren implementation. Similar to IFieldHolder,
/// but has a List<IFieldHolder> of children. /// but has a List<IFieldHolder> of children.
/// Field values are passed to and from children as well. /// Field values are passed to and from children as well.
/// </summary> /// </summary>
[Serializable()] [Serializable()]
public abstract class AbstractFieldHolderWithChildren : AbstractFieldHolder { public abstract class AbstractFieldHolderWithChildren : AbstractFieldHolder
readonly FieldChangedEventHandler fieldChangedEventHandler; {
FieldChangedEventHandler fieldChangedEventHandler;
[NonSerialized] [NonSerialized]
private EventHandler childrenChanged; private EventHandler childrenChanged;
public event EventHandler ChildrenChanged { public event EventHandler ChildrenChanged
{
add { childrenChanged += value; } add { childrenChanged += value; }
remove { childrenChanged -= value; } remove { childrenChanged -= value; }
} }
public List<IFieldHolder> Children = new List<IFieldHolder>(); public List<IFieldHolder> Children = new List<IFieldHolder>();
public AbstractFieldHolderWithChildren() { public AbstractFieldHolderWithChildren()
{
fieldChangedEventHandler = OnFieldChanged; fieldChangedEventHandler = OnFieldChanged;
} }
[OnDeserialized] [OnDeserialized()]
private void OnFieldHolderWithChildrenDeserialized(StreamingContext context) { private void OnDeserialized(StreamingContext context)
{
// listen to changing properties // listen to changing properties
foreach(IFieldHolder fieldHolder in Children) { foreach (IFieldHolder fieldHolder in Children)
{
fieldHolder.FieldChanged += fieldChangedEventHandler; fieldHolder.FieldChanged += fieldChangedEventHandler;
} }
if(childrenChanged != null) childrenChanged(this, EventArgs.Empty); if (childrenChanged != null) childrenChanged(this, EventArgs.Empty);
} }
public void AddChild(IFieldHolder fieldHolder) { public void AddChild(IFieldHolder fieldHolder)
{
Children.Add(fieldHolder); Children.Add(fieldHolder);
fieldHolder.FieldChanged += fieldChangedEventHandler; fieldHolder.FieldChanged += fieldChangedEventHandler;
if(childrenChanged != null) childrenChanged(this, EventArgs.Empty); if (childrenChanged != null) childrenChanged(this, EventArgs.Empty);
} }
public void RemoveChild(IFieldHolder fieldHolder) { public void RemoveChild(IFieldHolder fieldHolder)
{
Children.Remove(fieldHolder); Children.Remove(fieldHolder);
fieldHolder.FieldChanged -= fieldChangedEventHandler; fieldHolder.FieldChanged -= fieldChangedEventHandler;
if(childrenChanged != null) childrenChanged(this, EventArgs.Empty); if (childrenChanged != null) childrenChanged(this, EventArgs.Empty);
} }
public new List<Field> GetFields() { public new IList<IField> GetFields()
List<Field> ret = new List<Field>(); {
List<IField> ret = new List<IField>();
ret.AddRange(base.GetFields()); ret.AddRange(base.GetFields());
foreach(IFieldHolder fh in Children) { foreach (IFieldHolder fh in Children)
{
ret.AddRange(fh.GetFields()); ret.AddRange(fh.GetFields());
} }
return ret; return ret;
} }
public new Field GetField(FieldType fieldType) { public new IField GetField(IFieldType fieldType)
Field ret = null; {
if(base.HasField(fieldType)) { IField ret = null;
if (base.HasField(fieldType))
{
ret = base.GetField(fieldType); ret = base.GetField(fieldType);
} else { }
foreach(IFieldHolder fh in Children) { else
if(fh.HasField(fieldType)) { {
foreach (IFieldHolder fh in Children)
{
if (fh.HasField(fieldType))
{
ret = fh.GetField(fieldType); ret = fh.GetField(fieldType);
break; break;
} }
} }
} }
if(ret == null) { if (ret == null)
throw new ArgumentException("Field '"+fieldType+"' does not exist in " + GetType()); {
throw new ArgumentException("Field '" + fieldType + "' does not exist in " + GetType());
} }
return ret; return ret;
} }
public new bool HasField(FieldType fieldType) { public new bool HasField(IFieldType fieldType)
{
bool ret = base.HasField(fieldType); bool ret = base.HasField(fieldType);
if(!ret) { if (!ret)
foreach(IFieldHolder fh in Children) { {
if(fh.HasField(fieldType)) { foreach (IFieldHolder fh in Children)
{
if (fh.HasField(fieldType))
{
ret = true; ret = true;
break; break;
} }
@ -106,14 +130,16 @@ namespace Greenshot.Drawing.Fields {
return ret; return ret;
} }
public new bool HasFieldValue(FieldType fieldType) { public new bool HasFieldValue(IFieldType fieldType)
Field f = GetField(fieldType); {
IField f = GetField(fieldType);
return f != null && f.HasValue; return f != null && f.HasValue;
} }
public new void SetFieldValue(FieldType fieldType, object value) { public new void SetFieldValue(IFieldType fieldType, object value)
Field f = GetField(fieldType); {
if(f != null) f.Value = value; IField f = GetField(fieldType);
if (f != null) f.Value = value;
} }
} }

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,35 +18,52 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using GreenshotPlugin.Interfaces.Drawing;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
namespace Greenshot.Drawing.Fields { namespace Greenshot.Drawing.Fields
{
/// <summary> /// <summary>
/// Represents a single field of a drawable element, i.e. /// Represents a single field of a drawable element, i.e.
/// line thickness of a rectangle. /// line thickness of a rectangle.
/// </summary> /// </summary>
[Serializable] [Serializable]
public class Field : INotifyPropertyChanged { public class Field : IField
[field:NonSerialized] {
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged; public event PropertyChangedEventHandler PropertyChanged;
public object myValue; private object _myValue;
public object Value { public object Value
get { {
return myValue; get
{
return _myValue;
} }
set { set
if (!Equals(myValue,value)) { {
myValue = value; if (!Equals(_myValue, value))
if (PropertyChanged!=null) { {
_myValue = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Value")); PropertyChanged(this, new PropertyChangedEventArgs("Value"));
} }
} }
} }
} }
public FieldType FieldType; public IFieldType FieldType
public string Scope; {
get;
set;
}
public string Scope
{
get;
set;
}
/// <summary> /// <summary>
/// Constructs a new Field instance, usually you should be using FieldFactory /// Constructs a new Field instance, usually you should be using FieldFactory
@ -59,37 +76,44 @@ namespace Greenshot.Drawing.Fields {
/// When scope is set to a Type (e.g. typeof(RectangleContainer)), its value /// When scope is set to a Type (e.g. typeof(RectangleContainer)), its value
/// should not be reused for FieldHolders of another Type (e.g. typeof(EllipseContainer)) /// should not be reused for FieldHolders of another Type (e.g. typeof(EllipseContainer))
/// </param> /// </param>
public Field(FieldType fieldType, Type scope) { public Field(IFieldType fieldType, Type scope)
{
FieldType = fieldType; FieldType = fieldType;
Scope = scope.Name; Scope = scope.Name;
} }
public Field(FieldType fieldType, string scope) { public Field(IFieldType fieldType, string scope)
{
FieldType = fieldType; FieldType = fieldType;
Scope = scope; Scope = scope;
} }
public Field(FieldType fieldType) { public Field(IFieldType fieldType)
{
FieldType = fieldType; FieldType = fieldType;
} }
/// <summary> /// <summary>
/// Returns true if this field holds a value other than null. /// Returns true if this field holds a value other than null.
/// </summary> /// </summary>
public bool HasValue { public bool HasValue
get{ return Value != null; } {
get { return Value != null; }
} }
/// <summary> /// <summary>
/// Creates a flat clone of this Field. The fields value itself is not cloned. /// Creates a flat clone of this Field. The fields value itself is not cloned.
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public Field Clone() { public Field Clone()
{
Field ret = new Field(FieldType, Scope); Field ret = new Field(FieldType, Scope);
ret.Value = Value; ret.Value = Value;
return ret; return ret;
} }
public override int GetHashCode() { public override int GetHashCode()
{
int hashCode = 0; int hashCode = 0;
unchecked { unchecked
{
hashCode += 1000000009 * FieldType.GetHashCode(); hashCode += 1000000009 * FieldType.GetHashCode();
if (Scope != null) if (Scope != null)
hashCode += 1000000021 * Scope.GetHashCode(); hashCode += 1000000021 * Scope.GetHashCode();
@ -97,32 +121,19 @@ namespace Greenshot.Drawing.Fields {
return hashCode; return hashCode;
} }
public override bool Equals(object obj) { public override bool Equals(object obj)
{
Field other = obj as Field; Field other = obj as Field;
if (other == null) { if (other == null)
{
return false; return false;
} }
return FieldType == other.FieldType && Equals(Scope, other.Scope); return FieldType == other.FieldType && Equals(Scope, other.Scope);
} }
public override string ToString() { public override string ToString()
return string.Format("[Field FieldType={1} Value={0} Scope={2}]", myValue, FieldType, Scope); {
} return string.Format("[Field FieldType={1} Value={0} Scope={2}]", _myValue, FieldType, Scope);
}
/// <summary>
/// EventHandler to be used when a field value changes
/// </summary>
public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e);
/// <summary>
/// EventArgs to be used with FieldChangedEventHandler
/// </summary>
public class FieldChangedEventArgs : EventArgs {
public readonly Field Field;
public FieldChangedEventArgs(Field field) {
Field = field;
} }
} }
} }

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,14 +19,18 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Greenshot.Configuration;
using Greenshot.IniFile;
using Greenshot.Plugin;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Interfaces;
using GreenshotPlugin.Interfaces.Drawing;
using log4net;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using Greenshot.Configuration; namespace Greenshot.Drawing.Fields
using Greenshot.IniFile; {
using Greenshot.Plugin.Drawing;
namespace Greenshot.Drawing.Fields {
/// <summary> /// <summary>
/// Represents the current set of properties for the editor. /// Represents the current set of properties for the editor.
/// When one of EditorProperties' properties is updated, the change will be promoted /// When one of EditorProperties' properties is updated, the change will be promoted
@ -38,35 +42,47 @@ namespace Greenshot.Drawing.Fields {
/// Properties that do not apply for ALL selected elements are null (or 0 respectively) /// Properties that do not apply for ALL selected elements are null (or 0 respectively)
/// If the property values of the selected elements differ, the value of the last bound element wins. /// If the property values of the selected elements differ, the value of the last bound element wins.
/// </summary> /// </summary>
public class FieldAggregator : AbstractFieldHolder { public class FieldAggregator : AbstractFieldHolder
{
private readonly List<IDrawableContainer> boundContainers; private IDrawableContainerList boundContainers;
private bool internalUpdateRunning; private bool internalUpdateRunning = false;
private static readonly EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>(); enum Status { IDLE, BINDING, UPDATING };
public FieldAggregator() { private static readonly ILog LOG = LogManager.GetLogger(typeof(FieldAggregator));
foreach(FieldType fieldType in FieldType.Values) { private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection<EditorConfiguration>();
public FieldAggregator(ISurface parent)
{
foreach (FieldType fieldType in FieldType.Values)
{
Field field = new Field(fieldType, GetType()); Field field = new Field(fieldType, GetType());
AddField(field); AddField(field);
} }
boundContainers = new List<IDrawableContainer>(); boundContainers = new DrawableContainerList();
boundContainers.Parent = parent;
} }
public override void AddField(Field field) { public override void AddField(IField field)
{
base.AddField(field); base.AddField(field);
field.PropertyChanged += OwnPropertyChanged; field.PropertyChanged += OwnPropertyChanged;
} }
public void BindElements(DrawableContainerList dcs) { public void BindElements(IDrawableContainerList dcs)
foreach(DrawableContainer dc in dcs) { {
foreach (DrawableContainer dc in dcs)
{
BindElement(dc); BindElement(dc);
} }
} }
public void BindElement(IDrawableContainer dc) { public void BindElement(IDrawableContainer dc)
{
DrawableContainer container = dc as DrawableContainer; DrawableContainer container = dc as DrawableContainer;
if (container != null && !boundContainers.Contains(container)) { if (container != null && !boundContainers.Contains(container))
{
boundContainers.Add(container); boundContainers.Add(container);
container.ChildrenChanged += delegate { container.ChildrenChanged += delegate {
UpdateFromBoundElements(); UpdateFromBoundElements();
@ -75,19 +91,24 @@ namespace Greenshot.Drawing.Fields {
} }
} }
public void BindAndUpdateElement(IDrawableContainer dc) { public void BindAndUpdateElement(IDrawableContainer dc)
{
UpdateElement(dc); UpdateElement(dc);
BindElement(dc); BindElement(dc);
} }
public void UpdateElement(IDrawableContainer dc) { public void UpdateElement(IDrawableContainer dc)
{
DrawableContainer container = dc as DrawableContainer; DrawableContainer container = dc as DrawableContainer;
if (container == null) { if (container == null)
{
return; return;
} }
internalUpdateRunning = true; internalUpdateRunning = true;
foreach(Field field in GetFields()) { foreach (Field field in GetFields())
if (container.HasField(field.FieldType) && field.HasValue) { {
if (container.HasField(field.FieldType) && field.HasValue)
{
//if(LOG.IsDebugEnabled) LOG.Debug(" "+field+ ": "+field.Value); //if(LOG.IsDebugEnabled) LOG.Debug(" "+field+ ": "+field.Value);
container.SetFieldValue(field.FieldType, field.Value); container.SetFieldValue(field.FieldType, field.Value);
} }
@ -95,14 +116,17 @@ namespace Greenshot.Drawing.Fields {
internalUpdateRunning = false; internalUpdateRunning = false;
} }
public void UnbindElement(IDrawableContainer dc) { public void UnbindElement(IDrawableContainer dc)
if (boundContainers.Contains(dc)) { {
if (boundContainers.Contains(dc))
{
boundContainers.Remove(dc); boundContainers.Remove(dc);
UpdateFromBoundElements(); UpdateFromBoundElements();
} }
} }
public void Clear() { public void Clear()
{
ClearFields(); ClearFields();
boundContainers.Clear(); boundContainers.Clear();
UpdateFromBoundElements(); UpdateFromBoundElements();
@ -111,9 +135,11 @@ namespace Greenshot.Drawing.Fields {
/// <summary> /// <summary>
/// sets all field values to null, however does not remove fields /// sets all field values to null, however does not remove fields
/// </summary> /// </summary>
private void ClearFields() { private void ClearFields()
{
internalUpdateRunning = true; internalUpdateRunning = true;
foreach(Field field in GetFields()) { foreach (Field field in GetFields())
{
field.Value = null; field.Value = null;
} }
internalUpdateRunning = false; internalUpdateRunning = false;
@ -124,51 +150,66 @@ namespace Greenshot.Drawing.Fields {
/// Fields that do not apply to every bound element are set to null, or 0 respectively. /// Fields that do not apply to every bound element are set to null, or 0 respectively.
/// All other fields will be set to the field value of the least bound element. /// All other fields will be set to the field value of the least bound element.
/// </summary> /// </summary>
private void UpdateFromBoundElements() { private void UpdateFromBoundElements()
{
ClearFields(); ClearFields();
internalUpdateRunning = true; internalUpdateRunning = true;
foreach(Field field in FindCommonFields()) { foreach (Field field in FindCommonFields())
{
SetFieldValue(field.FieldType, field.Value); SetFieldValue(field.FieldType, field.Value);
} }
internalUpdateRunning = false; internalUpdateRunning = false;
} }
private List<Field> FindCommonFields() { private IList<IField> FindCommonFields()
List<Field> returnFields = null; {
if (boundContainers.Count > 0) { IList<IField> returnFields = null;
if (boundContainers.Count > 0)
{
// take all fields from the least selected container... // take all fields from the least selected container...
DrawableContainer leastSelectedContainer = boundContainers[boundContainers.Count - 1] as DrawableContainer; DrawableContainer leastSelectedContainer = boundContainers[boundContainers.Count - 1] as DrawableContainer;
if (leastSelectedContainer != null) { if (leastSelectedContainer != null)
{
returnFields = leastSelectedContainer.GetFields(); returnFields = leastSelectedContainer.GetFields();
for (int i = 0; i < boundContainers.Count - 1; i++) { for (int i = 0; i < boundContainers.Count - 1; i++)
{
DrawableContainer dc = boundContainers[i] as DrawableContainer; DrawableContainer dc = boundContainers[i] as DrawableContainer;
if (dc != null) { if (dc != null)
List<Field> fieldsToRemove = new List<Field>(); {
foreach (Field f in returnFields) { IList<IField> fieldsToRemove = new List<IField>();
foreach (IField field in returnFields)
{
// ... throw out those that do not apply to one of the other containers // ... throw out those that do not apply to one of the other containers
if (!dc.HasField(f.FieldType)) { if (!dc.HasField(field.FieldType))
fieldsToRemove.Add(f); {
fieldsToRemove.Add(field);
} }
} }
foreach (Field f in fieldsToRemove) { foreach (IField field in fieldsToRemove)
returnFields.Remove(f); {
returnFields.Remove(field);
} }
} }
} }
} }
} }
if (returnFields == null) { if (returnFields == null)
returnFields = new List<Field>(); {
returnFields = new List<IField>();
} }
return returnFields; return returnFields;
} }
public void OwnPropertyChanged(object sender, PropertyChangedEventArgs ea) { public void OwnPropertyChanged(object sender, PropertyChangedEventArgs ea)
Field field = (Field) sender; {
if (!internalUpdateRunning && field.Value != null) { IField field = (IField)sender;
foreach(DrawableContainer drawableContainer in boundContainers) { if (!internalUpdateRunning && field.Value != null)
if (drawableContainer.HasField(field.FieldType)) { {
Field drawableContainerField = drawableContainer.GetField(field.FieldType); foreach (DrawableContainer drawableContainer in boundContainers)
{
if (drawableContainer.HasField(field.FieldType))
{
IField drawableContainerField = drawableContainer.GetField(field.FieldType);
// Notify before change, so we can e.g. invalidate the area // Notify before change, so we can e.g. invalidate the area
drawableContainer.BeforeFieldChange(drawableContainerField, field.Value); drawableContainer.BeforeFieldChange(drawableContainerField, field.Value);

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,38 +18,41 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using GreenshotPlugin.Interfaces.Drawing;
using System; using System;
namespace Greenshot.Drawing.Fields { namespace Greenshot.Drawing.Fields
{
/// <summary> /// <summary>
/// Defines all FieldTypes + their default value. /// Defines all FieldTypes + their default value.
/// (The additional value is why this is not an enum) /// (The additional value is why this is not an enum)
/// </summary> /// </summary>
[Serializable] [Serializable]
public class FieldType { public class FieldType : IFieldType
{
public static readonly FieldType ARROWHEADS = new FieldType("ARROWHEADS"); public static readonly IFieldType ARROWHEADS = new FieldType("ARROWHEADS");
public static readonly FieldType BLUR_RADIUS = new FieldType("BLUR_RADIUS"); public static readonly IFieldType BLUR_RADIUS = new FieldType("BLUR_RADIUS");
public static readonly FieldType BRIGHTNESS = new FieldType("BRIGHTNESS"); public static readonly IFieldType BRIGHTNESS = new FieldType("BRIGHTNESS");
public static readonly FieldType FILL_COLOR = new FieldType("FILL_COLOR"); public static readonly IFieldType FILL_COLOR = new FieldType("FILL_COLOR");
public static readonly FieldType FONT_BOLD = new FieldType("FONT_BOLD"); public static readonly IFieldType FONT_BOLD = new FieldType("FONT_BOLD");
public static readonly FieldType FONT_FAMILY = new FieldType("FONT_FAMILY"); public static readonly IFieldType FONT_FAMILY = new FieldType("FONT_FAMILY");
public static readonly FieldType FONT_ITALIC = new FieldType("FONT_ITALIC"); public static readonly IFieldType FONT_ITALIC = new FieldType("FONT_ITALIC");
public static readonly FieldType FONT_SIZE = new FieldType("FONT_SIZE"); public static readonly IFieldType FONT_SIZE = new FieldType("FONT_SIZE");
public static readonly FieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType("TEXT_HORIZONTAL_ALIGNMENT"); public static readonly IFieldType TEXT_HORIZONTAL_ALIGNMENT = new FieldType("TEXT_HORIZONTAL_ALIGNMENT");
public static readonly FieldType TEXT_VERTICAL_ALIGNMENT = new FieldType("TEXT_VERTICAL_ALIGNMENT"); public static readonly IFieldType TEXT_VERTICAL_ALIGNMENT = new FieldType("TEXT_VERTICAL_ALIGNMENT");
public static readonly FieldType HIGHLIGHT_COLOR = new FieldType("HIGHLIGHT_COLOR"); public static readonly IFieldType HIGHLIGHT_COLOR = new FieldType("HIGHLIGHT_COLOR");
public static readonly FieldType LINE_COLOR = new FieldType("LINE_COLOR"); public static readonly IFieldType LINE_COLOR = new FieldType("LINE_COLOR");
public static readonly FieldType LINE_THICKNESS = new FieldType("LINE_THICKNESS"); public static readonly IFieldType LINE_THICKNESS = new FieldType("LINE_THICKNESS");
public static readonly FieldType MAGNIFICATION_FACTOR = new FieldType("MAGNIFICATION_FACTOR"); public static readonly IFieldType MAGNIFICATION_FACTOR = new FieldType("MAGNIFICATION_FACTOR");
public static readonly FieldType PIXEL_SIZE = new FieldType("PIXEL_SIZE"); public static readonly IFieldType PIXEL_SIZE = new FieldType("PIXEL_SIZE");
public static readonly FieldType PREVIEW_QUALITY = new FieldType("PREVIEW_QUALITY"); public static readonly IFieldType PREVIEW_QUALITY = new FieldType("PREVIEW_QUALITY");
public static readonly FieldType SHADOW = new FieldType("SHADOW"); public static readonly IFieldType SHADOW = new FieldType("SHADOW");
public static readonly FieldType PREPARED_FILTER_OBFUSCATE = new FieldType("PREPARED_FILTER_OBFUSCATE"); public static readonly IFieldType PREPARED_FILTER_OBFUSCATE = new FieldType("PREPARED_FILTER_OBFUSCATE");
public static readonly FieldType PREPARED_FILTER_HIGHLIGHT = new FieldType("PREPARED_FILTER_HIGHLIGHT"); public static readonly IFieldType PREPARED_FILTER_HIGHLIGHT = new FieldType("PREPARED_FILTER_HIGHLIGHT");
public static readonly FieldType FLAGS = new FieldType("FLAGS"); public static readonly IFieldType FLAGS = new FieldType("FLAGS");
public static FieldType[] Values = new FieldType[]{ public static IFieldType[] Values = new IFieldType[]{
ARROWHEADS, ARROWHEADS,
BLUR_RADIUS, BLUR_RADIUS,
BRIGHTNESS, BRIGHTNESS,
@ -72,24 +75,25 @@ namespace Greenshot.Drawing.Fields {
FLAGS FLAGS
}; };
[Flags] public string Name
public enum Flag { {
NONE = 0, get;
CONFIRMABLE = 1 set;
} }
private FieldType(string name)
public string Name; {
private FieldType(string name) {
Name = name; Name = name;
} }
public override string ToString() { public override string ToString()
{
return Name; return Name;
} }
public override int GetHashCode() public override int GetHashCode()
{ {
int hashCode = 0; int hashCode = 0;
unchecked { unchecked
{
if (Name != null) if (Name != null)
hashCode += 1000000009 * Name.GetHashCode(); hashCode += 1000000009 * Name.GetHashCode();
} }
@ -100,19 +104,20 @@ namespace Greenshot.Drawing.Fields {
{ {
FieldType other = obj as FieldType; FieldType other = obj as FieldType;
if (other == null) if (other == null)
{
return false; return false;
return Equals(Name,other.Name); }
return Equals(Name, other.Name);
} }
public static bool operator ==(FieldType a, FieldType b) { public static bool operator ==(FieldType a, FieldType b)
return Equals(a,b); {
return Equals(a, b);
} }
public static bool operator !=(FieldType a, FieldType b) { public static bool operator !=(FieldType a, FieldType b)
return !Equals(a,b); {
return !Equals(a, b);
} }
} }
} }

View file

@ -21,11 +21,11 @@
using System.ComponentModel; using System.ComponentModel;
using System.Drawing; using System.Drawing;
using Greenshot.Drawing.Fields;
using Greenshot.Plugin.Drawing; using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Drawing.Filters { namespace Greenshot.Drawing.Filters
{
public interface IFilter : INotifyPropertyChanged, IFieldHolder { public interface IFilter : INotifyPropertyChanged, IFieldHolder {
DrawableContainer Parent {get; set; } DrawableContainer Parent {get; set; }
void Apply(Graphics graphics, Bitmap bmp, Rectangle rect, RenderMode renderMode); void Apply(Graphics graphics, Bitmap bmp, Rectangle rect, RenderMode renderMode);

View file

@ -23,6 +23,7 @@ using System.Runtime.Serialization;
using Greenshot.Drawing.Fields; using Greenshot.Drawing.Fields;
using Greenshot.Drawing.Filters; using Greenshot.Drawing.Filters;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Drawing { namespace Greenshot.Drawing {
/// <summary> /// <summary>

View file

@ -28,6 +28,7 @@ using System.Drawing.Drawing2D;
using Greenshot.Core; using Greenshot.Core;
using log4net; using log4net;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Drawing { namespace Greenshot.Drawing {
/// <summary> /// <summary>

View file

@ -22,6 +22,7 @@ using System;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using Greenshot.Drawing.Fields; using Greenshot.Drawing.Fields;
using Greenshot.Drawing.Filters; using Greenshot.Drawing.Filters;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Drawing { namespace Greenshot.Drawing {
/// <summary> /// <summary>

View file

@ -48,8 +48,8 @@ namespace Greenshot.Drawing
/// <param name="context"></param> /// <param name="context"></param>
[OnSerializing] [OnSerializing]
private void SetValuesOnSerializing(StreamingContext context) { private void SetValuesOnSerializing(StreamingContext context) {
if (TargetGripper != null) { if (TargetAdorner != null) {
_storedTargetGripperLocation = TargetGripper.Location; _storedTargetGripperLocation = TargetAdorner.Location;
} }
} }
@ -59,7 +59,7 @@ namespace Greenshot.Drawing
/// <param name="context"></param> /// <param name="context"></param>
protected override void OnDeserialized(StreamingContext context) protected override void OnDeserialized(StreamingContext context)
{ {
InitTargetGripper(Color.Green, _storedTargetGripperLocation); InitAdorner(Color.Green, _storedTargetGripperLocation);
} }
#endregion #endregion
@ -88,9 +88,9 @@ namespace Greenshot.Drawing
/// </summary> /// </summary>
/// <returns>true if the surface doesn't need to handle the event</returns> /// <returns>true if the surface doesn't need to handle the event</returns>
public override bool HandleMouseDown(int mouseX, int mouseY) { public override bool HandleMouseDown(int mouseX, int mouseY) {
if (TargetGripper == null) { if (TargetAdorner == null) {
_initialGripperPoint = new Point(mouseX, mouseY); _initialGripperPoint = new Point(mouseX, mouseY);
InitTargetGripper(Color.Green, new Point(mouseX, mouseY)); InitAdorner(Color.Green, new Point(mouseX, mouseY));
} }
return base.HandleMouseDown(mouseX, mouseY); return base.HandleMouseDown(mouseX, mouseY);
} }
@ -114,9 +114,9 @@ namespace Greenshot.Drawing
Point newGripperLocation = _initialGripperPoint; Point newGripperLocation = _initialGripperPoint;
newGripperLocation.Offset(xOffset, yOffset); newGripperLocation.Offset(xOffset, yOffset);
if (TargetGripper.Location != newGripperLocation) { if (TargetAdorner.Location != newGripperLocation) {
Invalidate(); Invalidate();
TargetGripper.Location = newGripperLocation; TargetAdorner.Location = newGripperLocation;
Invalidate(); Invalidate();
} }
return returnValue; return returnValue;
@ -178,7 +178,7 @@ namespace Greenshot.Drawing
private GraphicsPath CreateTail() { private GraphicsPath CreateTail() {
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
int tailLength = GeometryHelper.Distance2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetGripper.Location.X, TargetGripper.Location.Y); int tailLength = GeometryHelper.Distance2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetAdorner.Location.X, TargetAdorner.Location.Y);
int tailWidth = (Math.Abs(rect.Width) + Math.Abs(rect.Height)) / 20; int tailWidth = (Math.Abs(rect.Width) + Math.Abs(rect.Height)) / 20;
// This should fix a problem with the tail being to wide // This should fix a problem with the tail being to wide
@ -190,7 +190,7 @@ namespace Greenshot.Drawing
tail.AddLine(tailWidth, 0, 0, -tailLength); tail.AddLine(tailWidth, 0, 0, -tailLength);
tail.CloseFigure(); tail.CloseFigure();
int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetGripper.Location.X, TargetGripper.Location.Y); int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2, TargetAdorner.Location.X, TargetAdorner.Location.Y);
using (Matrix tailMatrix = new Matrix()) { using (Matrix tailMatrix = new Matrix()) {
tailMatrix.Translate(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2); tailMatrix.Translate(rect.Left + rect.Width / 2, rect.Top + rect.Height / 2);
@ -207,7 +207,7 @@ namespace Greenshot.Drawing
/// <param name="graphics"></param> /// <param name="graphics"></param>
/// <param name="renderMode"></param> /// <param name="renderMode"></param>
public override void Draw(Graphics graphics, RenderMode renderMode) { public override void Draw(Graphics graphics, RenderMode renderMode) {
if (TargetGripper == null) { if (TargetAdorner == null) {
return; return;
} }
graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality;

View file

@ -94,6 +94,10 @@ namespace Greenshot.Drawing {
/// </summary> /// </summary>
/// <param name="newParent"></param> /// <param name="newParent"></param>
protected override void SwitchParent(Surface newParent) { protected override void SwitchParent(Surface newParent) {
if (newParent == Parent)
{
return;
}
if (Parent != null) { if (Parent != null) {
((Surface)Parent).RemoveStepLabel(this); ((Surface)Parent).RemoveStepLabel(this);
} }

File diff suppressed because it is too large Load diff

View file

@ -23,6 +23,7 @@ using Greenshot.Drawing.Fields;
using Greenshot.Helpers; using Greenshot.Helpers;
using Greenshot.Memento; using Greenshot.Memento;
using Greenshot.Plugin.Drawing; using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Interfaces.Drawing;
using System; using System;
using System.ComponentModel; using System.ComponentModel;
using System.Drawing; using System.Drawing;

View file

@ -30,8 +30,10 @@ using Greenshot.Help;
using Greenshot.Helpers; using Greenshot.Helpers;
using Greenshot.IniFile; using Greenshot.IniFile;
using Greenshot.Plugin; using Greenshot.Plugin;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Controls; using GreenshotPlugin.Controls;
using GreenshotPlugin.Core; using GreenshotPlugin.Core;
using GreenshotPlugin.Interfaces.Drawing;
using GreenshotPlugin.UnmanagedHelpers; using GreenshotPlugin.UnmanagedHelpers;
using log4net; using log4net;
using System; using System;
@ -56,7 +58,7 @@ namespace Greenshot {
private Surface _surface; private Surface _surface;
private GreenshotToolStripButton[] _toolbarButtons; private GreenshotToolStripButton[] _toolbarButtons;
private static readonly string[] SupportedClipboardFormats = {typeof(string).FullName, "Text", typeof(DrawableContainerList).FullName}; private static readonly string[] SupportedClipboardFormats = {typeof(string).FullName, "Text", typeof(IDrawableContainerList).FullName};
private bool _originalBoldCheckState; private bool _originalBoldCheckState;
private bool _originalItalicCheckState; private bool _originalItalicCheckState;
@ -1045,7 +1047,7 @@ namespace Greenshot {
textVerticalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT); textVerticalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT);
shadowButton.Visible = props.HasFieldValue(FieldType.SHADOW); shadowButton.Visible = props.HasFieldValue(FieldType.SHADOW);
btnConfirm.Visible = btnCancel.Visible = props.HasFieldValue(FieldType.FLAGS) btnConfirm.Visible = btnCancel.Visible = props.HasFieldValue(FieldType.FLAGS)
&& ((FieldType.Flag)props.GetFieldValue(FieldType.FLAGS)&FieldType.Flag.CONFIRMABLE) == FieldType.Flag.CONFIRMABLE; && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE;
obfuscateModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE); obfuscateModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE);
highlightModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); highlightModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT);
@ -1078,9 +1080,10 @@ namespace Greenshot {
FieldAggregator props = _surface.FieldAggregator; FieldAggregator props = _surface.FieldAggregator;
// if a confirmable element is selected, we must disable most of the controls // if a confirmable element is selected, we must disable most of the controls
// since we demand confirmation or cancel for confirmable element // since we demand confirmation or cancel for confirmable element
if (props.HasFieldValue(FieldType.FLAGS) && ((FieldType.Flag)props.GetFieldValue(FieldType.FLAGS) & FieldType.Flag.CONFIRMABLE) == FieldType.Flag.CONFIRMABLE) { if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE)
{
// disable most controls // disable most controls
if(!_controlsDisabledDueToConfirmable) { if (!_controlsDisabledDueToConfirmable) {
ToolStripItemEndisabler.Disable(menuStrip1); ToolStripItemEndisabler.Disable(menuStrip1);
ToolStripItemEndisabler.Disable(destinationsToolStrip); ToolStripItemEndisabler.Disable(destinationsToolStrip);
ToolStripItemEndisabler.Disable(toolsToolStrip); ToolStripItemEndisabler.Disable(toolsToolStrip);

View file

@ -112,7 +112,6 @@
<Compile Include="Drawing\Fields\AbstractFieldHolder.cs" /> <Compile Include="Drawing\Fields\AbstractFieldHolder.cs" />
<Compile Include="Drawing\Fields\Field.cs" /> <Compile Include="Drawing\Fields\Field.cs" />
<Compile Include="Drawing\Fields\FieldType.cs" /> <Compile Include="Drawing\Fields\FieldType.cs" />
<Compile Include="Drawing\Fields\IFieldHolder.cs" />
<Compile Include="Drawing\Fields\FieldAggregator.cs" /> <Compile Include="Drawing\Fields\FieldAggregator.cs" />
<Compile Include="Drawing\ObfuscateContainer.cs" /> <Compile Include="Drawing\ObfuscateContainer.cs" />
<Compile Include="Drawing\FreehandContainer.cs" /> <Compile Include="Drawing\FreehandContainer.cs" />
@ -215,13 +214,14 @@
<Compile Include="Helpers\IEInterop\IEContainer.cs" /> <Compile Include="Helpers\IEInterop\IEContainer.cs" />
<Compile Include="Helpers\ProcessorHelper.cs" /> <Compile Include="Helpers\ProcessorHelper.cs" />
<Compile Include="Help\HelpFileLoader.cs" /> <Compile Include="Help\HelpFileLoader.cs" />
<Compile Include="Memento\AddElementsMemento.cs" />
<Compile Include="Memento\DeleteElementsMemento.cs" />
<Compile Include="Processors\TitleFixProcessor.cs" /> <Compile Include="Processors\TitleFixProcessor.cs" />
<Compile Include="Helpers\WindowWrapper.cs" /> <Compile Include="Helpers\WindowWrapper.cs" />
<Compile Include="Memento\AddElementMemento.cs" /> <Compile Include="Memento\AddElementMemento.cs" />
<Compile Include="Memento\ChangeFieldHolderMemento.cs" /> <Compile Include="Memento\ChangeFieldHolderMemento.cs" />
<Compile Include="Memento\DeleteElementMemento.cs" /> <Compile Include="Memento\DeleteElementMemento.cs" />
<Compile Include="Memento\TextChangeMemento.cs" /> <Compile Include="Memento\TextChangeMemento.cs" />
<Compile Include="Memento\IMemento.cs" />
<Compile Include="Memento\DrawableContainerBoundsChangeMemento.cs" /> <Compile Include="Memento\DrawableContainerBoundsChangeMemento.cs" />
<Compile Include="Memento\SurfaceBackgroundChangeMemento.cs" /> <Compile Include="Memento\SurfaceBackgroundChangeMemento.cs" />
<Compile Include="Helpers\UpdateHelper.cs" /> <Compile Include="Helpers\UpdateHelper.cs" />

View file

@ -47,12 +47,6 @@ namespace Greenshot.Memento {
_surface = null; _surface = null;
} }
public LangKey ActionLanguageKey {
get {
return LangKey.none;
}
}
public bool Merge(IMemento otherMemento) { public bool Merge(IMemento otherMemento) {
return false; return false;
} }

View file

@ -0,0 +1,77 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing;
using Greenshot.Plugin.Drawing;
namespace Greenshot.Memento
{
/// <summary>
/// The AddElementMemento makes it possible to undo adding an element
/// </summary>
public class AddElementsMemento : IMemento
{
private IDrawableContainerList _containerList;
private Surface _surface;
public AddElementsMemento(Surface surface, IDrawableContainerList containerList)
{
_surface = surface;
_containerList = containerList;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_containerList != null)
{
_containerList.Dispose();
}
}
_containerList = null;
_surface = null;
}
public bool Merge(IMemento otherMemento)
{
return false;
}
public IMemento Restore()
{
// Store the selected state, as it's overwritten by the RemoveElement
bool selected = _containerList.Selected;
var oldState = new DeleteElementsMemento(_surface, _containerList);
_surface.RemoveElements(_containerList, false);
// After, so everything is gone
_surface.Invalidate();
return oldState;
}
}
}

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,47 +18,54 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System;
using Greenshot.Plugin.Drawing;
using Greenshot.Drawing.Fields;
using Greenshot.Configuration;
namespace Greenshot.Memento { using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Interfaces.Drawing;
namespace Greenshot.Memento
{
/// <summary> /// <summary>
/// The ChangeFieldHolderMemento makes it possible to undo-redo an IDrawableContainer move /// The ChangeFieldHolderMemento makes it possible to undo-redo an IDrawableContainer move
/// </summary> /// </summary>
public class ChangeFieldHolderMemento : IMemento { public class ChangeFieldHolderMemento : IMemento
private IDrawableContainer drawableContainer; {
private readonly Field fieldToBeChanged; private IDrawableContainer _drawableContainer;
private readonly object oldValue; private IField _fieldToBeChanged;
private object _oldValue;
public ChangeFieldHolderMemento(IDrawableContainer drawableContainer, Field fieldToBeChanged) { public ChangeFieldHolderMemento(IDrawableContainer drawableContainer, IField fieldToBeChanged)
this.drawableContainer = drawableContainer; {
this.fieldToBeChanged = fieldToBeChanged; _drawableContainer = drawableContainer;
oldValue = fieldToBeChanged.Value; _fieldToBeChanged = fieldToBeChanged;
_oldValue = fieldToBeChanged.Value;
} }
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this);
} }
protected virtual void Dispose(bool disposing) { protected virtual void Dispose(bool disposing)
//if (disposing) { } {
drawableContainer = null; if (disposing)
{
if (_drawableContainer != null)
{
_drawableContainer.Dispose();
}
}
_drawableContainer = null;
} }
public LangKey ActionLanguageKey { public bool Merge(IMemento otherMemento)
get { {
return LangKey.none;
}
}
public bool Merge(IMemento otherMemento) {
ChangeFieldHolderMemento other = otherMemento as ChangeFieldHolderMemento; ChangeFieldHolderMemento other = otherMemento as ChangeFieldHolderMemento;
if (other != null) { if (other != null)
if (other.drawableContainer.Equals(drawableContainer)) { {
if (other.fieldToBeChanged.Equals(fieldToBeChanged)) { if (other._drawableContainer.Equals(_drawableContainer))
{
if (other._fieldToBeChanged.Equals(_fieldToBeChanged))
{
// Match, do not store anything as the initial state is what we want. // Match, do not store anything as the initial state is what we want.
return true; return true;
} }
@ -67,13 +74,14 @@ namespace Greenshot.Memento {
return false; return false;
} }
public IMemento Restore() { public IMemento Restore()
{
// Before // Before
drawableContainer.Invalidate(); _drawableContainer.Invalidate();
ChangeFieldHolderMemento oldState = new ChangeFieldHolderMemento(drawableContainer, fieldToBeChanged); ChangeFieldHolderMemento oldState = new ChangeFieldHolderMemento(_drawableContainer, _fieldToBeChanged);
fieldToBeChanged.Value = oldValue; _fieldToBeChanged.Value = _oldValue;
// After // After
drawableContainer.Invalidate(); _drawableContainer.Invalidate();
return oldState; return oldState;
} }
} }

View file

@ -50,13 +50,6 @@ namespace Greenshot.Memento {
} }
} }
public LangKey ActionLanguageKey {
get {
//return LangKey.editor_deleteelement;
return LangKey.none;
}
}
public bool Merge(IMemento otherMemento) { public bool Merge(IMemento otherMemento) {
return false; return false;
} }

View file

@ -0,0 +1,72 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using Greenshot.Drawing;
using Greenshot.Plugin.Drawing;
namespace Greenshot.Memento
{
/// <summary>
/// The DeleteElementMemento makes it possible to undo deleting an element
/// </summary>
public class DeleteElementsMemento : IMemento
{
private IDrawableContainerList _containerList;
private Surface _surface;
public DeleteElementsMemento(Surface surface, IDrawableContainerList containerList)
{
_surface = surface;
_containerList = containerList;
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_containerList != null)
{
_containerList.Dispose();
}
}
_containerList = null;
_surface = null;
}
public bool Merge(IMemento otherMemento)
{
return false;
}
public IMemento Restore()
{
AddElementsMemento oldState = new AddElementsMemento(_surface, _containerList);
_surface.AddElements(_containerList, false);
// After
_surface.Invalidate();
return oldState;
}
}
}

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,61 +18,70 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using System; using Greenshot.Drawing;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Core;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using Greenshot.Configuration; namespace Greenshot.Memento
using Greenshot.Plugin.Drawing; {
using GreenshotPlugin.Core;
namespace Greenshot.Memento {
/// <summary> /// <summary>
/// The DrawableContainerBoundsChangeMemento makes it possible to undo-redo an IDrawableContainer resize & move /// The DrawableContainerBoundsChangeMemento makes it possible to undo-redo an IDrawableContainer resize & move
/// </summary> /// </summary>
public class DrawableContainerBoundsChangeMemento : IMemento { public class DrawableContainerBoundsChangeMemento : IMemento
readonly List<Point> points = new List<Point>(); {
readonly List<Size> sizes = new List<Size>(); List<Point> points = new List<Point>();
List<IDrawableContainer> listOfdrawableContainer; List<Size> sizes = new List<Size>();
IDrawableContainerList listOfdrawableContainer;
private void StoreBounds() { private void StoreBounds()
foreach(IDrawableContainer drawableContainer in listOfdrawableContainer) { {
foreach (IDrawableContainer drawableContainer in listOfdrawableContainer)
{
points.Add(drawableContainer.Location); points.Add(drawableContainer.Location);
sizes.Add(drawableContainer.Size); sizes.Add(drawableContainer.Size);
} }
} }
public DrawableContainerBoundsChangeMemento(List<IDrawableContainer> listOfdrawableContainer) { public DrawableContainerBoundsChangeMemento(IDrawableContainerList listOfdrawableContainer)
{
this.listOfdrawableContainer = listOfdrawableContainer; this.listOfdrawableContainer = listOfdrawableContainer;
StoreBounds(); StoreBounds();
} }
public DrawableContainerBoundsChangeMemento(IDrawableContainer drawableContainer) { public DrawableContainerBoundsChangeMemento(IDrawableContainer drawableContainer)
listOfdrawableContainer = new List<IDrawableContainer>(); {
listOfdrawableContainer = new DrawableContainerList();
listOfdrawableContainer.Add(drawableContainer); listOfdrawableContainer.Add(drawableContainer);
listOfdrawableContainer.Parent = drawableContainer.Parent;
StoreBounds(); StoreBounds();
} }
public void Dispose() { public void Dispose()
{
Dispose(true); Dispose(true);
GC.SuppressFinalize(this);
} }
protected virtual void Dispose(bool disposing) { protected virtual void Dispose(bool disposing)
// if (disposing) { } {
if (disposing)
{
if (listOfdrawableContainer != null)
{
listOfdrawableContainer.Dispose();
}
}
listOfdrawableContainer = null; listOfdrawableContainer = null;
} }
public LangKey ActionLanguageKey { public bool Merge(IMemento otherMemento)
get { {
return LangKey.none; var other = otherMemento as DrawableContainerBoundsChangeMemento;
} if (other != null)
} {
if (Objects.CompareLists<IDrawableContainer>(listOfdrawableContainer, other.listOfdrawableContainer))
public bool Merge(IMemento otherMemento) { {
DrawableContainerBoundsChangeMemento other = otherMemento as DrawableContainerBoundsChangeMemento;
if (other != null) {
if (Objects.CompareLists<IDrawableContainer>(listOfdrawableContainer, other.listOfdrawableContainer)) {
// Lists are equal, as we have the state already we can ignore the new memento // Lists are equal, as we have the state already we can ignore the new memento
return true; return true;
} }
@ -80,9 +89,11 @@ namespace Greenshot.Memento {
return false; return false;
} }
public IMemento Restore() { public IMemento Restore()
DrawableContainerBoundsChangeMemento 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 // Before
drawableContainer.Invalidate(); drawableContainer.Invalidate();

View file

@ -44,7 +44,6 @@ namespace Greenshot.Memento {
public void Dispose() { public void Dispose() {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this);
} }
protected virtual void Dispose(bool disposing) { protected virtual void Dispose(bool disposing) {
@ -65,13 +64,6 @@ namespace Greenshot.Memento {
return false; return false;
} }
public LangKey ActionLanguageKey {
get {
//return LangKey.editor_crop;
return LangKey.none;
}
}
public IMemento Restore() { public IMemento Restore() {
SurfaceBackgroundChangeMemento oldState = new SurfaceBackgroundChangeMemento(_surface, _matrix); SurfaceBackgroundChangeMemento oldState = new SurfaceBackgroundChangeMemento(_surface, _matrix);
_surface.UndoBackgroundChange(_image, _matrix); _surface.UndoBackgroundChange(_image, _matrix);

View file

@ -37,7 +37,6 @@ namespace Greenshot.Memento {
public void Dispose() { public void Dispose() {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this);
} }
protected virtual void Dispose(bool disposing) { protected virtual void Dispose(bool disposing) {
@ -46,12 +45,6 @@ namespace Greenshot.Memento {
} }
} }
public LangKey ActionLanguageKey {
get {
return LangKey.none;
}
}
public bool Merge(IMemento otherMemento) { public bool Merge(IMemento otherMemento) {
TextChangeMemento other = otherMemento as TextChangeMemento; TextChangeMemento other = otherMemento as TextChangeMemento;
if (other != null) { if (other != null) {

View file

@ -55,7 +55,7 @@ namespace GreenshotPlugin.Core
/// <returns>true if we are running on Windows 8 or later</returns> /// <returns>true if we are running on Windows 8 or later</returns>
public static bool IsWindows8OrLater(this OperatingSystem operatingSystem) public static bool IsWindows8OrLater(this OperatingSystem operatingSystem)
{ {
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2) || operatingSystem.Version.Major >= 6; return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 2) || operatingSystem.Version.Major > 6;
} }
/// <summary> /// <summary>
@ -65,7 +65,7 @@ namespace GreenshotPlugin.Core
/// <returns>true if we are running on Windows 7 or later</returns> /// <returns>true if we are running on Windows 7 or later</returns>
public static bool IsWindows7OrLater(this OperatingSystem operatingSystem) public static bool IsWindows7OrLater(this OperatingSystem operatingSystem)
{ {
return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 1) || operatingSystem.Version.Major >= 6; return (operatingSystem.Version.Major == 6 && operatingSystem.Version.Minor >= 1) || operatingSystem.Version.Major > 6;
} }
/// <summary> /// <summary>

View file

@ -1017,7 +1017,11 @@ namespace GreenshotPlugin.Core {
// and subtracting the border from the size (2 times, as we move right/down for the capture without resizing) // and subtracting the border from the size (2 times, as we move right/down for the capture without resizing)
captureRectangle.Inflate(borderSize.Width, borderSize.Height); captureRectangle.Inflate(borderSize.Width, borderSize.Height);
} else { } else {
// TODO: Also 8.x?
if (Environment.OSVersion.IsWindows10())
{
captureRectangle.Inflate(-1, -1); captureRectangle.Inflate(-1, -1);
}
if (autoMode) { if (autoMode) {
// check if the capture fits // check if the capture fits

View file

@ -68,6 +68,9 @@
<Compile Include="IEInterop\IHTMLWindow4.cs" /> <Compile Include="IEInterop\IHTMLWindow4.cs" />
<Compile Include="IEInterop\IWebBrowser2.cs" /> <Compile Include="IEInterop\IWebBrowser2.cs" />
<Compile Include="Interfaces\Drawing\Adorners\IAdorner.cs" /> <Compile Include="Interfaces\Drawing\Adorners\IAdorner.cs" />
<Compile Include="Interfaces\Drawing\IField.cs" />
<Compile Include="Interfaces\Drawing\IFieldHolder.cs" />
<Compile Include="Interfaces\Drawing\IMemento.cs" />
<Compile Include="Interop\Base.cs" /> <Compile Include="Interop\Base.cs" />
<Compile Include="Interop\ComProgIdAttribute.cs" /> <Compile Include="Interop\ComProgIdAttribute.cs" />
<Compile Include="Interop\COMWrapper.cs" /> <Compile Include="Interop\COMWrapper.cs" />

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -25,65 +25,80 @@ using System.Drawing.Imaging;
using System.Windows.Forms; using System.Windows.Forms;
using System.ComponentModel; using System.ComponentModel;
using System.Collections.Generic; using System.Collections.Generic;
using GreenshotPlugin.Interfaces.Drawing;
using Greenshot.Plugin.Drawing.Adorners; using Greenshot.Plugin.Drawing.Adorners;
using System.Runtime.Serialization;
namespace Greenshot.Plugin.Drawing { namespace Greenshot.Plugin.Drawing
public enum RenderMode {EDIT, EXPORT}; {
public enum EditStatus {UNDRAWN, DRAWING, MOVING, RESIZING, IDLE}; public enum RenderMode { EDIT, EXPORT };
public enum EditStatus { UNDRAWN, DRAWING, MOVING, RESIZING, IDLE };
public interface IDrawableContainer : INotifyPropertyChanged, IDisposable { public interface IDrawableContainer : INotifyPropertyChanged, IDisposable
ISurface Parent { {
ISurface Parent
{
get; get;
set;
} }
bool Selected { bool Selected
{
get; get;
set; set;
} }
int Left { int Left
{
get; get;
set; set;
} }
int Top { int Top
{
get; get;
set; set;
} }
int Width { int Width
{
get; get;
set; set;
} }
int Height { int Height
{
get; get;
set; set;
} }
Point Location { Point Location
{
get; get;
} }
Size Size { Size Size
{
get; get;
} }
Rectangle Bounds { Rectangle Bounds
{
get; get;
} }
Rectangle DrawingBounds { Rectangle DrawingBounds
{
get; get;
} }
void ApplyBounds(RectangleF newBounds); void ApplyBounds(RectangleF newBounds);
bool hasFilters { bool hasFilters
{
get; get;
} }
EditStatus Status { EditStatus Status
{
get; get;
set; set;
} }
@ -97,7 +112,8 @@ namespace Greenshot.Plugin.Drawing {
bool HandleMouseMove(int x, int y); bool HandleMouseMove(int x, int y);
bool InitContent(); bool InitContent();
void MakeBoundsChangeUndoable(bool allowMerge); void MakeBoundsChangeUndoable(bool allowMerge);
EditStatus DefaultEditMode { EditStatus DefaultEditMode
{
get; get;
} }
@ -107,38 +123,91 @@ namespace Greenshot.Plugin.Drawing {
IList<IAdorner> Adorners { get; } IList<IAdorner> Adorners { get; }
} }
public interface ITextContainer: IDrawableContainer { public interface IDrawableContainerList : IList<IDrawableContainer>, IDisposable
string Text { {
Guid ParentID
{
get;
}
bool Selected
{
get;
set;
}
ISurface Parent
{
get;
set;
}
EditStatus Status
{
get;
set;
}
void MakeBoundsChangeUndoable(bool allowMerge);
void Transform(Matrix matrix);
void MoveBy(int dx, int dy);
bool ClickableAt(int x, int y);
IDrawableContainer ClickableElementAt(int x, int y);
void OnDoubleClick();
bool HasIntersectingFilters(Rectangle clipRectangle);
bool IntersectsWith(Rectangle clipRectangle);
void Draw(Graphics g, Bitmap bitmap, RenderMode renderMode, Rectangle clipRectangle);
void Invalidate();
void PullElementsToTop(IDrawableContainerList elements);
bool CanPushDown(IDrawableContainerList elements);
void PullElementsUp(IDrawableContainerList elements);
bool CanPullUp(IDrawableContainerList elements);
void PushElementsDown(IDrawableContainerList elements);
void PushElementsToBottom(IDrawableContainerList elements);
void ShowContextMenu(MouseEventArgs e, ISurface surface);
void HandleFieldChangedEvent(object sender, FieldChangedEventArgs e);
}
public interface ITextContainer : IDrawableContainer
{
string Text
{
get; get;
set; set;
} }
void FitToText(); void FitToText();
} }
public interface IImageContainer: IDrawableContainer { public interface IImageContainer : IDrawableContainer
Image Image { {
Image Image
{
get; get;
set; set;
} }
void Load(string filename); void Load(string filename);
} }
public interface ICursorContainer: IDrawableContainer { public interface ICursorContainer : IDrawableContainer
Cursor Cursor { {
Cursor Cursor
{
get; get;
set; set;
} }
void Load(string filename); void Load(string filename);
} }
public interface IIconContainer: IDrawableContainer { public interface IIconContainer : IDrawableContainer
Icon Icon { {
Icon Icon
{
get; get;
set; set;
} }
void Load(string filename); void Load(string filename);
} }
public interface IMetafileContainer: IDrawableContainer { public interface IMetafileContainer : IDrawableContainer
Metafile Metafile { {
Metafile Metafile
{
get; get;
set; set;
} }

View file

@ -0,0 +1,84 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.ComponentModel;
namespace GreenshotPlugin.Interfaces.Drawing
{
[Flags]
public enum FieldFlag
{
NONE = 0,
CONFIRMABLE = 1
}
public interface IFieldType
{
string Name
{
get;
set;
}
}
public interface IField : INotifyPropertyChanged
{
object Value
{
get;
set;
}
IFieldType FieldType
{
get;
set;
}
string Scope
{
get;
set;
}
bool HasValue
{
get;
}
}
/// <summary>
/// EventHandler to be used when a field value changes
/// </summary>
public delegate void FieldChangedEventHandler(object sender, FieldChangedEventArgs e);
/// <summary>
/// EventArgs to be used with FieldChangedEventHandler
/// </summary>
public class FieldChangedEventArgs : EventArgs
{
public IField Field
{
get;
private set;
}
public FieldChangedEventArgs(IField field)
{
Field = field;
}
}
}

View file

@ -0,0 +1,56 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System.Collections.Generic;
namespace GreenshotPlugin.Interfaces.Drawing
{
/// <summary>
/// Any element holding Fields must provide access to it.
/// AbstractFieldHolder is the basic implementation.
/// If you need the fieldHolder to have child fieldHolders,
/// you should consider using IFieldHolderWithChildren.
/// </summary>
public interface IFieldHolder
{
event FieldChangedEventHandler FieldChanged;
void AddField(IField field);
void RemoveField(IField field);
IList<IField> GetFields();
IField GetField(IFieldType fieldType);
bool HasField(IFieldType fieldType);
void SetFieldValue(IFieldType fieldType, object value);
}
/// <summary>
/// Extended fieldHolder which has fieldHolder children.
/// Implementations should pass field values to and from
/// their children.
/// AbstractFieldHolderWithChildren is the basic implementation.
/// </summary>
public interface IFieldHolderWithChildren : IFieldHolder
{
void AddChild(IFieldHolder fieldHolder);
void RemoveChild(IFieldHolder fieldHolder);
}
}

View file

@ -0,0 +1,43 @@
/*
* Greenshot - a free and open source screenshot tool
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
*
* For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
namespace Greenshot.Memento {
/// <summary>
/// Description of IMemento.
/// </summary>
public interface IMemento : IDisposable {
/// <summary>
/// Restores target to the state memorized by this memento.
/// </summary>
/// <returns>
/// A memento of the state before restoring
/// </returns>
IMemento Restore();
/// <summary>
/// Try to merge the current memento with another, preventing loads of items on the stack
/// </summary>
/// <param name="other">The memento to try to merge with</param>
/// <returns></returns>
bool Merge(IMemento other);
}
}

View file

@ -3,7 +3,7 @@
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom * Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
* *
* For more information see: http://getgreenshot.org/ * For more information see: http://getgreenshot.org/
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -18,53 +18,63 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
using Greenshot.Core;
using Greenshot.Memento;
using Greenshot.Plugin.Drawing;
using GreenshotPlugin.Interfaces.Drawing;
using System; using System;
using System.Drawing; using System.Drawing;
using System.IO;
using System.Windows.Forms; using System.Windows.Forms;
using Greenshot.Plugin.Drawing; namespace Greenshot.Plugin
using System.IO; {
using System.Collections.Generic;
using Greenshot.Core;
namespace Greenshot.Plugin {
/// <summary> /// <summary>
/// Alignment Enums for possitioning /// Alignment Enums for possitioning
/// </summary> /// </summary>
//public enum HorizontalAlignment {LEFT, CENTER, RIGHT}; //public enum HorizontalAlignment {LEFT, CENTER, RIGHT};
public enum VerticalAlignment {TOP, CENTER, BOTTOM}; public enum VerticalAlignment { TOP, CENTER, BOTTOM };
public enum SurfaceMessageTyp { public enum SurfaceMessageTyp
{
FileSaved, FileSaved,
Error, Error,
Info, Info,
UploadedUri UploadedUri
} }
public class SurfaceMessageEventArgs : EventArgs { public class SurfaceMessageEventArgs : EventArgs
public SurfaceMessageTyp MessageType { {
public SurfaceMessageTyp MessageType
{
get; get;
set; set;
} }
public string Message { public string Message
{
get; get;
set; set;
} }
public ISurface Surface { public ISurface Surface
{
get; get;
set; set;
} }
} }
public class SurfaceElementEventArgs : EventArgs { public class SurfaceElementEventArgs : EventArgs
public IList<IDrawableContainer> Elements { {
public IDrawableContainerList Elements
{
get; get;
set; set;
} }
} }
public class SurfaceDrawingModeEventArgs : EventArgs { public class SurfaceDrawingModeEventArgs : EventArgs
public DrawingModes DrawingMode { {
public DrawingModes DrawingMode
{
get; get;
set; set;
} }
@ -74,7 +84,8 @@ namespace Greenshot.Plugin {
public delegate void SurfaceMessageEventHandler(object sender, SurfaceMessageEventArgs e); public delegate void SurfaceMessageEventHandler(object sender, SurfaceMessageEventArgs e);
public delegate void SurfaceElementEventHandler(object sender, SurfaceElementEventArgs e); public delegate void SurfaceElementEventHandler(object sender, SurfaceElementEventArgs e);
public delegate void SurfaceDrawingModeEventHandler(object sender, SurfaceDrawingModeEventArgs e); public delegate void SurfaceDrawingModeEventHandler(object sender, SurfaceDrawingModeEventArgs e);
public enum DrawingModes { public enum DrawingModes
{
None, None,
Rect, Rect,
Ellipse, Ellipse,
@ -93,7 +104,8 @@ namespace Greenshot.Plugin {
/// <summary> /// <summary>
/// The interface to the Surface object, so Plugins can use it. /// The interface to the Surface object, so Plugins can use it.
/// </summary> /// </summary>
public interface ISurface : IDisposable { public interface ISurface : IDisposable
{
event SurfaceSizeChangeEventHandler SurfaceSizeChanged; event SurfaceSizeChangeEventHandler SurfaceSizeChanged;
event SurfaceMessageEventHandler SurfaceMessage; event SurfaceMessageEventHandler SurfaceMessage;
event SurfaceDrawingModeEventHandler DrawingModeChanged; event SurfaceDrawingModeEventHandler DrawingModeChanged;
@ -102,11 +114,17 @@ namespace Greenshot.Plugin {
/// <summary> /// <summary>
/// Unique ID of the Surface /// Unique ID of the Surface
/// </summary> /// </summary>
Guid ID { Guid ID
{
get; get;
set; set;
} }
IDrawableContainerList Elements
{
get;
}
/// <summary> /// <summary>
/// Get/Set the image to the Surface /// Get/Set the image to the Surface
/// get will give the image as is currently visible /// get will give the image as is currently visible
@ -116,7 +134,8 @@ namespace Greenshot.Plugin {
/// The setter will clone the passed bitmap and dispose it when the Surface is disposed /// The setter will clone the passed bitmap and dispose it when the Surface is disposed
/// This means that the supplied image needs to be disposed by the calling code (if needed!) /// This means that the supplied image needs to be disposed by the calling code (if needed!)
/// </summary> /// </summary>
Image Image { Image Image
{
get; get;
set; set;
} }
@ -154,7 +173,8 @@ namespace Greenshot.Plugin {
long SaveElementsToStream(Stream stream); long SaveElementsToStream(Stream stream);
void LoadElementsFromStream(Stream stream); void LoadElementsFromStream(Stream stream);
bool HasSelectedElements { bool HasSelectedElements
{
get; get;
} }
void RemoveSelectedElements(); void RemoveSelectedElements();
@ -162,9 +182,32 @@ namespace Greenshot.Plugin {
void CopySelectedElements(); void CopySelectedElements();
void PasteElementFromClipboard(); void PasteElementFromClipboard();
void DuplicateSelectedElements(); void DuplicateSelectedElements();
void DeselectElement(IDrawableContainer container); void DeselectElement(IDrawableContainer container, bool generateEvents = true);
void DeselectAllElements(); void DeselectAllElements();
void SelectElement(IDrawableContainer container);
/// <summary>
/// Add an element to the surface
/// </summary>
/// <param name="elements">IDrawableContainerList</param>
/// <param name="makeUndoable">Should it be placed on the undo stack?</param>
void AddElements(IDrawableContainerList elements, bool makeUndoable = true);
void RemoveElements(IDrawableContainerList elements, bool makeUndoable = true);
void SelectElements(IDrawableContainerList elements);
/// <summary>
/// Add an element to the surface
/// </summary>
/// <param name="element">IDrawableContainer</param>
/// <param name="makeUndoable">Should it be placed on the undo stack?</param>
/// <param name="invalidate">Should it be invalidated (draw)</param>
void AddElement(IDrawableContainer element, bool makeUndoable = true, bool invalidate = true);
/// <summary>
/// Select the supplied container
/// </summary>
/// <param name="container">IDrawableContainer</param>
/// <param name="invalidate">false to skip invalidation</param>
void SelectElement(IDrawableContainer container, bool invalidate = true, bool generateEvents = true);
/// <summary> /// <summary>
/// Is the supplied container "on" the surface? /// Is the supplied container "on" the surface?
/// </summary> /// </summary>
@ -173,31 +216,46 @@ namespace Greenshot.Plugin {
bool IsOnSurface(IDrawableContainer container); bool IsOnSurface(IDrawableContainer container);
void Invalidate(Rectangle rectangleToInvalidate); void Invalidate(Rectangle rectangleToInvalidate);
void Invalidate(); void Invalidate();
bool Modified { bool Modified
{
get; get;
set; set;
} }
string LastSaveFullPath { string LastSaveFullPath
{
get; get;
set; set;
} }
string UploadURL { string UploadURL
{
get; get;
set; set;
} }
void RemoveElement(IDrawableContainer elementToRemove, bool makeUndoable); /// <summary>
/// Remove an element of the elements list
/// </summary>
/// <param name="elementToRemove">Element to remove</param>
/// <param name="makeUndoable">flag specifying if the remove needs to be undoable</param>
/// <param name="invalidate">flag specifying if an surface invalidate needs to be called</param>
/// <param name="generateEvents">flag specifying if the deselect needs to generate an event</param>
void RemoveElement(IDrawableContainer elementToRemove, bool makeUndoable = true, bool invalidate = true, bool generateEvents = true);
void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message); void SendMessageEvent(object source, SurfaceMessageTyp messageType, string message);
void ApplyBitmapEffect(IEffect effect); void ApplyBitmapEffect(IEffect effect);
void RemoveCursor(); void RemoveCursor();
bool HasCursor { bool HasCursor
{
get; get;
} }
ICaptureDetails CaptureDetails { ICaptureDetails CaptureDetails
{
get; get;
set; set;
} }
int Width { get; } int Width { get; }
int Height { get; } int Height { get; }
void MakeUndoable(IMemento memento, bool allowMerge);
} }
} }