Trying to replace the Gripper (which is a Label/Control) with adorners (custom code). This should prevent the slow cleanup, reduce resources and speedup the editor. Also we should have better "UI" feedback. This is still very experimental.

This commit is contained in:
Robin 2016-05-23 13:32:52 +02:00
commit 31db071394
15 changed files with 643 additions and 349 deletions

View file

@ -20,6 +20,7 @@
*/
using Greenshot.Configuration;
using Greenshot.Drawing.Adorners;
using Greenshot.Drawing.Fields;
using Greenshot.Drawing.Filters;
using Greenshot.Helpers;
@ -27,6 +28,7 @@ using Greenshot.IniFile;
using Greenshot.Memento;
using Greenshot.Plugin;
using Greenshot.Plugin.Drawing;
using Greenshot.Plugin.Drawing.Adorners;
using log4net;
using System;
using System.Collections.Generic;
@ -35,7 +37,8 @@ using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace Greenshot.Drawing {
namespace Greenshot.Drawing
{
/// <summary>
/// represents a rectangle, ellipse, label or whatever. Can contain filters, too.
/// serializable for clipboard support
@ -73,16 +76,6 @@ namespace Greenshot.Drawing {
if (!disposing) {
return;
}
if (_grippers != null) {
for (int i = 0; i < _grippers.Length; i++) {
if (_grippers[i] == null) {
continue;
}
_grippers[i].Dispose();
_grippers[i] = null;
}
_grippers = null;
}
FieldAggregator aggProps = _parent.FieldAggregator;
aggProps.UnbindElement(this);
@ -117,14 +110,13 @@ namespace Greenshot.Drawing {
get { return _parent; }
set { SwitchParent((Surface)value); }
}
[NonSerialized]
protected Gripper[] _grippers;
private bool layoutSuspended;
[NonSerialized]
private Gripper _targetGripper;
private TargetAdorner _targetGripper;
public Gripper TargetGripper {
public TargetAdorner TargetGripper {
get {
return _targetGripper;
}
@ -220,6 +212,11 @@ namespace Greenshot.Drawing {
}
}
/// <summary>
/// List of available Adorners
/// </summary>
public IList<IAdorner> Adorners { get; } = new List<IAdorner>();
[NonSerialized]
// will store current bounds of this DrawableContainer before starting a resize
protected Rectangle _boundsBeforeResize = Rectangle.Empty;
@ -329,73 +326,23 @@ namespace Greenshot.Drawing {
DoLayout();
}
/// <summary>
/// Move the TargetGripper around, confined to the surface to solve BUG-1682
/// </summary>
/// <param name="newX"></param>
/// <param name="newY"></param>
protected virtual void TargetGripperMove(int newX, int newY) {
Point newGripperLocation = new Point(newX, newY);
Rectangle surfaceBounds = new Rectangle(0, 0, _parent.Width, _parent.Height);
// Check if gripper inside the parent (surface), if not we need to move it inside
// This was made for BUG-1682
if (!surfaceBounds.Contains(newGripperLocation)) {
if (newGripperLocation.X > surfaceBounds.Right) {
newGripperLocation.X = surfaceBounds.Right - 5;
}
if (newGripperLocation.X < surfaceBounds.Left) {
newGripperLocation.X = surfaceBounds.Left;
}
if (newGripperLocation.Y > surfaceBounds.Bottom) {
newGripperLocation.Y = surfaceBounds.Bottom - 5;
}
if (newGripperLocation.Y < surfaceBounds.Top) {
newGripperLocation.Y = surfaceBounds.Top;
}
}
_targetGripper.Left = newGripperLocation.X;
_targetGripper.Top = newGripperLocation.Y;
}
/// <summary>
/// Initialize a target gripper
/// </summary>
protected void InitTargetGripper(Color gripperColor, Point location) {
_targetGripper = new Gripper {
Cursor = Cursors.SizeAll,
BackColor = gripperColor,
Visible = false,
Parent = _parent,
Location = location
};
_targetGripper.MouseDown += GripperMouseDown;
_targetGripper.MouseUp += GripperMouseUp;
_targetGripper.MouseMove += GripperMouseMove;
if (_parent != null) {
_parent.Controls.Add(_targetGripper); // otherwise we'll attach them in switchParent
}
_targetGripper = new TargetAdorner(this, location);
}
protected void InitGrippers() {
_grippers = new Gripper[8];
for(int i=0; i<_grippers.Length; i++) {
_grippers[i] = new Gripper();
_grippers[i].Position = i;
_grippers[i].MouseDown += GripperMouseDown;
_grippers[i].MouseUp += GripperMouseUp;
_grippers[i].MouseMove += GripperMouseMove;
_grippers[i].Visible = false;
_grippers[i].Parent = _parent;
}
_grippers[Gripper.POSITION_TOP_CENTER].Cursor = Cursors.SizeNS;
_grippers[Gripper.POSITION_MIDDLE_RIGHT].Cursor = Cursors.SizeWE;
_grippers[Gripper.POSITION_BOTTOM_CENTER].Cursor = Cursors.SizeNS;
_grippers[Gripper.POSITION_MIDDLE_LEFT].Cursor = Cursors.SizeWE;
if (_parent != null) {
_parent.Controls.AddRange(_grippers); // otherwise we'll attach them in switchParent
}
// Create the GripperAdorners
Adorners.Add(new GripperAdorner(this, Positions.TopLeft));
Adorners.Add(new GripperAdorner(this, Positions.TopCenter));
Adorners.Add(new GripperAdorner(this, Positions.TopRight));
Adorners.Add(new GripperAdorner(this, Positions.BottomLeft));
Adorners.Add(new GripperAdorner(this, Positions.BottomCenter));
Adorners.Add(new GripperAdorner(this, Positions.BottomRight));
Adorners.Add(new GripperAdorner(this, Positions.MiddleLeft));
Adorners.Add(new GripperAdorner(this, Positions.MiddleRight));
}
public void SuspendLayout() {
@ -407,101 +354,8 @@ namespace Greenshot.Drawing {
DoLayout();
}
protected virtual void DoLayout() {
if (_grippers == null) {
return;
}
if (!layoutSuspended) {
int[] xChoords = {Left-2,Left+Width/2-2,Left+Width-2};
int[] yChoords = {Top-2,Top+Height/2-2,Top+Height-2};
public virtual void DoLayout() {
_grippers[Gripper.POSITION_TOP_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_TOP_LEFT].Top = yChoords[0];
_grippers[Gripper.POSITION_TOP_CENTER].Left = xChoords[1]; _grippers[Gripper.POSITION_TOP_CENTER].Top = yChoords[0];
_grippers[Gripper.POSITION_TOP_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_TOP_RIGHT].Top = yChoords[0];
_grippers[Gripper.POSITION_MIDDLE_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_MIDDLE_RIGHT].Top = yChoords[1];
_grippers[Gripper.POSITION_BOTTOM_RIGHT].Left = xChoords[2]; _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top = yChoords[2];
_grippers[Gripper.POSITION_BOTTOM_CENTER].Left = xChoords[1]; _grippers[Gripper.POSITION_BOTTOM_CENTER].Top = yChoords[2];
_grippers[Gripper.POSITION_BOTTOM_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_BOTTOM_LEFT].Top = yChoords[2];
_grippers[Gripper.POSITION_MIDDLE_LEFT].Left = xChoords[0]; _grippers[Gripper.POSITION_MIDDLE_LEFT].Top = yChoords[1];
if((_grippers[Gripper.POSITION_TOP_LEFT].Left < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) ||
_grippers[Gripper.POSITION_TOP_LEFT].Left > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) {
_grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNWSE;
_grippers[Gripper.POSITION_TOP_RIGHT].Cursor = Cursors.SizeNESW;
_grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNWSE;
_grippers[Gripper.POSITION_BOTTOM_LEFT].Cursor = Cursors.SizeNESW;
} else if((_grippers[Gripper.POSITION_TOP_LEFT].Left > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) ||
_grippers[Gripper.POSITION_TOP_LEFT].Left < _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left && _grippers[Gripper.POSITION_TOP_LEFT].Top > _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) {
_grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNESW;
_grippers[Gripper.POSITION_TOP_RIGHT].Cursor = Cursors.SizeNWSE;
_grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNESW;
_grippers[Gripper.POSITION_BOTTOM_LEFT].Cursor = Cursors.SizeNWSE;
} else if (_grippers[Gripper.POSITION_TOP_LEFT].Left == _grippers[Gripper.POSITION_BOTTOM_RIGHT].Left) {
_grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeNS;
_grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeNS;
} else if (_grippers[Gripper.POSITION_TOP_LEFT].Top == _grippers[Gripper.POSITION_BOTTOM_RIGHT].Top) {
_grippers[Gripper.POSITION_TOP_LEFT].Cursor = Cursors.SizeWE;
_grippers[Gripper.POSITION_BOTTOM_RIGHT].Cursor = Cursors.SizeWE;
}
}
}
private void GripperMouseDown(object sender, MouseEventArgs e) {
Gripper originatingGripper = (Gripper)sender;
if (originatingGripper != _targetGripper) {
Status = EditStatus.RESIZING;
_boundsBeforeResize = new Rectangle(left, top, width, height);
_boundsAfterResize = new RectangleF(_boundsBeforeResize.Left, _boundsBeforeResize.Top, _boundsBeforeResize.Width, _boundsBeforeResize.Height);
} else {
Status = EditStatus.MOVING;
}
isMadeUndoable = false;
}
private void GripperMouseUp(object sender, MouseEventArgs e) {
Gripper originatingGripper = (Gripper)sender;
if (originatingGripper != _targetGripper) {
_boundsBeforeResize = Rectangle.Empty;
_boundsAfterResize = RectangleF.Empty;
isMadeUndoable = false;
}
Status = EditStatus.IDLE;
Invalidate();
}
private void GripperMouseMove(object sender, MouseEventArgs e) {
Invalidate();
Gripper originatingGripper = (Gripper)sender;
int absX = originatingGripper.Left + e.X;
int absY = originatingGripper.Top + e.Y;
if (originatingGripper == _targetGripper && Status.Equals(EditStatus.MOVING)) {
TargetGripperMove(absX, absY);
} else if (Status.Equals(EditStatus.RESIZING)) {
// check if we already made this undoable
if (!isMadeUndoable) {
// don't allow another undo until we are finished with this move
isMadeUndoable = true;
// Make undo-able
MakeBoundsChangeUndoable(false);
}
SuspendLayout();
// reset "workbench" rectangle to current bounds
_boundsAfterResize.X = _boundsBeforeResize.X;
_boundsAfterResize.Y = _boundsBeforeResize.Y;
_boundsAfterResize.Width = _boundsBeforeResize.Width;
_boundsAfterResize.Height = _boundsBeforeResize.Height;
// calculate scaled rectangle
ScaleHelper.Scale(ref _boundsAfterResize, originatingGripper.Position, new PointF(absX, absY), ScaleHelper.GetScaleOptions());
// apply scaled bounds to this DrawableContainer
ApplyBounds(_boundsAfterResize);
ResumeLayout();
}
Invalidate();
}
public bool hasFilters {
@ -558,38 +412,6 @@ namespace Greenshot.Drawing {
}
}
public virtual void ShowGrippers() {
if (_grippers != null) {
for (int i = 0; i < _grippers.Length; i++) {
if (_grippers[i].Enabled) {
_grippers[i].Show();
} else {
_grippers[i].Hide();
}
}
}
if (_targetGripper != null) {
if (_targetGripper.Enabled) {
_targetGripper.Show();
} else {
_targetGripper.Hide();
}
}
ResumeLayout();
}
public virtual void HideGrippers() {
SuspendLayout();
if (_grippers != null) {
for (int i = 0; i < _grippers.Length; i++) {
_grippers[i].Hide();
}
}
if (_targetGripper != null) {
_targetGripper.Hide();
}
}
public void ResizeTo(int width, int height, int anchorPosition) {
SuspendLayout();
Width = width;
@ -659,28 +481,6 @@ namespace Greenshot.Drawing {
}
protected virtual void SwitchParent(Surface newParent) {
// Target gripper
if (_parent != null && _targetGripper != null) {
_parent.Controls.Remove(_targetGripper);
}
// Normal grippers
if (_parent != null && _grippers != null) {
for (int i=0; i<_grippers.Length; i++) {
_parent.Controls.Remove(_grippers[i]);
}
} else if (_grippers == null) {
InitControls();
}
_parent = newParent;
// Target gripper
if (_parent != null && _targetGripper != null) {
_parent.Controls.Add(_targetGripper);
}
// Normal grippers
if (_grippers != null) {
_parent.Controls.AddRange(_grippers);
}
foreach(IFilter filter in Filters) {
filter.Parent = this;
}
@ -778,22 +578,13 @@ namespace Greenshot.Drawing {
SuspendLayout();
Point topLeft = new Point(Left, Top);
Point bottomRight = new Point(Left + Width, Top + Height);
Point[] points;
if (TargetGripper != null) {
points = new[] {topLeft, bottomRight, TargetGripper.Location};
} else {
points = new[] { topLeft, bottomRight };
}
Point[] points = new[] { topLeft, bottomRight };
matrix.TransformPoints(points);
Left = points[0].X;
Top = points[0].Y;
Width = points[1].X - points[0].X;
Height = points[1].Y - points[0].Y;
if (TargetGripper != null) {
TargetGripper.Location = points[points.Length-1];
}
ResumeLayout();
}