From ef5b5deb7ade72376f7adef6081125ab90cec90d Mon Sep 17 00:00:00 2001 From: Killy Date: Fri, 1 May 2020 18:16:33 +0300 Subject: [PATCH] Smarter zoom - keep selected elements in sight --- Greenshot/Drawing/DrawableContainerList.cs | 24 ++++++++++++ Greenshot/Drawing/Surface.cs | 7 ++++ Greenshot/Forms/ImageEditorForm.cs | 38 +++++++++++++------ .../Interfaces/Drawing/Container.cs | 4 ++ 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/Greenshot/Drawing/DrawableContainerList.cs b/Greenshot/Drawing/DrawableContainerList.cs index 9451b06ea..3d200598e 100644 --- a/Greenshot/Drawing/DrawableContainerList.cs +++ b/Greenshot/Drawing/DrawableContainerList.cs @@ -235,6 +235,30 @@ namespace Greenshot.Drawing { return false; } + /// + /// A rectangle containing DrawingBounds of all drawableContainers in this list, + /// or empty rectangle if nothing is there. + /// + public Rectangle DrawingBounds + { + get + { + if (Count == 0) + { + return Rectangle.Empty; + } + else + { + var result = this[0].DrawingBounds; + for (int i = 1; i < Count; i++) + { + result = Rectangle.Union(result, this[i].DrawingBounds); + } + return result; + } + } + } + /// /// Triggers all elements in the list ot be redrawn. /// diff --git a/Greenshot/Drawing/Surface.cs b/Greenshot/Drawing/Surface.cs index 2ea5e0b00..8b33b6a56 100644 --- a/Greenshot/Drawing/Surface.cs +++ b/Greenshot/Drawing/Surface.cs @@ -1922,6 +1922,13 @@ namespace Greenshot.Drawing ); } + /// + /// Get the rectangle bounding all selected elements (in surface coordinates space), + /// or empty rectangle if nothing is selcted. + /// + public Rectangle GetSelectionRectangle() + => ToSurfaceCoordinates(selectedElements.DrawingBounds); + /// /// Duplicate all the selecteded elements /// diff --git a/Greenshot/Forms/ImageEditorForm.cs b/Greenshot/Forms/ImageEditorForm.cs index 1e177e428..8bf59df27 100644 --- a/Greenshot/Forms/ImageEditorForm.cs +++ b/Greenshot/Forms/ImageEditorForm.cs @@ -1580,21 +1580,37 @@ namespace Greenshot { { return; } + if (value == Surface.ZoomFactor) + { + return; + } - // Store old scroll position - // When no scroll is currently needed - prefer top left corner. - var horizontalCenter = 0.0; - var verticalCenter = 0.0; - var rc = surface.GetVisibleRectangle(); + // Store scroll position + var rc = surface.GetVisibleRectangle(); // use visible rc by default var size = surface.Size; - if (size.Width > rc.Width) + if (value > Surface.ZoomFactor) // being smart on zoom-in { - horizontalCenter = 1.0 * (rc.Left + rc.Width / 2) / size.Width; - } - if (size.Height > rc.Height) - { - verticalCenter = 1.0 * (rc.Top + rc.Height / 2) / size.Height; + var sel = surface.GetSelectionRectangle(); + if (sel != Rectangle.Empty) + { + rc.Intersect(sel); // zoom to visible part of selection + } + else + { + // if image fits completely to currently visible rc and there are no things to focus on + // - prefer top left corner to zoom-in as less disorienting for screenshots + if (size.Width < rc.Width) + { + rc.Width = 0; + } + if (size.Height < rc.Height) + { + rc.Height = 0; + } + } } + var horizontalCenter = 1.0 * (rc.Left + rc.Width / 2) / size.Width; + var verticalCenter = 1.0 * (rc.Top + rc.Height / 2) / size.Height; // Set the new zoom value Surface.ZoomFactor = value; diff --git a/GreenshotPlugin/Interfaces/Drawing/Container.cs b/GreenshotPlugin/Interfaces/Drawing/Container.cs index 35a6cf50a..f4065801a 100644 --- a/GreenshotPlugin/Interfaces/Drawing/Container.cs +++ b/GreenshotPlugin/Interfaces/Drawing/Container.cs @@ -145,6 +145,10 @@ namespace GreenshotPlugin.Interfaces.Drawing get; set; } + Rectangle DrawingBounds + { + get; + } void MakeBoundsChangeUndoable(bool allowMerge); void Transform(Matrix matrix); void MoveBy(int dx, int dy);