Refactor snap to edge

(cherry picked from commit 9295c343b3797d469e393a4cd2cc771c80fff7ea)
This commit is contained in:
Nathan Brown 2022-11-18 15:23:13 -08:00
commit 1f50db16dc
3 changed files with 66 additions and 58 deletions

View file

@ -29,6 +29,14 @@ using Greenshot.Base.Interfaces.Drawing.Adorners;
namespace Greenshot.Base.Interfaces.Drawing namespace Greenshot.Base.Interfaces.Drawing
{ {
public enum Direction
{
LEFT,
RIGHT,
TOP,
BOTTOM,
}
public interface IDrawableContainer : INotifyPropertyChanged, IDisposable public interface IDrawableContainer : INotifyPropertyChanged, IDisposable
{ {
/// <summary> /// <summary>
@ -111,5 +119,12 @@ namespace Greenshot.Base.Interfaces.Drawing
/// <param name="surface">ISurface</param> /// <param name="surface">ISurface</param>
/// <param name="mouseEventArgs">MouseEventArgs</param> /// <param name="mouseEventArgs">MouseEventArgs</param>
void AddContextMenuItems(ContextMenuStrip menu, ISurface surface, MouseEventArgs mouseEventArgs); void AddContextMenuItems(ContextMenuStrip menu, ISurface surface, MouseEventArgs mouseEventArgs);
/// <summary>
/// Snap the container to the edge of the surface.
/// </summary>
/// <param name="direction">Direction in which to move the container.</param>
/// <param name="surface">The surface the container belongs to.</param>
void SnapToEdge(Direction direction, ISurface surface);
} }
} }

View file

@ -684,5 +684,43 @@ namespace Greenshot.Editor.Drawing
protected virtual void InitializeFields() protected virtual void InitializeFields()
{ {
} }
/// <summary>
/// Snap the container to the edge of the surface.
/// </summary>
/// <param name="direction">Direction in which to move the container.</param>
/// <param name="surface">The surface the container belongs to.</param>
public void SnapToEdge(Direction direction, ISurface surface)
{
Size surfaceBounds = new(surface.Image.Width, surface.Image.Height);
NativeRectFloat newBounds = GetLocationAfterSnap(direction, this.Bounds, surfaceBounds);
this.MakeBoundsChangeUndoable(allowMerge: false);
this.ApplyBounds(newBounds);
}
private static NativeRectFloat GetLocationAfterSnap(Direction direction, NativeRect bounds, Size surfaceSize)
{
switch (direction)
{
case Direction.LEFT:
bounds = bounds.ChangeX(0);
break;
case Direction.RIGHT:
bounds = bounds.Offset(offsetX: surfaceSize.Width - bounds.Right);
break;
case Direction.TOP:
bounds = bounds.ChangeY(0);
break;
case Direction.BOTTOM:
bounds = bounds.Offset(offsetY: surfaceSize.Height - bounds.Bottom);
break;
default:
break;
}
return bounds;
}
} }
} }

View file

@ -39,14 +39,6 @@ using Greenshot.Editor.Memento;
namespace Greenshot.Editor.Drawing namespace Greenshot.Editor.Drawing
{ {
public enum Direction
{
LEFT,
RIGHT,
TOP,
BOTTOM,
}
/// <summary> /// <summary>
/// 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>
@ -743,7 +735,7 @@ namespace Greenshot.Editor.Drawing
MakeBoundsChangeUndoable(false); MakeBoundsChangeUndoable(false);
item.Width = surface.Image.Width; item.Width = surface.Image.Width;
} }
SnapAllToEdge(Direction.LEFT, surface, this); SnapAllToEdge(Direction.LEFT, surface);
surface.Invalidate(); // not sure if this belongs surface.Invalidate(); // not sure if this belongs
}; };
fitSubmenu.DropDownItems.Add(item); fitSubmenu.DropDownItems.Add(item);
@ -760,7 +752,7 @@ namespace Greenshot.Editor.Drawing
MakeBoundsChangeUndoable(false); MakeBoundsChangeUndoable(false);
item.Height = surface.Image.Height; item.Height = surface.Image.Height;
} }
SnapAllToEdge(Direction.TOP, surface, this); SnapAllToEdge(Direction.TOP, surface);
surface.Invalidate(); // not sure if this belongs surface.Invalidate(); // not sure if this belongs
}; };
fitSubmenu.DropDownItems.Add(item); fitSubmenu.DropDownItems.Add(item);
@ -775,7 +767,7 @@ namespace Greenshot.Editor.Drawing
}; };
item.Click += delegate item.Click += delegate
{ {
SnapAllToEdge(Direction.LEFT, surface, this); SnapAllToEdge(Direction.LEFT, surface);
}; };
snapSubmenu.DropDownItems.Add(item); snapSubmenu.DropDownItems.Add(item);
@ -786,7 +778,7 @@ namespace Greenshot.Editor.Drawing
}; };
item.Click += delegate item.Click += delegate
{ {
SnapAllToEdge(Direction.RIGHT, surface, this); SnapAllToEdge(Direction.RIGHT, surface);
}; };
snapSubmenu.DropDownItems.Add(item); snapSubmenu.DropDownItems.Add(item);
@ -797,7 +789,7 @@ namespace Greenshot.Editor.Drawing
}; };
item.Click += delegate item.Click += delegate
{ {
SnapAllToEdge(Direction.TOP, surface, this); SnapAllToEdge(Direction.TOP, surface);
}; };
snapSubmenu.DropDownItems.Add(item); snapSubmenu.DropDownItems.Add(item);
@ -808,7 +800,7 @@ namespace Greenshot.Editor.Drawing
}; };
item.Click += delegate item.Click += delegate
{ {
SnapAllToEdge(Direction.BOTTOM, surface, this); SnapAllToEdge(Direction.BOTTOM, surface);
}; };
snapSubmenu.DropDownItems.Add(item); snapSubmenu.DropDownItems.Add(item);
menu.Items.Add(snapSubmenu); menu.Items.Add(snapSubmenu);
@ -922,54 +914,17 @@ namespace Greenshot.Editor.Drawing
} }
} }
/// <summary>
/// Move an element to one edge of the surface.
/// </summary>
/// <param name="direction">Direction to move the element.</param>
/// <param name="surface"></param>
/// <param name="targetElement"></param>
public void SnapToEdge(Direction direction, ISurface surface, IDrawableContainer targetElement)
{
Size surfaceBounds = new(surface.Image.Width, surface.Image.Height);
NativeRectFloat newBounds = SnapHelper(direction, targetElement.Bounds, surfaceBounds);
targetElement.MakeBoundsChangeUndoable(allowMerge: false);
targetElement.ApplyBounds(newBounds);
}
public static NativeRectFloat SnapHelper(Direction direction, NativeRect bounds, Size surfaceSize)
{
switch (direction)
{
case Direction.LEFT:
bounds = bounds.ChangeX(0);
break;
case Direction.RIGHT:
bounds = bounds.Offset(offsetX: surfaceSize.Width - bounds.Right);
break;
case Direction.TOP:
bounds = bounds.ChangeY(0);
break;
case Direction.BOTTOM:
bounds = bounds.Offset(offsetY: surfaceSize.Height - bounds.Bottom);
break;
default:
break;
}
return bounds;
}
/// <summary> /// <summary>
/// Moves all selected elements to one edge of the surface. /// Moves all selected elements to one edge of the surface.
/// </summary> /// </summary>
/// <param name="direction"></param> /// <param name="direction"></param>
/// <param name="surface"></param> /// <param name="surface"></param>
/// <param name="elements"></param> ///
public void SnapAllToEdge(Direction direction, ISurface surface, IDrawableContainerList elements) public void SnapAllToEdge(Direction direction, ISurface surface)
{ {
foreach (var item in elements) foreach (IDrawableContainer item in this)
{ {
SnapToEdge(direction, surface, item); item.SnapToEdge(direction, surface);
} }
surface.DeselectAllElements(); surface.DeselectAllElements();
} }
@ -986,12 +941,12 @@ namespace Greenshot.Editor.Drawing
surface.ResizeCanvas(expansion.Left, expansion.Right, expansion.Top, expansion.Bottom); surface.ResizeCanvas(expansion.Left, expansion.Right, expansion.Top, expansion.Bottom);
SnapToEdge(direction, surface, targetElement); targetElement.SnapToEdge(direction, surface);
if (direction == Direction.LEFT || direction == Direction.RIGHT) if (direction == Direction.LEFT || direction == Direction.RIGHT)
SnapToEdge(Direction.TOP, surface, targetElement); targetElement.SnapToEdge(Direction.TOP, surface);
else if (direction == Direction.TOP || direction == Direction.BOTTOM) else if (direction == Direction.TOP || direction == Direction.BOTTOM)
SnapToEdge(Direction.LEFT, surface, targetElement); targetElement.SnapToEdge(Direction.LEFT, surface);
surface.DeselectAllElements(); surface.DeselectAllElements();
} }