diff --git a/Greenshot/Configuration/EditorConfiguration.cs b/Greenshot/Configuration/EditorConfiguration.cs index 956927be9..2d1aa37e6 100644 --- a/Greenshot/Configuration/EditorConfiguration.cs +++ b/Greenshot/Configuration/EditorConfiguration.cs @@ -50,6 +50,8 @@ namespace Greenshot.Configuration { public Point WindowMaxPosition; [IniProperty("WindowNormalPosition", Description="Position of normal window", DefaultValue="100,100,400,400")] public Rectangle WindowNormalPosition; + [IniProperty("ReuseEditor", Description = "Reuse already open editor", DefaultValue = "false")] + public bool ReuseEditor; [IniProperty("SuppressSaveDialogAtClose", Description="Suppressed the 'do you want to save' dialog when closing the editor.", DefaultValue="False")] public bool SuppressSaveDialogAtClose; diff --git a/Greenshot/Destinations/EditorDestination.cs b/Greenshot/Destinations/EditorDestination.cs index a2174b5b4..fbfaab185 100644 --- a/Greenshot/Destinations/EditorDestination.cs +++ b/Greenshot/Destinations/EditorDestination.cs @@ -38,7 +38,7 @@ namespace Greenshot.Destinations { /// public class EditorDestination : AbstractDestination { private static log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(EditorDestination)); - private static CoreConfiguration conf = IniConfig.GetIniSection(); + private static EditorConfiguration editorConfiguration = IniConfig.GetIniSection(); public const string DESIGNATION = "Editor"; private IImageEditor editor = null; private static Image greenshotIcon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon().ToBitmap(); @@ -92,35 +92,46 @@ namespace Greenshot.Destinations { public override ExportInformation ExportCapture(bool manuallyInitiated, ISurface surface, ICaptureDetails captureDetails) { ExportInformation exportInformation = new ExportInformation(this.Designation, this.Description); + // Make sure we collect the garbage before opening the screenshot + GC.Collect(); + GC.WaitForPendingFinalizers(); + if (editor == null) { - // Make sure we collect the garbage before opening the screenshot - GC.Collect(); - GC.WaitForPendingFinalizers(); - - try { - ImageEditorForm editorForm = new ImageEditorForm(surface, !surface.Modified); // Output made?? - - if (!string.IsNullOrEmpty(captureDetails.Filename)) { - editorForm.SetImagePath(captureDetails.Filename); + if (editorConfiguration.ReuseEditor) { + foreach(IImageEditor openedEditor in ImageEditorForm.Editors) { + if (!openedEditor.Surface.Modified) { + openedEditor.Surface = surface; + exportInformation.ExportMade = true; + break; + } + } + } + if (!exportInformation.ExportMade) { + try { + ImageEditorForm editorForm = new ImageEditorForm(surface, !surface.Modified); // Output made?? + + if (!string.IsNullOrEmpty(captureDetails.Filename)) { + editorForm.SetImagePath(captureDetails.Filename); + } + editorForm.Show(); + editorForm.Activate(); + LOG.Debug("Finished opening Editor"); + exportInformation.ExportMade = true; + } catch (Exception e) { + LOG.Error(e); + exportInformation.ErrorMessage = e.Message; + } + } + } else { + try { + using (Bitmap image = (Bitmap)surface.GetImageForExport()) { + editor.Surface.AddBitmapContainer(image, 10, 10); } - editorForm.Show(); - editorForm.Activate(); - LOG.Debug("Finished opening Editor"); exportInformation.ExportMade = true; } catch (Exception e) { LOG.Error(e); exportInformation.ErrorMessage = e.Message; } - } else { - try { - using (Bitmap image = (Bitmap)surface.GetImageForExport()) { - editor.Surface.AddBitmapContainer(image, 10, 10); - } - exportInformation.ExportMade = true; - } catch (Exception e) { - LOG.Error(e); - exportInformation.ErrorMessage = e.Message; - } } ProcessExport(exportInformation, surface); return exportInformation; diff --git a/Greenshot/Drawing/DrawableContainer.cs b/Greenshot/Drawing/DrawableContainer.cs index d86d527f5..b2bc375ba 100644 --- a/Greenshot/Drawing/DrawableContainer.cs +++ b/Greenshot/Drawing/DrawableContainer.cs @@ -24,12 +24,10 @@ using System.ComponentModel; using System.Drawing; using System.Windows.Forms; -using Greenshot.Configuration; using Greenshot.Drawing.Fields; using Greenshot.Drawing.Filters; using Greenshot.Helpers; using Greenshot.Plugin; -using GreenshotPlugin.Core; using Greenshot.Plugin.Drawing; using Greenshot.Memento; using System.Drawing.Drawing2D; @@ -87,7 +85,16 @@ namespace Greenshot.Drawing { } [NonSerialized] - public EditStatus Status = EditStatus.UNDRAWN; + private EditStatus status = EditStatus.UNDRAWN; + public EditStatus Status { + get { + return status; + } + set { + status = value; + } + } + private int left = 0; public int Left { diff --git a/Greenshot/Drawing/DrawableContainerList.cs b/Greenshot/Drawing/DrawableContainerList.cs index e3e03876f..d1fca4fe5 100644 --- a/Greenshot/Drawing/DrawableContainerList.cs +++ b/Greenshot/Drawing/DrawableContainerList.cs @@ -35,8 +35,8 @@ namespace Greenshot.Drawing { /// /// Dispatches most of a DrawableContainer's public properties and methods to a list of DrawableContainers. /// - [Serializable()] - public class DrawableContainerList : List { + [Serializable()] + public class DrawableContainerList : List { private static CoreConfiguration conf = IniConfig.GetIniSection(); private static System.ComponentModel.ComponentResourceManager editorFormResources = new System.ComponentModel.ComponentResourceManager(typeof(ImageEditorForm)); @@ -48,7 +48,9 @@ namespace Greenshot.Drawing { return this[Count-1].Status; } set { - foreach(DrawableContainer dc in this) dc.Status = value; + foreach (DrawableContainer dc in this) { + dc.Status = value; + } } } @@ -178,9 +180,9 @@ namespace Greenshot.Drawing { /// x coordinate to be checked /// y coordinate to be checked /// the topmost element from the list being clickable at the given location, null if there is no clickable element - public DrawableContainer ClickableElementAt(int x, int y) { - for(int i=Count-1; i>=0; i--) { - if(this[i].ClickableAt(x,y)) { + public IDrawableContainer ClickableElementAt(int x, int y) { + for (int i=Count-1; i>=0; i--) { + if (this[i].ClickableAt(x,y)) { return this[i]; } } @@ -280,7 +282,7 @@ namespace Greenshot.Drawing { /// list of elements to pull up public void PullElementsUp(DrawableContainerList elements) { for(int i=this.Count-1; i>=0; i--) { - DrawableContainer dc = this[i]; + IDrawableContainer dc = this[i]; if (elements.Contains(dc)) { if (Count > (i+1) && !elements.Contains(this[i+1])) { SwapElements(i,i+1); @@ -294,9 +296,9 @@ namespace Greenshot.Drawing { /// /// of elements to pull to top public void PullElementsToTop(DrawableContainerList elements) { - DrawableContainer[] dcs = this.ToArray(); + IDrawableContainer[] dcs = this.ToArray(); for(int i=0; ilist of elements to push down public void PushElementsDown(DrawableContainerList elements) { for(int i=0; i0) && !elements.Contains(this[i-1])) { SwapElements(i,i-1); @@ -343,9 +345,9 @@ namespace Greenshot.Drawing { /// /// of elements to push to bottom public void PushElementsToBottom(DrawableContainerList elements) { - DrawableContainer[] dcs = this.ToArray(); + IDrawableContainer[] dcs = this.ToArray(); for(int i=dcs.Length-1; i>=0; i--) { - DrawableContainer dc = dcs[i]; + IDrawableContainer dc = dcs[i]; if(elements.Contains(dc)) { this.Remove(dc); this.Insert(0, dc); @@ -362,7 +364,7 @@ namespace Greenshot.Drawing { /// index of the 2nd element private void SwapElements(int index1, int index2) { if(index1 >= 0 && index1 < Count && index2 >= 0 && index2 < Count && index1 != index2) { - DrawableContainer dc = this[index1]; + IDrawableContainer dc = this[index1]; this[index1] = this[index2]; this[index2] = dc; Parent.Modified = true; diff --git a/Greenshot/Drawing/Fields/FieldAggregator.cs b/Greenshot/Drawing/Fields/FieldAggregator.cs index c5b954b2b..05d82ef42 100644 --- a/Greenshot/Drawing/Fields/FieldAggregator.cs +++ b/Greenshot/Drawing/Fields/FieldAggregator.cs @@ -24,6 +24,7 @@ using System.ComponentModel; using Greenshot.Configuration; using Greenshot.IniFile; +using Greenshot.Plugin.Drawing; namespace Greenshot.Drawing.Fields { /// @@ -39,7 +40,7 @@ namespace Greenshot.Drawing.Fields { /// public class FieldAggregator : AbstractFieldHolder { - private List boundContainers; + private List boundContainers; private bool internalUpdateRunning = false; enum Status {IDLE, BINDING, UPDATING}; @@ -52,7 +53,7 @@ namespace Greenshot.Drawing.Fields { Field field = new Field(fieldType, GetType()); AddField(field); } - boundContainers = new List(); + boundContainers = new List(); } public override void AddField(Field field) { @@ -66,31 +67,38 @@ namespace Greenshot.Drawing.Fields { } } - public void BindElement(DrawableContainer dc) { - if (!boundContainers.Contains(dc)) { - boundContainers.Add(dc); - dc.ChildrenChanged += delegate { UpdateFromBoundElements(); }; + public void BindElement(IDrawableContainer dc) { + DrawableContainer container = dc as DrawableContainer; + if (container != null && !boundContainers.Contains(container)) { + boundContainers.Add(container); + container.ChildrenChanged += delegate { + UpdateFromBoundElements(); + }; UpdateFromBoundElements(); } } - public void BindAndUpdateElement(DrawableContainer dc) { + public void BindAndUpdateElement(IDrawableContainer dc) { UpdateElement(dc); BindElement(dc); } - public void UpdateElement(DrawableContainer dc) { + public void UpdateElement(IDrawableContainer dc) { + DrawableContainer container = dc as DrawableContainer; + if (container == null) { + return; + } internalUpdateRunning = true; foreach(Field field in GetFields()) { - if (dc.HasField(field.FieldType) && field.HasValue) { + if (container.HasField(field.FieldType) && field.HasValue) { //if(LOG.IsDebugEnabled) LOG.Debug(" "+field+ ": "+field.Value); - dc.SetFieldValue(field.FieldType, field.Value); + container.SetFieldValue(field.FieldType, field.Value); } } internalUpdateRunning = false; } - public void UnbindElement(DrawableContainer dc) { + public void UnbindElement(IDrawableContainer dc) { if (boundContainers.Contains(dc)) { boundContainers.Remove(dc); UpdateFromBoundElements(); @@ -129,28 +137,33 @@ namespace Greenshot.Drawing.Fields { } private List FindCommonFields() { - List ret = null; + List returnFields = null; if (boundContainers.Count > 0) { // take all fields from the least selected container... - ret = boundContainers[boundContainers.Count-1].GetFields(); - for(int i=0;i fieldsToRemove = new List(); - foreach(Field f in ret) { - // ... throw out those that do not apply to one of the other containers - if (!dc.HasField(f.FieldType)) { - fieldsToRemove.Add(f); + DrawableContainer leastSelectedContainer = boundContainers[boundContainers.Count - 1] as DrawableContainer; + if (leastSelectedContainer != null) { + returnFields = leastSelectedContainer.GetFields(); + for (int i = 0; i < boundContainers.Count - 1; i++) { + DrawableContainer dc = boundContainers[i] as DrawableContainer; + if (dc != null) { + List fieldsToRemove = new List(); + foreach (Field f in returnFields) { + // ... throw out those that do not apply to one of the other containers + if (!dc.HasField(f.FieldType)) { + fieldsToRemove.Add(f); + } + } + foreach (Field f in fieldsToRemove) { + returnFields.Remove(f); + } } } - foreach(Field f in fieldsToRemove) { - ret.Remove(f); - } } } - if (ret == null) { - ret = new List(); + if (returnFields == null) { + returnFields = new List(); } - return ret; + return returnFields; } public void OwnPropertyChanged(object sender, PropertyChangedEventArgs ea) { diff --git a/Greenshot/Drawing/Surface.cs b/Greenshot/Drawing/Surface.cs index 137c03ed5..6b2dfaf1e 100644 --- a/Greenshot/Drawing/Surface.cs +++ b/Greenshot/Drawing/Surface.cs @@ -39,10 +39,6 @@ using System.Drawing.Drawing2D; using GreenshotPlugin.Controls; namespace Greenshot.Drawing { - public delegate void SurfaceElementEventHandler(object source, DrawableContainerList element); - public delegate void SurfaceDrawingModeEventHandler(object source, DrawingModes drawingMode); - - public enum DrawingModes { None, Rect, Ellipse, Text, Line, Arrow, Crop, Highlight, Obfuscate, Bitmap, Path } /// /// Description of Surface. @@ -155,7 +151,7 @@ namespace Greenshot.Drawing { /// The selected element for the mouse down, do not serialize /// [NonSerialized] - private DrawableContainer mouseDownElement = null; + private IDrawableContainer mouseDownElement = null; /// /// all selected elements, do not serialize @@ -167,19 +163,19 @@ namespace Greenshot.Drawing { /// the element we are drawing with, do not serialize /// [NonSerialized] - private DrawableContainer drawingElement = null; + private IDrawableContainer drawingElement = null; /// /// the element we want to draw with (not yet drawn), do not serialize /// [NonSerialized] - private DrawableContainer undrawnElement = null; + private IDrawableContainer undrawnElement = null; /// /// the cropcontainer, when cropping this is set, do not serialize /// [NonSerialized] - private DrawableContainer cropContainer = null; + private IDrawableContainer cropContainer = null; /// /// the brush which is used for transparent backgrounds, set by the editor, do not serialize @@ -319,8 +315,12 @@ namespace Greenshot.Drawing { } public ICaptureDetails CaptureDetails { - get {return captureDetails;} - set {captureDetails = value;} + get { + return captureDetails; + } + set { + captureDetails = value; + } } public Surface() : base(){ @@ -338,6 +338,7 @@ namespace Greenshot.Drawing { this.elements.Parent = this; // Make sure we are visible this.Visible = true; + this.TabStop = false; // Enable double buffering this.DoubleBuffered = true; this.SetStyle(ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.ResizeRedraw | ControlStyles.ContainerControl | ControlStyles.OptimizedDoubleBuffer | ControlStyles.SupportsTransparentBackColor, true); @@ -447,6 +448,7 @@ namespace Greenshot.Drawing { } } } + public LangKey RedoActionKey { get { if (CanRedo) { @@ -932,7 +934,7 @@ namespace Greenshot.Drawing { selectedList = selectedElements; } else { // Single element - DrawableContainer rightClickedContainer = elements.ClickableElementAt(mouseStart.X, mouseStart.Y); + IDrawableContainer rightClickedContainer = elements.ClickableElementAt(mouseStart.X, mouseStart.Y); if (rightClickedContainer != null) { selectedList = new DrawableContainerList(); selectedList.Add(rightClickedContainer); @@ -996,7 +998,7 @@ namespace Greenshot.Drawing { mouseDownElement = null; if (DrawingMode == DrawingModes.None) { // check whether an existing element was clicked - DrawableContainer element = elements.ClickableElementAt(currentMouse.X, currentMouse.Y); + IDrawableContainer element = elements.ClickableElementAt(currentMouse.X, currentMouse.Y); bool shiftModifier = (Control.ModifierKeys & Keys.Shift) == Keys.Shift; if (element != null) { element.Invalidate(); @@ -1166,7 +1168,7 @@ namespace Greenshot.Drawing { /// Wrapper for makeUndoable flag which was introduced later, will call AddElement with makeundoable set to true /// /// the new element - public void AddElement(DrawableContainer element) { + public void AddElement(IDrawableContainer element) { AddElement(element, true); } @@ -1175,11 +1177,14 @@ namespace Greenshot.Drawing { /// /// the new element /// true if the adding should be undoable - public void AddElement(DrawableContainer element, bool makeUndoable) { + public void AddElement(IDrawableContainer element, bool makeUndoable) { elements.Add(element); - element.FieldChanged += element_FieldChanged; + DrawableContainer container = element as DrawableContainer; + if (container != null) { + container.FieldChanged += element_FieldChanged; + } element.PropertyChanged += ElementPropertyChanged; - if(element.Status == EditStatus.UNDRAWN) { + if (element.Status == EditStatus.UNDRAWN) { element.Status = EditStatus.IDLE; } element.Invalidate(); @@ -1190,21 +1195,23 @@ namespace Greenshot.Drawing { } public void RemoveElement(IDrawableContainer elementToRemove, bool makeUndoable) { + DeselectElement(elementToRemove); + elements.Remove(elementToRemove); DrawableContainer element = elementToRemove as DrawableContainer; - DeselectElement(element); - elements.Remove(element); - element.FieldChanged -= element_FieldChanged; - element.PropertyChanged -= ElementPropertyChanged; + if (element != null) { + element.FieldChanged -= element_FieldChanged; + } + elementToRemove.PropertyChanged -= ElementPropertyChanged; // Do not dispose, the memento should!! element.Dispose(); - element.Invalidate(); + elementToRemove.Invalidate(); if (makeUndoable) { - MakeUndoable(new DeleteElementMemento(this, element), false); + MakeUndoable(new DeleteElementMemento(this, elementToRemove), false); } modified = true; } public void AddElements(DrawableContainerList elementsToAdd) { - foreach(DrawableContainer element in elementsToAdd) { + foreach(IDrawableContainer element in elementsToAdd) { AddElement(element, true); } } @@ -1248,8 +1255,8 @@ namespace Greenshot.Drawing { public void ConfirmSelectedConfirmableElements(bool confirm){ // create new collection so that we can iterate safely (selectedElements might change due with confirm/cancel) - List selectedDCs = new List(selectedElements); - foreach(DrawableContainer dc in selectedDCs){ + List selectedDCs = new List(selectedElements); + foreach(IDrawableContainer dc in selectedDCs){ if(dc.Equals(cropContainer)){ DrawingMode = DrawingModes.None; // No undo memento for the cropcontainer itself, only for the effect @@ -1314,11 +1321,10 @@ namespace Greenshot.Drawing { } public void DeselectElement(IDrawableContainer container) { - DrawableContainer element = container as DrawableContainer; - element.HideGrippers(); - element.Selected = false; - selectedElements.Remove(element); - FieldAggregator.UnbindElement(element); + container.HideGrippers(); + container.Selected = false; + selectedElements.Remove(container); + FieldAggregator.UnbindElement(container); if (movingElementChanged != null) { movingElementChanged(this, selectedElements); } @@ -1327,7 +1333,7 @@ namespace Greenshot.Drawing { public void DeselectAllElements() { if (HasSelectedElements()) { while(selectedElements.Count > 0) { - DrawableContainer element = selectedElements[0]; + IDrawableContainer element = selectedElements[0]; element.Invalidate(); element.HideGrippers(); element.Selected = false; @@ -1341,16 +1347,15 @@ namespace Greenshot.Drawing { } public void SelectElement(IDrawableContainer container) { - DrawableContainer element = container as DrawableContainer; - if(!selectedElements.Contains(element)) { - selectedElements.Add(element); - element.ShowGrippers(); - element.Selected = true; - FieldAggregator.BindElement(element); + if (!selectedElements.Contains(container)) { + selectedElements.Add(container); + container.ShowGrippers(); + container.Selected = true; + FieldAggregator.BindElement(container); if (movingElementChanged != null) { movingElementChanged(this, selectedElements); } - element.Invalidate(); + container.Invalidate(); } } diff --git a/Greenshot/Forms/ImageEditorForm.cs b/Greenshot/Forms/ImageEditorForm.cs index d7749f07d..be99b0e55 100644 --- a/Greenshot/Forms/ImageEditorForm.cs +++ b/Greenshot/Forms/ImageEditorForm.cs @@ -40,6 +40,7 @@ using GreenshotPlugin.Core; using Greenshot.IniFile; using System.Threading; using System.Drawing.Imaging; +using Greenshot.Plugin.Drawing; namespace Greenshot { /// @@ -71,12 +72,6 @@ namespace Greenshot { get { return this; } } - public Surface EditorSurface { - get { - return surface; - } - } - public static List Editors { get { return editorList; @@ -84,19 +79,13 @@ namespace Greenshot { } public ImageEditorForm(ISurface iSurface, bool outputMade) { - // init surface - this.surface = iSurface as Surface; editorList.Add(this); - - // Intial "saved" flag for asking if the image needs to be save - surface.Modified = !outputMade; - + // // The InitializeComponent() call is required for Windows Forms designer support. // this.ManualLanguageApply = true; InitializeComponent(); - updateUI(); this.Load += delegate { new Thread(delegate() {AddDestinations();}).Start(); @@ -104,18 +93,58 @@ namespace Greenshot { IniConfig.IniChanged += new FileSystemEventHandler(ReloadConfiguration); + + // init surface + Surface = iSurface; + // Intial "saved" flag for asking if the image needs to be save + surface.Modified = !outputMade; + updateUI(); + // Make sure the editor is placed on the same location as the last editor was on close WindowDetails thisForm = new WindowDetails(this.Handle); thisForm.SetWindowPlacement(editorConfiguration.GetEditorPlacement()); - SurfaceSizeChanged(this.Surface); - - bindFieldControls(); - refreshEditorControls(); // Workaround: As the cursor is (mostly) selected on the surface a funny artifact is visible, this fixes it. hideToolstripItems(); } - + + private void RemoveSurface() { + if (surface != null) { + panel1.Controls.Remove(surface as Control); + this.surface.Dispose(); + this.surface = null; + } + } + + private void SetSurface(ISurface newSurface) { + if (this.Surface != null && this.Surface.Modified) { + throw new ApplicationException("Surface modified"); + } + + RemoveSurface(); + + this.surface = newSurface as Surface; + panel1.Controls.Add(surface as Surface); + Image backgroundForTransparency = GreenshotPlugin.Core.GreenshotResources.getImage("Checkerboard.Image"); + this.surface.TransparencyBackgroundBrush = new TextureBrush(backgroundForTransparency, WrapMode.Tile); + + surface.MovingElementChanged += delegate { + refreshEditorControls(); + }; + surface.DrawingModeChanged += new SurfaceDrawingModeEventHandler(surface_DrawingModeChanged); + surface.SurfaceSizeChanged += new SurfaceSizeChangeEventHandler(SurfaceSizeChanged); + surface.SurfaceMessage += new SurfaceMessageEventHandler(SurfaceMessageReceived); + surface.FieldAggregator.FieldChanged += new FieldChangedEventHandler(FieldAggregatorFieldChanged); + + SurfaceSizeChanged(this.Surface); + + bindFieldControls(); + refreshEditorControls(); + // Fix title + if (surface != null && surface.CaptureDetails != null && surface.CaptureDetails.Title != null) { + this.Text = surface.CaptureDetails.Title + " - " + Language.GetString(LangKey.editor_title); + } + } private void updateUI() { this.Icon = GreenshotPlugin.Core.GreenshotResources.getGreenshotIcon(); @@ -126,9 +155,6 @@ namespace Greenshot { toolStripSeparator11.Visible = !coreConf.DisableSettings; btnSettings.Visible = !coreConf.DisableSettings; - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ImageEditorForm)); - Image backgroundForTransparency = GreenshotPlugin.Core.GreenshotResources.getImage("Checkerboard.Image"); - surface.TransparencyBackgroundBrush = new TextureBrush(backgroundForTransparency, WrapMode.Tile); // Make sure Double-buffer is enabled SetStyle(ControlStyles.DoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true); @@ -136,22 +162,12 @@ namespace Greenshot { // to fix the bug (?) with the vscrollbar not being able to shrink to // a smaller size than the initial panel size (as set by the forms designer) panel1.Height = 10; - - surface.TabStop = false; - - surface.MovingElementChanged += delegate { refreshEditorControls(); }; - surface.DrawingModeChanged += new SurfaceDrawingModeEventHandler(surface_DrawingModeChanged); - surface.SurfaceSizeChanged += new SurfaceSizeChangeEventHandler(SurfaceSizeChanged); - surface.SurfaceMessage += new SurfaceMessageEventHandler(SurfaceMessageReceived); this.fontFamilyComboBox.PropertyChanged += new PropertyChangedEventHandler(FontPropertyChanged); - surface.FieldAggregator.FieldChanged += new FieldChangedEventHandler( FieldAggregatorFieldChanged ); obfuscateModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked; highlightModeButton.DropDownItemClicked += FilterPresetDropDownItemClicked; - panel1.Controls.Add(surface); - toolbarButtons = new GreenshotPlugin.Controls.GreenshotToolStripButton[] { btnCursor, btnRect, btnEllipse, btnText, btnLine, btnArrow, btnFreehand, btnHighlight, btnObfuscate, btnCrop }; //toolbarDropDownButtons = new ToolStripDropDownButton[]{btnBlur, btnPixeliate, btnTextHighlighter, btnAreaHighlighter, btnMagnifier}; @@ -161,11 +177,6 @@ namespace Greenshot { this.MouseWheel += new MouseEventHandler( PanelMouseWheel); ApplyLanguage(); - - // Fix title - if (surface != null && surface.CaptureDetails != null && surface.CaptureDetails.Title != null) { - this.Text = surface.CaptureDetails.Title + " - " + Language.GetString(LangKey.editor_title); - } } /// @@ -329,15 +340,20 @@ namespace Greenshot { // Even update language when needed ApplyLanguage(); - // Fix title - if (surface != null && surface.CaptureDetails != null && surface.CaptureDetails.Title != null) { - this.Text = surface.CaptureDetails.Title + " - " + Language.GetString(LangKey.editor_title); - } + // Fix title + if (surface != null && surface.CaptureDetails != null && surface.CaptureDetails.Title != null) { + this.Text = surface.CaptureDetails.Title + " - " + Language.GetString(LangKey.editor_title); + } }); } public ISurface Surface { - get {return surface;} + get { + return surface; + } + set { + SetSurface(value); + } } public void SetImagePath(string fullpath) { @@ -648,7 +664,7 @@ namespace Greenshot { updateClipboardSurfaceDependencies(); updateUndoRedoSurfaceDependencies(); } - + void ImageEditorFormFormClosing(object sender, FormClosingEventArgs e) { IniConfig.IniChanged -= new FileSystemEventHandler(ReloadConfiguration); if (surface.Modified && !editorConfiguration.SuppressSaveDialogAtClose) { diff --git a/Greenshot/Memento/AddElementMemento.cs b/Greenshot/Memento/AddElementMemento.cs index a480823ea..6fe178664 100644 --- a/Greenshot/Memento/AddElementMemento.cs +++ b/Greenshot/Memento/AddElementMemento.cs @@ -21,16 +21,17 @@ using System; using Greenshot.Configuration; using Greenshot.Drawing; +using Greenshot.Plugin.Drawing; namespace Greenshot.Memento { /// /// The AddElementMemento makes it possible to undo adding an element /// public class AddElementMemento : IMemento { - private DrawableContainer drawableContainer; + private IDrawableContainer drawableContainer; private Surface surface; - public AddElementMemento(Surface surface, DrawableContainer drawableContainer) { + public AddElementMemento(Surface surface, IDrawableContainer drawableContainer) { this.surface = surface; this.drawableContainer = drawableContainer; } diff --git a/Greenshot/Memento/DeleteElementMemento.cs b/Greenshot/Memento/DeleteElementMemento.cs index a8453803f..126fd0841 100644 --- a/Greenshot/Memento/DeleteElementMemento.cs +++ b/Greenshot/Memento/DeleteElementMemento.cs @@ -21,16 +21,17 @@ using System; using Greenshot.Configuration; using Greenshot.Drawing; +using Greenshot.Plugin.Drawing; namespace Greenshot.Memento { /// /// The DeleteElementMemento makes it possible to undo deleting an element /// public class DeleteElementMemento : IMemento { - private DrawableContainer drawableContainer; + private IDrawableContainer drawableContainer; private Surface surface; - - public DeleteElementMemento(Surface surface, DrawableContainer drawableContainer) { + + public DeleteElementMemento(Surface surface, IDrawableContainer drawableContainer) { this.surface = surface; this.drawableContainer = drawableContainer; } diff --git a/GreenshotPlugin/Core/ImageHelper.cs b/GreenshotPlugin/Core/ImageHelper.cs index 395dae935..31d5a5ee1 100644 --- a/GreenshotPlugin/Core/ImageHelper.cs +++ b/GreenshotPlugin/Core/ImageHelper.cs @@ -745,7 +745,7 @@ namespace GreenshotPlugin.Core { cm.Matrix22 = 0; cm.Matrix33 = darkness; ia.SetColorMatrix(cm); - Rectangle shadowRectangle = new Rectangle(new Point(shadowSize - 1, shadowSize - 1), sourceBitmap.Size); + Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size); graphics.DrawImage(sourceBitmap, shadowRectangle, 0, 0, sourceBitmap.Width, sourceBitmap.Height, GraphicsUnit.Pixel, ia); } // blur "shadow", apply to whole new image diff --git a/GreenshotPlugin/Interfaces/Drawing/Container.cs b/GreenshotPlugin/Interfaces/Drawing/Container.cs index 175f882d4..b07dbb5b2 100644 --- a/GreenshotPlugin/Interfaces/Drawing/Container.cs +++ b/GreenshotPlugin/Interfaces/Drawing/Container.cs @@ -22,12 +22,13 @@ using System; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms; +using System.ComponentModel; namespace Greenshot.Plugin.Drawing { public enum RenderMode {EDIT, EXPORT}; public enum EditStatus {UNDRAWN, DRAWING, MOVING, RESIZING, IDLE}; - public interface IDrawableContainer { + public interface IDrawableContainer : INotifyPropertyChanged { ISurface Parent { get; } @@ -76,9 +77,22 @@ namespace Greenshot.Plugin.Drawing { get; } + EditStatus Status { + get; + set; + } void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment); void Invalidate(); void Dispose(); + bool ClickableAt(int x, int y); + void HideGrippers(); + void ShowGrippers(); + void MoveBy(int x, int y); + bool HandleMouseDown(int x, int y); + void HandleMouseUp(int x, int y); + bool HandleMouseMove(int x, int y); + bool InitContent(); + void MakeBoundsChangeUndoable(bool allowMerge); } public interface ITextContainer: IDrawableContainer { diff --git a/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs b/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs index a87416b2b..a67c5e4ff 100644 --- a/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs +++ b/GreenshotPlugin/Interfaces/Forms/ImageEditor.cs @@ -70,9 +70,10 @@ namespace Greenshot.Plugin { ICaptureDetails CaptureDetails { get; } - + ISurface Surface { get; + set; } } } diff --git a/GreenshotPlugin/Interfaces/Generic.cs b/GreenshotPlugin/Interfaces/Generic.cs index f8fa9261b..2aed38908 100644 --- a/GreenshotPlugin/Interfaces/Generic.cs +++ b/GreenshotPlugin/Interfaces/Generic.cs @@ -25,6 +25,7 @@ using System.Windows.Forms; using Greenshot.Plugin.Drawing; using System.IO; +using System.Collections.Generic; namespace Greenshot.Plugin { /// @@ -58,13 +59,18 @@ namespace Greenshot.Plugin { public delegate void SurfaceSizeChangeEventHandler(object source); public delegate void SurfaceMessageEventHandler(object source, SurfaceMessageEventArgs eventArgs); + public delegate void SurfaceElementEventHandler(object source, IList element); + public delegate void SurfaceDrawingModeEventHandler(object source, DrawingModes drawingMode); + public enum DrawingModes { None, Rect, Ellipse, Text, Line, Arrow, Crop, Highlight, Obfuscate, Bitmap, Path } /// /// The interface to the Surface object, so Plugins can use it. /// public interface ISurface : IDisposable { event SurfaceSizeChangeEventHandler SurfaceSizeChanged; - event SurfaceMessageEventHandler SurfaceMessage; + event SurfaceMessageEventHandler SurfaceMessage; + event SurfaceDrawingModeEventHandler DrawingModeChanged; + event SurfaceElementEventHandler MovingElementChanged; /// /// Get/Set the image to the Surface