mirror of
https://github.com/greenshot/greenshot
synced 2025-07-16 10:03:44 -07:00
Zoom feature for the editor
This commit is contained in:
parent
38739ce427
commit
8b45489b11
18 changed files with 585 additions and 52 deletions
|
@ -66,6 +66,12 @@ namespace Greenshot {
|
|||
// whether part of the editor controls are disabled depending on selected item(s)
|
||||
private bool _controlsDisabledDueToConfirmable;
|
||||
|
||||
/// <summary>
|
||||
/// All provided zoom values (in percents) in ascending order.
|
||||
/// </summary>
|
||||
private readonly int[] ZOOM_VALUES = new[] { 25, 50, 66, 75, 100, 200, 300, 400, 600 };
|
||||
private int _zoomValue = 100;
|
||||
|
||||
/// <summary>
|
||||
/// An Implementation for the IImageEditor, this way Plugins have access to the HWND handles wich can be used with Win32 API calls.
|
||||
/// </summary>
|
||||
|
@ -420,20 +426,14 @@ namespace Greenshot {
|
|||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
private void SurfaceSizeChanged(object sender, EventArgs e) {
|
||||
if (EditorConfiguration.MatchSizeToCapture) {
|
||||
// Set editor's initial size to the size of the surface plus the size of the chrome
|
||||
Size imageSize = Surface.Image.Size;
|
||||
Size currentFormSize = Size;
|
||||
Size currentImageClientSize = panel1.ClientSize;
|
||||
int minimumFormWidth = 650;
|
||||
int minimumFormHeight = 530;
|
||||
int newWidth = Math.Max(minimumFormWidth, currentFormSize.Width - currentImageClientSize.Width + imageSize.Width);
|
||||
int newHeight = Math.Max(minimumFormHeight, currentFormSize.Height - currentImageClientSize.Height + imageSize.Height);
|
||||
Size = new Size(newWidth, newHeight);
|
||||
private void SurfaceSizeChanged(object sender, EventArgs e)
|
||||
{
|
||||
if (EditorConfiguration.MatchSizeToCapture)
|
||||
{
|
||||
Size = GetOptimalWindowSize();
|
||||
}
|
||||
dimensionsLabel.Text = Surface.Image.Width + "x" + Surface.Image.Height;
|
||||
ImageEditorFormResize(sender, new EventArgs());
|
||||
AlignCanvasPositionAfterResize();
|
||||
}
|
||||
|
||||
public ISurface Surface {
|
||||
|
@ -860,15 +860,34 @@ namespace Greenshot {
|
|||
case Keys.Oemcomma: // Rotate CCW Ctrl + ,
|
||||
RotateCcwToolstripButtonClick(sender, e);
|
||||
break;
|
||||
case Keys.OemPeriod: // Rotate CW Ctrl + .
|
||||
case Keys.OemPeriod: // Rotate CW Ctrl + .
|
||||
RotateCwToolstripButtonClick(sender, e);
|
||||
break;
|
||||
case Keys.Add: // Ctrl + +
|
||||
case Keys.Oemplus: // Ctrl + +
|
||||
case Keys.Add: // Ctrl + Num+
|
||||
case Keys.Oemplus: // Ctrl + +
|
||||
ZoomInMenuItemClick(sender, e);
|
||||
break;
|
||||
case Keys.Subtract: // Ctrl + Num-
|
||||
case Keys.OemMinus: // Ctrl + -
|
||||
ZoomOutMenuItemClick(sender, e);
|
||||
break;
|
||||
case Keys.Divide: // Ctrl + Num/
|
||||
case Keys.OemQuestion: // Ctrl + / (?)
|
||||
ZoomSetValueMenuItemClick(zoomActualSizeMenuItem, e);
|
||||
break;
|
||||
case Keys.Multiply: // Ctrl + Num*
|
||||
case Keys.D8: // Ctrl + 8 (*)
|
||||
ZoomBestFitMenuItemClick(sender, e);
|
||||
break;
|
||||
}
|
||||
} else if (e.Modifiers.Equals(Keys.Control | Keys.Shift)) {
|
||||
switch (e.KeyCode) {
|
||||
case Keys.Add: // Ctrl + Shift + Num+
|
||||
case Keys.Oemplus: // Ctrl + Shift + +
|
||||
EnlargeCanvasToolStripMenuItemClick(sender, e);
|
||||
break;
|
||||
case Keys.Subtract: // Ctrl + -
|
||||
case Keys.OemMinus: // Ctrl + -
|
||||
case Keys.Subtract: // Ctrl + Shift + Num-
|
||||
case Keys.OemMinus: // Ctrl + Shift + -
|
||||
ShrinkCanvasToolStripMenuItemClick(sender, e);
|
||||
break;
|
||||
}
|
||||
|
@ -1444,28 +1463,130 @@ namespace Greenshot {
|
|||
}
|
||||
|
||||
private void ImageEditorFormResize(object sender, EventArgs e) {
|
||||
AlignCanvasPositionAfterResize();
|
||||
}
|
||||
|
||||
private void AlignCanvasPositionAfterResize() {
|
||||
if (Surface?.Image == null || panel1 == null) {
|
||||
return;
|
||||
}
|
||||
Size imageSize = Surface.Image.Size;
|
||||
Size currentClientSize = panel1.ClientSize;
|
||||
var canvas = Surface as Control;
|
||||
Size canvasSize = canvas.Size;
|
||||
Size currentClientSize = panel1.ClientSize;
|
||||
Panel panel = (Panel) canvas?.Parent;
|
||||
if (panel == null) {
|
||||
return;
|
||||
}
|
||||
int offsetX = -panel.HorizontalScroll.Value;
|
||||
int offsetY = -panel.VerticalScroll.Value;
|
||||
if (currentClientSize.Width > imageSize.Width) {
|
||||
canvas.Left = offsetX + (currentClientSize.Width - imageSize.Width) / 2;
|
||||
if (currentClientSize.Width > canvasSize.Width) {
|
||||
canvas.Left = offsetX + (currentClientSize.Width - canvasSize.Width) / 2;
|
||||
} else {
|
||||
canvas.Left = offsetX + 0;
|
||||
}
|
||||
if (currentClientSize.Height > imageSize.Height) {
|
||||
canvas.Top = offsetY + (currentClientSize.Height - imageSize.Height) / 2;
|
||||
if (currentClientSize.Height > canvasSize.Height) {
|
||||
canvas.Top = offsetY + (currentClientSize.Height - canvasSize.Height) / 2;
|
||||
} else {
|
||||
canvas.Top = offsetY + 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compute a size as a sum of surface size and chrome.
|
||||
/// Upper bound is working area of the screen. Lower bound is fixed value.
|
||||
/// </summary>
|
||||
private Size GetOptimalWindowSize() {
|
||||
var surfaceSize = (Surface as Control).Size;
|
||||
var chromeSize = GetChromeSize();
|
||||
var newWidth = chromeSize.Width + surfaceSize.Width;
|
||||
var newHeight = chromeSize.Height + surfaceSize.Height;
|
||||
|
||||
// Upper bound. Don't make it bigger than the available working area.
|
||||
var screen = Screen.FromControl(this);
|
||||
var workingArea = screen.WorkingArea;
|
||||
newWidth = Math.Min(newWidth, workingArea.Width);
|
||||
newHeight = Math.Min(newHeight, workingArea.Height);
|
||||
|
||||
// Lower bound. Don't make it smaller than a fixed value.
|
||||
int minimumFormWidth = 650;
|
||||
int minimumFormHeight = 530;
|
||||
newWidth = Math.Max(minimumFormWidth, newWidth);
|
||||
newHeight = Math.Max(minimumFormHeight, newHeight);
|
||||
|
||||
return new Size(newWidth, newHeight);
|
||||
}
|
||||
|
||||
private Size GetChromeSize()
|
||||
=> Size - panel1.ClientSize;
|
||||
|
||||
/// <summary>
|
||||
/// Compute a size that the form can take without getting out of working area of the screen.
|
||||
/// </summary>
|
||||
private Size GetAvailableScreenSpace() {
|
||||
var screen = Screen.FromControl(this);
|
||||
var screenBounds = screen.Bounds;
|
||||
var workingArea = screen.WorkingArea;
|
||||
if (Left > screenBounds.Left && Top > screenBounds.Top) {
|
||||
return new Size(workingArea.Width - Left, workingArea.Height - Top);
|
||||
} else {
|
||||
return workingArea.Size;
|
||||
}
|
||||
}
|
||||
|
||||
private void ZoomInMenuItemClick(object sender, EventArgs e) {
|
||||
var nextIndex = Array.FindIndex(ZOOM_VALUES, v => v > _zoomValue);
|
||||
var nextValue = nextIndex < 0 ? ZOOM_VALUES[ZOOM_VALUES.Length - 1] : ZOOM_VALUES[nextIndex];
|
||||
|
||||
ZoomSetValue(nextValue);
|
||||
}
|
||||
|
||||
private void ZoomOutMenuItemClick(object sender, EventArgs e) {
|
||||
var nextIndex = Array.FindLastIndex(ZOOM_VALUES, v => v < _zoomValue);
|
||||
var nextValue = nextIndex < 0 ? ZOOM_VALUES[0] : ZOOM_VALUES[nextIndex];
|
||||
|
||||
ZoomSetValue(nextValue);
|
||||
}
|
||||
|
||||
private void ZoomSetValueMenuItemClick(object sender, EventArgs e) {
|
||||
var senderMenuItem = (ToolStripMenuItem)sender;
|
||||
int zoomPercent = int.Parse((string)senderMenuItem.Tag);
|
||||
|
||||
ZoomSetValue(zoomPercent);
|
||||
}
|
||||
|
||||
private void ZoomBestFitMenuItemClick(object sender, EventArgs e) {
|
||||
var maxWindowSize = GetAvailableScreenSpace();
|
||||
var chromeSize = GetChromeSize();
|
||||
var maxImageSize = maxWindowSize - chromeSize;
|
||||
var imageSize = Surface.Image.Size;
|
||||
|
||||
static bool isFit(int zoom, int source, int boundary)
|
||||
=> source * zoom / 100 <= boundary;
|
||||
|
||||
var nextValue = Array.FindLast(
|
||||
ZOOM_VALUES,
|
||||
zoom => isFit(zoom, imageSize.Width, maxImageSize.Width)
|
||||
&& isFit(zoom, imageSize.Height, maxImageSize.Height)
|
||||
);
|
||||
|
||||
ZoomSetValue(nextValue);
|
||||
}
|
||||
|
||||
private void ZoomSetValue(int value) {
|
||||
_zoomValue = value;
|
||||
Surface.ZoomFactor = 1f * value / 100;
|
||||
|
||||
// Update zoom controls
|
||||
string valueString = value.ToString();
|
||||
zoomStatusDropDownBtn.Text = valueString + "%";
|
||||
foreach (var item in zoomMenuStrip.Items) {
|
||||
if (item is ToolStripMenuItem menuItem) {
|
||||
menuItem.Checked = menuItem.Tag as string == valueString;
|
||||
}
|
||||
}
|
||||
|
||||
Size = GetOptimalWindowSize();
|
||||
AlignCanvasPositionAfterResize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue