diff --git a/src/Greenshot.Base/Controls/GreenshotForm.cs b/src/Greenshot.Base/Controls/GreenshotForm.cs index eff79e975..42b2719ce 100644 --- a/src/Greenshot.Base/Controls/GreenshotForm.cs +++ b/src/Greenshot.Base/Controls/GreenshotForm.cs @@ -350,7 +350,7 @@ namespace Greenshot.Base.Controls { if (!Language.TryGetString(languageKey, out langString)) { - LOG.WarnFormat("Unknown language key '{0}' configured for control '{1}', this might be okay.", languageKey, applyTo.Name); + LOG.DebugFormat("Unknown language key '{0}' configured for control '{1}', this might be okay.", languageKey, applyTo.Name); return; } diff --git a/src/Greenshot.Base/Core/Language.cs b/src/Greenshot.Base/Core/Language.cs index 8037393ad..4627a10fc 100644 --- a/src/Greenshot.Base/Core/Language.cs +++ b/src/Greenshot.Base/Core/Language.cs @@ -470,7 +470,7 @@ namespace Greenshot.Base.Core languageFile }; LanguageFiles.Add(languageFile.Ietf, currentFiles); - Log.InfoFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath); + Log.DebugFormat("Added language definition {0} from: {1}", languageFile.Description, languageFile.Filepath); } } } diff --git a/src/Greenshot.Base/Interfaces/Drawing/Adorners/IAdorner.cs b/src/Greenshot.Base/Interfaces/Drawing/Adorners/IAdorner.cs index 4dfa4811d..c55044928 100644 --- a/src/Greenshot.Base/Interfaces/Drawing/Adorners/IAdorner.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/Adorners/IAdorner.cs @@ -108,5 +108,10 @@ namespace Greenshot.Base.Interfaces.Drawing.Adorners /// The color of the fill of the adorner /// Color FillColor { get; set; } + + /// + /// This is to TAG the adorner so we know the type + /// + string Tag { get; set; } } } \ No newline at end of file diff --git a/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs b/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs index 3d420bfa3..2363b7ac9 100644 --- a/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/IDrawableContainer.cs @@ -24,6 +24,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Drawing2D; +using System.Windows.Forms; using Greenshot.Base.Interfaces.Drawing.Adorners; namespace Greenshot.Base.Interfaces.Drawing @@ -97,5 +98,13 @@ namespace Greenshot.Base.Interfaces.Drawing /// /// uint void AdjustToDpi(uint dpi); + + /// + /// Enable a way for elements to add a context menu entry + /// + /// ContextMenuStrip + /// ISurface + /// MouseEventArgs + void AddContextMenuItems(ContextMenuStrip menu, ISurface surface, MouseEventArgs mouseEventArgs); } } \ No newline at end of file diff --git a/src/Greenshot.Base/Interfaces/ISurface.cs b/src/Greenshot.Base/Interfaces/ISurface.cs index 396a5702f..4ec000ed9 100644 --- a/src/Greenshot.Base/Interfaces/ISurface.cs +++ b/src/Greenshot.Base/Interfaces/ISurface.cs @@ -101,13 +101,49 @@ namespace Greenshot.Base.Interfaces long SaveElementsToStream(Stream stream); void LoadElementsFromStream(Stream stream); + /// + /// Provides the selected elements + /// + IDrawableContainerList SelectedElements { get; } + + /// + /// Is there an element selected on the surface? + /// bool HasSelectedElements { get; } + + /// + /// Remove all selected elements + /// void RemoveSelectedElements(); + + /// + /// Cut the selected elements to the clipboard + /// void CutSelectedElements(); + + /// + /// Copy the selected elements to the clipboard + /// void CopySelectedElements(); + + /// + /// Paste the elements from the clipboard + /// void PasteElementFromClipboard(); + + /// + /// Duplicate the selected elements + /// void DuplicateSelectedElements(); + + /// + /// Deselected the specified element + /// void DeselectElement(IDrawableContainer container, bool generateEvents = true); + + /// + /// Deselected all elements + /// void DeselectAllElements(); /// diff --git a/src/Greenshot.Base/UnmanagedHelpers/Enums/RegionResult.cs b/src/Greenshot.Base/UnmanagedHelpers/Enums/RegionResult.cs index 013f70ef3..f9c0e5a1f 100644 --- a/src/Greenshot.Base/UnmanagedHelpers/Enums/RegionResult.cs +++ b/src/Greenshot.Base/UnmanagedHelpers/Enums/RegionResult.cs @@ -28,5 +28,7 @@ namespace Greenshot.Base.UnmanagedHelpers.Enums { REGION_ERROR = 0, REGION_NULLREGION = 1, + SIMPLEREGION = 2, + COMPLEXREGION = 3 } } \ No newline at end of file diff --git a/src/Greenshot.Editor/Drawing/Adorners/AbstractAdorner.cs b/src/Greenshot.Editor/Drawing/Adorners/AbstractAdorner.cs index dde10bb84..0890a87d9 100644 --- a/src/Greenshot.Editor/Drawing/Adorners/AbstractAdorner.cs +++ b/src/Greenshot.Editor/Drawing/Adorners/AbstractAdorner.cs @@ -176,5 +176,10 @@ namespace Greenshot.Editor.Drawing.Adorners public virtual void Transform(Matrix matrix) { } + + /// + /// This is to TAG the adorner so we know the type + /// + public string Tag { get; set; } } } \ No newline at end of file diff --git a/src/Greenshot.Editor/Drawing/Adorners/TargetAdorner.cs b/src/Greenshot.Editor/Drawing/Adorners/TargetAdorner.cs index f39f535e6..c59fc43ef 100644 --- a/src/Greenshot.Editor/Drawing/Adorners/TargetAdorner.cs +++ b/src/Greenshot.Editor/Drawing/Adorners/TargetAdorner.cs @@ -27,7 +27,7 @@ using Greenshot.Base.Interfaces.Drawing; namespace Greenshot.Editor.Drawing.Adorners { /// - /// This implements the special "gripper" for the Speech-Bubble tail + /// This implements the special target "gripper", e.g. used for the Speech-Bubble tail /// public sealed class TargetAdorner : AbstractAdorner { @@ -41,8 +41,8 @@ namespace Greenshot.Editor.Drawing.Adorners /// /// Handle the mouse down /// - /// - /// + /// object + /// MouseEventArgs public override void MouseDown(object sender, MouseEventArgs mouseEventArgs) { EditStatus = EditStatus.MOVING; @@ -51,8 +51,8 @@ namespace Greenshot.Editor.Drawing.Adorners /// /// Handle the mouse move /// - /// - /// + /// object + /// MouseEventArgs public override void MouseMove(object sender, MouseEventArgs mouseEventArgs) { if (EditStatus != EditStatus.MOVING) diff --git a/src/Greenshot.Editor/Drawing/ArrowContainer.cs b/src/Greenshot.Editor/Drawing/ArrowContainer.cs index eb1e10e2f..9907ad106 100644 --- a/src/Greenshot.Editor/Drawing/ArrowContainer.cs +++ b/src/Greenshot.Editor/Drawing/ArrowContainer.cs @@ -66,44 +66,40 @@ namespace Greenshot.Editor.Drawing int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS); bool shadow = GetFieldValueAsBool(FieldType.SHADOW); - if (lineThickness > 0) + if (lineThickness <= 0) return; + + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.None; + Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); + ArrowHeadCombination heads = (ArrowHeadCombination) GetFieldValue(FieldType.ARROWHEADS); + if (shadow) { - graphics.SmoothingMode = SmoothingMode.HighQuality; - graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; - graphics.CompositingQuality = CompositingQuality.HighQuality; - graphics.PixelOffsetMode = PixelOffsetMode.None; - Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR); - ArrowHeadCombination heads = (ArrowHeadCombination) GetFieldValue(FieldType.ARROWHEADS); - if (lineThickness > 0) + //draw shadow first + int basealpha = 100; + int alpha = basealpha; + int steps = 5; + int currentStep = 1; + while (currentStep <= steps) { - if (shadow) - { - //draw shadow first - int basealpha = 100; - int alpha = basealpha; - int steps = 5; - int currentStep = 1; - while (currentStep <= steps) - { - using Pen shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness); - SetArrowHeads(heads, shadowCapPen); + using Pen shadowCapPen = new Pen(Color.FromArgb(alpha, 100, 100, 100), lineThickness); + SetArrowHeads(heads, shadowCapPen); - graphics.DrawLine(shadowCapPen, - Left + currentStep, - Top + currentStep, - Left + currentStep + Width, - Top + currentStep + Height); + graphics.DrawLine(shadowCapPen, + Left + currentStep, + Top + currentStep, + Left + currentStep + Width, + Top + currentStep + Height); - currentStep++; - alpha -= basealpha / steps; - } - } - - using Pen pen = new Pen(lineColor, lineThickness); - SetArrowHeads(heads, pen); - graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height); + currentStep++; + alpha -= basealpha / steps; } } + + using Pen pen = new Pen(lineColor, lineThickness); + SetArrowHeads(heads, pen); + graphics.DrawLine(pen, Left, Top, Left + Width, Top + Height); } private void SetArrowHeads(ArrowHeadCombination heads, Pen pen) diff --git a/src/Greenshot.Editor/Drawing/DrawableContainer.cs b/src/Greenshot.Editor/Drawing/DrawableContainer.cs index 38eab8b3f..f8a14052b 100644 --- a/src/Greenshot.Editor/Drawing/DrawableContainer.cs +++ b/src/Greenshot.Editor/Drawing/DrawableContainer.cs @@ -26,6 +26,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Runtime.Serialization; +using System.Windows.Forms; using Greenshot.Base.IniFile; using Greenshot.Base.Interfaces; using Greenshot.Base.Interfaces.Drawing; @@ -448,6 +449,12 @@ namespace Greenshot.Editor.Drawing } } + /// + public virtual void AddContextMenuItems(ContextMenuStrip menu, ISurface surface, MouseEventArgs mouseEventArgs) + { + // Empty as we do not want to add something to the context menu for every element + } + public virtual bool Contains(int x, int y) { return Bounds.Contains(x, y); diff --git a/src/Greenshot.Editor/Drawing/DrawableContainerList.cs b/src/Greenshot.Editor/Drawing/DrawableContainerList.cs index 9ab825e4a..4da98fa37 100644 --- a/src/Greenshot.Editor/Drawing/DrawableContainerList.cs +++ b/src/Greenshot.Editor/Drawing/DrawableContainerList.cs @@ -589,9 +589,10 @@ namespace Greenshot.Editor.Drawing /// /// Add items to a context menu for the selected item /// - /// - /// - public virtual void AddContextMenuItems(ContextMenuStrip menu, ISurface surface) + /// ContextMenuStrip + /// ISurface + /// MouseEventArgs + public virtual void AddContextMenuItems(ContextMenuStrip menu, ISurface surface, MouseEventArgs mouseEventArgs) { bool push = surface.Elements.CanPushDown(this); bool pull = surface.Elements.CanPullUp(this); @@ -678,15 +679,7 @@ namespace Greenshot.Editor.Drawing menu.Items.Add(item); // Reset - bool canReset = false; - foreach (var drawableContainer in this) - { - var container = (DrawableContainer) drawableContainer; - if (container.HasDefaultSize) - { - canReset = true; - } - } + bool canReset = this.Cast().Any(container => container.HasDefaultSize); if (canReset) { @@ -713,48 +706,40 @@ namespace Greenshot.Editor.Drawing }; menu.Items.Add(item); } + + // "ask" the containers to add to the context menu + foreach (var surfaceElement in surface.Elements) + { + surfaceElement.AddContextMenuItems(menu, surface, mouseEventArgs); + } } - public virtual void ShowContextMenu(MouseEventArgs e, ISurface iSurface) + public virtual void ShowContextMenu(MouseEventArgs mouseEventArgs, ISurface iSurface) { if (iSurface is not Surface surface) { return; } - bool hasMenu = false; - foreach (var drawableContainer in this) + bool hasMenu = this.Cast().Any(container => container.HasContextMenu); + + if (!hasMenu) return; + + ContextMenuStrip menu = new ContextMenuStrip(); + AddContextMenuItems(menu, surface, mouseEventArgs); + if (menu.Items.Count <= 0) return; + menu.Show(surface, surface.ToSurfaceCoordinates(mouseEventArgs.Location)); + while (true) { - var container = (DrawableContainer) drawableContainer; - if (!container.HasContextMenu) + if (menu.Visible) { - continue; + Application.DoEvents(); + Thread.Sleep(100); } - - hasMenu = true; - break; - } - - if (hasMenu) - { - ContextMenuStrip menu = new ContextMenuStrip(); - AddContextMenuItems(menu, surface); - if (menu.Items.Count > 0) + else { - menu.Show(surface, surface.ToSurfaceCoordinates(e.Location)); - while (true) - { - if (menu.Visible) - { - Application.DoEvents(); - Thread.Sleep(100); - } - else - { - menu.Dispose(); - break; - } - } + menu.Dispose(); + break; } } } @@ -763,18 +748,16 @@ namespace Greenshot.Editor.Drawing protected virtual void Dispose(bool disposing) { - if (!_disposedValue) + if (_disposedValue) return; + if (disposing) { - if (disposing) + foreach (var drawableContainer in this) { - foreach (var drawableContainer in this) - { - drawableContainer.Dispose(); - } + drawableContainer.Dispose(); } - - _disposedValue = true; } + + _disposedValue = true; } // This code added to correctly implement the disposable pattern. diff --git a/src/Greenshot.Editor/Drawing/Surface.cs b/src/Greenshot.Editor/Drawing/Surface.cs index be40c7d1c..8eb2a872e 100644 --- a/src/Greenshot.Editor/Drawing/Surface.cs +++ b/src/Greenshot.Editor/Drawing/Surface.cs @@ -2036,23 +2036,27 @@ namespace Greenshot.Editor.Drawing /// /// Returns if this surface has selected elements /// - /// - public bool HasSelectedElements => (selectedElements != null && selectedElements.Count > 0); + /// bool + public bool HasSelectedElements => selectedElements is { Count: > 0 }; + + /// + /// Provides the selected elements + /// + public IDrawableContainerList SelectedElements => selectedElements; /// /// Remove all the selected elements /// public void RemoveSelectedElements() { - if (HasSelectedElements) + if (!HasSelectedElements) return; + + // As RemoveElement will remove the element from the selectedElements list we need to copy the element to another list. + RemoveElements(selectedElements); + if (_movingElementChanged != null) { - // As RemoveElement will remove the element from the selectedElements list we need to copy the element to another list. - RemoveElements(selectedElements); - if (_movingElementChanged != null) - { - SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); - _movingElementChanged(this, eventArgs); - } + SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs(); + _movingElementChanged(this, eventArgs); } }