mirror of
https://github.com/greenshot/greenshot
synced 2025-07-30 03:30:02 -07:00
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:
parent
e9ab99c5ac
commit
31db071394
15 changed files with 643 additions and 349 deletions
232
Greenshot/Drawing/Adorners/GripperAdorner.cs
Normal file
232
Greenshot/Drawing/Adorners/GripperAdorner.cs
Normal file
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Helpers;
|
||||
using Greenshot.Plugin;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using Greenshot.Plugin.Drawing.Adorners;
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using System.Drawing.Drawing2D;
|
||||
|
||||
namespace Greenshot.Drawing.Adorners
|
||||
{
|
||||
/// <summary>
|
||||
/// This is the default "legacy" gripper adorner, not the one used for the tail in the speech-bubble
|
||||
/// </summary>
|
||||
public class GripperAdorner : IAdorner
|
||||
{
|
||||
private Rectangle _boundsBeforeResize = Rectangle.Empty;
|
||||
private RectangleF _boundsAfterResize = RectangleF.Empty;
|
||||
private EditStatus _editStatus;
|
||||
|
||||
public Positions Position { get; private set; }
|
||||
|
||||
public GripperAdorner(IDrawableContainer owner, Positions position)
|
||||
{
|
||||
Owner = owner;
|
||||
Position = position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cursor for when the mouse is over the adorner
|
||||
/// </summary>
|
||||
public Cursor Cursor
|
||||
{
|
||||
get
|
||||
{
|
||||
bool horizontalSwitched = Owner.Width < 0;
|
||||
switch (Position)
|
||||
{
|
||||
case Positions.TopLeft:
|
||||
case Positions.BottomRight:
|
||||
return horizontalSwitched ? Cursors.SizeNWSE : Cursors.SizeNESW;
|
||||
case Positions.TopRight:
|
||||
case Positions.BottomLeft:
|
||||
return horizontalSwitched ? Cursors.SizeNESW : Cursors.SizeNWSE;
|
||||
case Positions.MiddleLeft:
|
||||
case Positions.MiddleRight:
|
||||
return Cursors.SizeWE;
|
||||
case Positions.TopCenter:
|
||||
case Positions.BottomCenter:
|
||||
return Cursors.SizeNS;
|
||||
default:
|
||||
return Cursors.SizeAll;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IDrawableContainer Owner
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the point is inside the adorner
|
||||
/// </summary>
|
||||
/// <param name="point"></param>
|
||||
/// <returns></returns>
|
||||
public bool HitTest(Point point)
|
||||
{
|
||||
return Bounds.Contains(point);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the mouse down
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs"></param>
|
||||
public void MouseDown(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
_editStatus = EditStatus.RESIZING;
|
||||
_boundsBeforeResize = new Rectangle(Owner.Left, Owner.Top, Owner.Width, Owner.Height);
|
||||
_boundsAfterResize = _boundsBeforeResize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the mouse move
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs"></param>
|
||||
public void MouseMove(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
Owner.Invalidate();
|
||||
int absX = Owner.Left + mouseEventArgs.X;
|
||||
int absY = Owner.Top + mouseEventArgs.Y;
|
||||
|
||||
if (_editStatus.Equals(EditStatus.RESIZING))
|
||||
{
|
||||
Owner.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, Position, new PointF(absX, absY), ScaleHelper.GetScaleOptions());
|
||||
|
||||
// apply scaled bounds to this DrawableContainer
|
||||
Owner.ApplyBounds(_boundsAfterResize);
|
||||
|
||||
//ResumeLayout();
|
||||
Owner.DoLayout();
|
||||
}
|
||||
Owner.Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the mouse up
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs"></param>
|
||||
public void MouseUp(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
_editStatus = EditStatus.IDLE;
|
||||
Owner.Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the location of the adorner
|
||||
/// </summary>
|
||||
public Point Location {
|
||||
get
|
||||
{
|
||||
int x = 0,y = 0;
|
||||
switch (Position)
|
||||
{
|
||||
case Positions.TopLeft:
|
||||
x = Owner.Left;
|
||||
y = Owner.Top;
|
||||
break;
|
||||
case Positions.BottomLeft:
|
||||
x = Owner.Left;
|
||||
y = Owner.Top + Owner.Height;
|
||||
break;
|
||||
case Positions.MiddleLeft:
|
||||
x = Owner.Left;
|
||||
y = Owner.Top + (Owner.Height / 2);
|
||||
break;
|
||||
case Positions.TopCenter:
|
||||
x = Owner.Left + (Owner.Width / 2);
|
||||
y = Owner.Top;
|
||||
break;
|
||||
case Positions.BottomCenter:
|
||||
x = Owner.Left + (Owner.Width / 2);
|
||||
y = Owner.Top + Owner.Height;
|
||||
break;
|
||||
case Positions.TopRight:
|
||||
x = Owner.Left + Owner.Width;
|
||||
y = Owner.Top;
|
||||
break;
|
||||
case Positions.BottomRight:
|
||||
x = Owner.Left + Owner.Width;
|
||||
y = Owner.Top + Owner.Height;
|
||||
break;
|
||||
case Positions.MiddleRight:
|
||||
x = Owner.Left + Owner.Width;
|
||||
y = Owner.Top + (Owner.Height / 2);
|
||||
break;
|
||||
}
|
||||
return new Point(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the bounds of the Adorner
|
||||
/// </summary>
|
||||
public Rectangle Bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
Point location = Location;
|
||||
Size size = new Size(10, 10);
|
||||
return new Rectangle(location.X - (size.Width / 2), location.Y - (size.Height / 2), size.Width, size.Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw the adorner
|
||||
/// </summary>
|
||||
/// <param name="paintEventArgs">PaintEventArgs</param>
|
||||
public void Paint(PaintEventArgs paintEventArgs)
|
||||
{
|
||||
Graphics targetGraphics = paintEventArgs.Graphics;
|
||||
Rectangle clipRectangle = paintEventArgs.ClipRectangle;
|
||||
|
||||
var bounds = Bounds;
|
||||
targetGraphics.DrawRectangle(Pens.Black, bounds.X, bounds.Y, bounds.Width , bounds.Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// We ignore the Transform, as the coordinates are directly bound to those of the owner
|
||||
/// </summary>
|
||||
/// <param name="matrix"></param>
|
||||
public void Transform(Matrix matrix)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
177
Greenshot/Drawing/Adorners/TargetAdorner.cs
Normal file
177
Greenshot/Drawing/Adorners/TargetAdorner.cs
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using Greenshot.Plugin.Drawing.Adorners;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Greenshot.Drawing.Adorners
|
||||
{
|
||||
/// <summary>
|
||||
/// This implements the special "gripper" for the Speech-Bubble tail
|
||||
/// </summary>
|
||||
public class TargetAdorner : IAdorner
|
||||
{
|
||||
private EditStatus _editStatus;
|
||||
|
||||
public TargetAdorner(IDrawableContainer owner, Point location)
|
||||
{
|
||||
Owner = owner;
|
||||
Location = location;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the cursor for when the mouse is over the adorner
|
||||
/// </summary>
|
||||
public Cursor Cursor
|
||||
{
|
||||
get
|
||||
{
|
||||
return Cursors.SizeAll;
|
||||
}
|
||||
}
|
||||
|
||||
public IDrawableContainer Owner
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Test if the point is inside the adorner
|
||||
/// </summary>
|
||||
/// <param name="point"></param>
|
||||
/// <returns></returns>
|
||||
public bool HitTest(Point point)
|
||||
{
|
||||
return Bounds.Contains(point);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the mouse down
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs"></param>
|
||||
public void MouseDown(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
_editStatus = EditStatus.MOVING;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the mouse move
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs"></param>
|
||||
public void MouseMove(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
Owner.Invalidate();
|
||||
Point newGripperLocation = new Point(mouseEventArgs.X, mouseEventArgs.Y);
|
||||
Rectangle surfaceBounds = new Rectangle(0, 0, Owner.Parent.Width, Owner.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;
|
||||
}
|
||||
}
|
||||
|
||||
Location = newGripperLocation;
|
||||
Owner.Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handle the mouse up
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs"></param>
|
||||
public void MouseUp(object sender, MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
_editStatus = EditStatus.IDLE;
|
||||
Owner.Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the location of the adorner
|
||||
/// </summary>
|
||||
public Point Location
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return the bounds of the Adorner
|
||||
/// </summary>
|
||||
public Rectangle Bounds
|
||||
{
|
||||
get
|
||||
{
|
||||
Point location = Location;
|
||||
Size size = new Size(10, 10);
|
||||
return new Rectangle(location.X - (size.Width / 2), location.Y - (size.Height / 2), size.Width, size.Height);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draw the adorner
|
||||
/// </summary>
|
||||
/// <param name="paintEventArgs">PaintEventArgs</param>
|
||||
public void Paint(PaintEventArgs paintEventArgs)
|
||||
{
|
||||
Graphics targetGraphics = paintEventArgs.Graphics;
|
||||
Rectangle clipRectangle = paintEventArgs.ClipRectangle;
|
||||
|
||||
var bounds = Bounds;
|
||||
targetGraphics.DrawRectangle(Pens.Green, bounds.X, bounds.Y, bounds.Width, bounds.Height);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Made sure this adorner is transformed
|
||||
/// </summary>
|
||||
/// <param name="matrix">Matrix</param>
|
||||
public void Transform(Matrix matrix)
|
||||
{
|
||||
if (matrix == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Point[] points = new[] { Location };
|
||||
matrix.TransformPoints(points);
|
||||
Location = points[0];
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -171,26 +171,6 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides the grippers of all elements in the list.
|
||||
/// </summary>
|
||||
public void HideGrippers() {
|
||||
foreach(var dc in this) {
|
||||
dc.HideGrippers();
|
||||
dc.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the grippers of all elements in the list.
|
||||
/// </summary>
|
||||
public void ShowGrippers() {
|
||||
foreach(var dc in this) {
|
||||
dc.ShowGrippers();
|
||||
dc.Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether on of the elements is clickable at the given location
|
||||
/// </summary>
|
||||
|
|
|
@ -63,12 +63,7 @@ namespace Greenshot.Drawing {
|
|||
|
||||
|
||||
protected void Init() {
|
||||
if (_grippers != null) {
|
||||
for (int i = 0; i < _grippers.Length; i++) {
|
||||
_grippers[i].Enabled = false;
|
||||
_grippers[i].Visible = false;
|
||||
}
|
||||
}
|
||||
// TODO: Remove grippers
|
||||
}
|
||||
|
||||
public override void Transform(Matrix matrix) {
|
||||
|
@ -258,17 +253,6 @@ namespace Greenshot.Drawing {
|
|||
return freehandPath.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This is overriden to prevent the grippers to be modified.
|
||||
/// Might not be the best way...
|
||||
/// </summary>
|
||||
protected override void DoLayout() {
|
||||
}
|
||||
|
||||
public override void ShowGrippers() {
|
||||
ResumeLayout();
|
||||
}
|
||||
|
||||
public override bool ClickableAt(int x, int y) {
|
||||
bool returnValue = base.ClickableAt(x, y);
|
||||
if (returnValue) {
|
||||
|
|
|
@ -53,11 +53,7 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
protected void Init() {
|
||||
if (_grippers != null) {
|
||||
foreach (int index in new[] { 1, 2, 3, 5, 6, 7 }) {
|
||||
_grippers[index].Enabled = false;
|
||||
}
|
||||
}
|
||||
// TODO: Remove the unneeded grippers (1, 2, 3, 5, 6, 7)
|
||||
}
|
||||
|
||||
public override void Draw(Graphics graphics, RenderMode rm) {
|
||||
|
|
|
@ -19,38 +19,20 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Greenshot.Drawing {
|
||||
namespace Greenshot.Drawing
|
||||
{
|
||||
/// <summary>
|
||||
/// Grippers are the dragable edges of our containers
|
||||
/// Position
|
||||
/// </summary>
|
||||
public class Gripper : Label {
|
||||
/// <summary>
|
||||
/// Constants for anchor/gripper position:
|
||||
/// 0 1 2
|
||||
/// 7 3
|
||||
/// 6 5 4
|
||||
/// </summary>
|
||||
public const int POSITION_TOP_LEFT = 0;
|
||||
public const int POSITION_TOP_CENTER = 1;
|
||||
public const int POSITION_TOP_RIGHT = 2;
|
||||
public const int POSITION_MIDDLE_RIGHT = 3;
|
||||
public const int POSITION_BOTTOM_RIGHT = 4;
|
||||
public const int POSITION_BOTTOM_CENTER = 5;
|
||||
public const int POSITION_BOTTOM_LEFT = 6;
|
||||
public const int POSITION_MIDDLE_LEFT = 7;
|
||||
|
||||
public int Position {
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public Gripper() {
|
||||
Width = 5;
|
||||
Height = 5;
|
||||
BackColor = Color.Black;
|
||||
}
|
||||
public enum Positions : int
|
||||
{
|
||||
TopLeft = 0,
|
||||
TopCenter = 1,
|
||||
TopRight = 2,
|
||||
MiddleRight = 3,
|
||||
BottomRight = 4,
|
||||
BottomCenter = 5,
|
||||
BottomLeft = 6,
|
||||
MiddleLeft = 7
|
||||
}
|
||||
}
|
|
@ -118,7 +118,7 @@ namespace Greenshot.Drawing {
|
|||
|
||||
if (TargetGripper.Location != newGripperLocation) {
|
||||
Invalidate();
|
||||
TargetGripperMove(newGripperLocation.X, newGripperLocation.Y);
|
||||
TargetGripper.Location = newGripperLocation;
|
||||
Invalidate();
|
||||
}
|
||||
return returnValue;
|
||||
|
@ -180,7 +180,7 @@ namespace Greenshot.Drawing {
|
|||
private GraphicsPath CreateTail() {
|
||||
Rectangle rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height);
|
||||
|
||||
int tailLength = GeometryHelper.Distance2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetGripper.Left, TargetGripper.Top);
|
||||
int tailLength = GeometryHelper.Distance2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetGripper.Location.X, TargetGripper.Location.Y);
|
||||
int tailWidth = (Math.Abs(rect.Width) + Math.Abs(rect.Height)) / 20;
|
||||
|
||||
// This should fix a problem with the tail being to wide
|
||||
|
@ -192,7 +192,7 @@ namespace Greenshot.Drawing {
|
|||
tail.AddLine(tailWidth, 0, 0, -tailLength);
|
||||
tail.CloseFigure();
|
||||
|
||||
int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetGripper.Left, TargetGripper.Top);
|
||||
int tailAngle = 90 + (int)GeometryHelper.Angle2D(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2), TargetGripper.Location.X, TargetGripper.Location.Y);
|
||||
|
||||
using (Matrix tailMatrix = new Matrix()) {
|
||||
tailMatrix.Translate(rect.Left + (rect.Width / 2), rect.Top + (rect.Height / 2));
|
||||
|
|
|
@ -21,12 +21,14 @@
|
|||
|
||||
using Greenshot.Configuration;
|
||||
using Greenshot.Core;
|
||||
using Greenshot.Drawing.Adorners;
|
||||
using Greenshot.Drawing.Fields;
|
||||
using Greenshot.Helpers;
|
||||
using Greenshot.IniFile;
|
||||
using Greenshot.Memento;
|
||||
using Greenshot.Plugin;
|
||||
using Greenshot.Plugin.Drawing;
|
||||
using Greenshot.Plugin.Drawing.Adorners;
|
||||
using GreenshotPlugin.Controls;
|
||||
using GreenshotPlugin.Core;
|
||||
using log4net;
|
||||
|
@ -991,12 +993,45 @@ namespace Greenshot.Drawing {
|
|||
Invalidate();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if an adorner was "hit", and change the cursor if so
|
||||
/// </summary>
|
||||
/// <param name="mouseEventArgs">MouseEventArgs</param>
|
||||
/// <returns>IAdorner</returns>
|
||||
private IAdorner AdornersHitTest(MouseEventArgs mouseEventArgs)
|
||||
{
|
||||
foreach(IDrawableContainer drawableContainer in selectedElements)
|
||||
{
|
||||
foreach(IAdorner adorner in drawableContainer.Adorners)
|
||||
{
|
||||
if (adorner.HitTest(mouseEventArgs.Location))
|
||||
{
|
||||
if (adorner.Cursor != null)
|
||||
{
|
||||
Cursor = adorner.Cursor;
|
||||
}
|
||||
return adorner;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event handler is called when someone presses the mouse on a surface.
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SurfaceMouseDown(object sender, MouseEventArgs e) {
|
||||
|
||||
// Handle Adorners
|
||||
var adorner = AdornersHitTest(e);
|
||||
if (adorner != null)
|
||||
{
|
||||
adorner.MouseDown(sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
_mouseStart = e.Location;
|
||||
|
||||
// check contextmenu
|
||||
|
@ -1065,6 +1100,15 @@ namespace Greenshot.Drawing {
|
|||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SurfaceMouseUp(object sender, MouseEventArgs e) {
|
||||
|
||||
// Handle Adorners
|
||||
var adorner = AdornersHitTest(e);
|
||||
if (adorner != null)
|
||||
{
|
||||
adorner.MouseUp(sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
Point currentMouse = new Point(e.X, e.Y);
|
||||
|
||||
_elements.Status = EditStatus.IDLE;
|
||||
|
@ -1098,7 +1142,7 @@ namespace Greenshot.Drawing {
|
|||
}
|
||||
|
||||
if (selectedElements.Count > 0) {
|
||||
selectedElements.ShowGrippers();
|
||||
selectedElements.Invalidate();
|
||||
selectedElements.Selected = true;
|
||||
}
|
||||
|
||||
|
@ -1126,6 +1170,14 @@ namespace Greenshot.Drawing {
|
|||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SurfaceMouseMove(object sender, MouseEventArgs e) {
|
||||
// Handle Adorners
|
||||
var adorner = AdornersHitTest(e);
|
||||
if (adorner != null)
|
||||
{
|
||||
adorner.MouseMove(sender, e);
|
||||
return;
|
||||
}
|
||||
|
||||
Point currentMouse = e.Location;
|
||||
|
||||
if (DrawingMode != DrawingModes.None) {
|
||||
|
@ -1137,7 +1189,7 @@ namespace Greenshot.Drawing {
|
|||
if (_mouseDown) {
|
||||
if (_mouseDownElement != null) { // an element is currently dragged
|
||||
_mouseDownElement.Invalidate();
|
||||
selectedElements.HideGrippers();
|
||||
selectedElements.Invalidate();
|
||||
// Move the element
|
||||
if (_mouseDownElement.Selected) {
|
||||
if (!_isSurfaceMoveMadeUndoable) {
|
||||
|
@ -1208,10 +1260,10 @@ namespace Greenshot.Drawing {
|
|||
/// This is the event handler for the Paint Event, try to draw as little as possible!
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SurfacePaint(object sender, PaintEventArgs e) {
|
||||
Graphics targetGraphics = e.Graphics;
|
||||
Rectangle clipRectangle = e.ClipRectangle;
|
||||
/// <param name="paintEventArgs">PaintEventArgs</param>
|
||||
void SurfacePaint(object sender, PaintEventArgs paintEventArgs) {
|
||||
Graphics targetGraphics = paintEventArgs.Graphics;
|
||||
Rectangle clipRectangle = paintEventArgs.ClipRectangle;
|
||||
if (Rectangle.Empty.Equals(clipRectangle)) {
|
||||
LOG.Debug("Empty cliprectangle??");
|
||||
return;
|
||||
|
@ -1246,6 +1298,15 @@ namespace Greenshot.Drawing {
|
|||
targetGraphics.DrawImage(Image, clipRectangle, clipRectangle, GraphicsUnit.Pixel);
|
||||
_elements.Draw(targetGraphics, null, RenderMode.EDIT, clipRectangle);
|
||||
}
|
||||
|
||||
// Draw adorners last
|
||||
foreach(var drawableContainer in selectedElements)
|
||||
{
|
||||
foreach(var adorner in drawableContainer.Adorners)
|
||||
{
|
||||
adorner.Paint(paintEventArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawBackground(Graphics targetGraphics, Rectangle clipRectangle) {
|
||||
|
@ -1531,9 +1592,9 @@ namespace Greenshot.Drawing {
|
|||
/// </summary>
|
||||
/// <param name="container"></param>
|
||||
public void DeselectElement(IDrawableContainer container) {
|
||||
container.HideGrippers();
|
||||
container.Selected = false;
|
||||
selectedElements.Remove(container);
|
||||
container.Invalidate();
|
||||
FieldAggregator.UnbindElement(container);
|
||||
if (_movingElementChanged != null) {
|
||||
SurfaceElementEventArgs eventArgs = new SurfaceElementEventArgs();
|
||||
|
@ -1549,10 +1610,9 @@ namespace Greenshot.Drawing {
|
|||
if (HasSelectedElements) {
|
||||
while(selectedElements.Count > 0) {
|
||||
IDrawableContainer element = selectedElements[0];
|
||||
element.Invalidate();
|
||||
element.HideGrippers();
|
||||
element.Selected = false;
|
||||
selectedElements.Remove(element);
|
||||
element.Invalidate();
|
||||
FieldAggregator.UnbindElement(element);
|
||||
}
|
||||
if (_movingElementChanged != null) {
|
||||
|
@ -1570,7 +1630,6 @@ namespace Greenshot.Drawing {
|
|||
public void SelectElement(IDrawableContainer container) {
|
||||
if (!selectedElements.Contains(container)) {
|
||||
selectedElements.Add(container);
|
||||
container.ShowGrippers();
|
||||
container.Selected = true;
|
||||
FieldAggregator.BindElement(container);
|
||||
if (_movingElementChanged != null) {
|
||||
|
|
|
@ -75,7 +75,10 @@
|
|||
<Compile Include="Destinations\FileWithDialogDestination.cs" />
|
||||
<Compile Include="Destinations\PickerDestination.cs" />
|
||||
<Compile Include="Destinations\PrinterDestination.cs" />
|
||||
<Compile Include="Drawing\Adorners\GripperAdorner.cs" />
|
||||
<Compile Include="Drawing\Adorners\TargetAdorner.cs" />
|
||||
<Compile Include="Drawing\ArrowContainer.cs" />
|
||||
<Compile Include="Drawing\Positions.cs" />
|
||||
<Compile Include="Drawing\StepLabelContainer.cs" />
|
||||
<Compile Include="Drawing\ImageContainer.cs" />
|
||||
<Compile Include="Drawing\CropContainer.cs" />
|
||||
|
@ -101,9 +104,6 @@
|
|||
<Compile Include="Drawing\Filters\MagnifierFilter.cs" />
|
||||
<Compile Include="Drawing\Filters\PixelizationFilter.cs" />
|
||||
<Compile Include="Drawing\Filters\BlurFilter.cs" />
|
||||
<Compile Include="Drawing\Gripper.cs">
|
||||
<SubType>Component</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Drawing\HighlightContainer.cs" />
|
||||
<Compile Include="Drawing\IconContainer.cs" />
|
||||
<Compile Include="Drawing\LineContainer.cs" />
|
||||
|
|
|
@ -119,15 +119,15 @@ namespace Greenshot.Helpers {
|
|||
return GetAlignedRectangle(newRect, targetRect, alignment);
|
||||
}
|
||||
|
||||
public static void RationalScale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
public static void RationalScale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Rational);
|
||||
}
|
||||
|
||||
public static void CenteredScale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
public static void CenteredScale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Centered);
|
||||
}
|
||||
|
||||
public static void Scale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
public static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, null);
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ namespace Greenshot.Helpers {
|
|||
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
|
||||
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
|
||||
/// <param name="options">ScaleOptions to use when scaling</param>
|
||||
public static void Scale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords, ScaleOptions? options) {
|
||||
public static void Scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords, ScaleOptions? options) {
|
||||
if(options == null) {
|
||||
options = GetScaleOptions();
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ namespace Greenshot.Helpers {
|
|||
resizeHandleCoords.X -= 2 * (resizeHandleCoords.X - rectCenterX);
|
||||
resizeHandleCoords.Y -= 2 * (resizeHandleCoords.Y - rectCenterY);
|
||||
// scale again with opposing handle and mirrored coordinates
|
||||
resizeHandlePosition = (resizeHandlePosition + 4) % 8;
|
||||
resizeHandlePosition = (Positions)((((int)resizeHandlePosition) + 4) % 8);
|
||||
scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
|
||||
} else {
|
||||
scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
|
||||
|
@ -171,47 +171,47 @@ namespace Greenshot.Helpers {
|
|||
/// <param name="originalRectangle">bounds of the current rectangle, scaled values will be written to this reference</param>
|
||||
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
|
||||
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
|
||||
private static void scale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
private static void scale(ref RectangleF originalRectangle, Positions resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
switch(resizeHandlePosition) {
|
||||
|
||||
case Gripper.POSITION_TOP_LEFT:
|
||||
case Positions.TopLeft:
|
||||
originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
|
||||
originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
|
||||
originalRectangle.X = resizeHandleCoords.X;
|
||||
originalRectangle.Y = resizeHandleCoords.Y;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_TOP_CENTER:
|
||||
case Positions.TopCenter:
|
||||
originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
|
||||
originalRectangle.Y = resizeHandleCoords.Y;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_TOP_RIGHT:
|
||||
case Positions.TopRight:
|
||||
originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
|
||||
originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
|
||||
originalRectangle.Y = resizeHandleCoords.Y;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_MIDDLE_LEFT:
|
||||
case Positions.MiddleLeft:
|
||||
originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
|
||||
originalRectangle.X = resizeHandleCoords.X;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_MIDDLE_RIGHT:
|
||||
case Positions.MiddleRight:
|
||||
originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_LEFT:
|
||||
case Positions.BottomLeft:
|
||||
originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
|
||||
originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
originalRectangle.X = resizeHandleCoords.X;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_CENTER:
|
||||
case Positions.BottomCenter:
|
||||
originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_RIGHT:
|
||||
case Positions.BottomRight:
|
||||
originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
|
||||
originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
break;
|
||||
|
@ -226,14 +226,14 @@ namespace Greenshot.Helpers {
|
|||
/// Adjusts resizeHandleCoords so that aspect ratio is kept after resizing a given rectangle with provided arguments
|
||||
/// </summary>
|
||||
/// <param name="originalRectangle">bounds of the current rectangle</param>
|
||||
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
|
||||
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see Position</param>
|
||||
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper, adjusted coordinates will be written to this reference</param>
|
||||
private static void adjustCoordsForRationalScale(RectangleF originalRectangle, int resizeHandlePosition, ref PointF resizeHandleCoords) {
|
||||
private static void adjustCoordsForRationalScale(RectangleF originalRectangle, Positions resizeHandlePosition, ref PointF resizeHandleCoords) {
|
||||
float originalRatio = originalRectangle.Width / originalRectangle.Height;
|
||||
float newWidth, newHeight, newRatio;
|
||||
switch(resizeHandlePosition) {
|
||||
|
||||
case Gripper.POSITION_TOP_LEFT:
|
||||
case Positions.TopLeft:
|
||||
newWidth = originalRectangle.Right - resizeHandleCoords.X;
|
||||
newHeight = originalRectangle.Bottom - resizeHandleCoords.Y;
|
||||
newRatio = newWidth / newHeight;
|
||||
|
@ -244,7 +244,7 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_TOP_RIGHT:
|
||||
case Positions.TopRight:
|
||||
newWidth = resizeHandleCoords.X - originalRectangle.Left;
|
||||
newHeight = originalRectangle.Bottom - resizeHandleCoords.Y;
|
||||
newRatio = newWidth / newHeight;
|
||||
|
@ -255,7 +255,7 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_LEFT:
|
||||
case Positions.BottomLeft:
|
||||
newWidth = originalRectangle.Right - resizeHandleCoords.X;
|
||||
newHeight = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
newRatio = newWidth / newHeight;
|
||||
|
@ -266,7 +266,7 @@ namespace Greenshot.Helpers {
|
|||
}
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_RIGHT:
|
||||
case Positions.BottomRight:
|
||||
newWidth = resizeHandleCoords.X - originalRectangle.Left;
|
||||
newHeight = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
newRatio = newWidth / newHeight;
|
||||
|
@ -285,10 +285,10 @@ namespace Greenshot.Helpers {
|
|||
|
||||
public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) {
|
||||
|
||||
Scale(boundsBeforeResize, Gripper.POSITION_TOP_LEFT, cursorX, cursorY, ref boundsAfterResize, angleRoundBehavior);
|
||||
Scale(boundsBeforeResize, Positions.TopLeft, cursorX, cursorY, ref boundsAfterResize, angleRoundBehavior);
|
||||
}
|
||||
|
||||
public static void Scale(Rectangle boundsBeforeResize, int gripperPosition, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) {
|
||||
public static void Scale(Rectangle boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) {
|
||||
|
||||
ScaleOptions opts = GetScaleOptions();
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
<Compile Include="IEInterop\IHTMLWindow3.cs" />
|
||||
<Compile Include="IEInterop\IHTMLWindow4.cs" />
|
||||
<Compile Include="IEInterop\IWebBrowser2.cs" />
|
||||
<Compile Include="Interfaces\Drawing\Adorners\IAdorner.cs" />
|
||||
<Compile Include="Interop\Base.cs" />
|
||||
<Compile Include="Interop\ComProgIdAttribute.cs" />
|
||||
<Compile Include="Interop\COMWrapper.cs" />
|
||||
|
|
81
GreenshotPlugin/Interfaces/Drawing/Adorners/IAdorner.cs
Normal file
81
GreenshotPlugin/Interfaces/Drawing/Adorners/IAdorner.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Greenshot - a free and open source screenshot tool
|
||||
* Copyright (C) 2007-2015 Thomas Braun, Jens Klingen, Robin Krom
|
||||
*
|
||||
* For more information see: http://getgreenshot.org/
|
||||
* The Greenshot project is hosted on Sourceforge: http://sourceforge.net/projects/greenshot/
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using System.Drawing;
|
||||
using System.Drawing.Drawing2D;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Greenshot.Plugin.Drawing.Adorners
|
||||
{
|
||||
public interface IAdorner
|
||||
{
|
||||
/// <summary>
|
||||
/// The owner of this adorner
|
||||
/// </summary>
|
||||
IDrawableContainer Owner { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Is the current point "over" the Adorner?
|
||||
/// If this is the case, the
|
||||
/// </summary>
|
||||
/// <param name="point">Point to test</param>
|
||||
/// <returns>true if so</returns>
|
||||
bool HitTest(Point point);
|
||||
|
||||
/// <summary>
|
||||
/// Handle the MouseDown event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs">MouseEventArgs</param>
|
||||
void MouseDown(object sender, MouseEventArgs mouseEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Handle the MouseUp event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs">MouseEventArgs</param>
|
||||
void MouseUp(object sender, MouseEventArgs mouseEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Handle the MouseMove event
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="mouseEventArgs">MouseEventArgs</param>
|
||||
void MouseMove(object sender, MouseEventArgs mouseEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cursor that should be displayed for this behavior.
|
||||
/// </summary>
|
||||
Cursor Cursor { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Draw the adorner
|
||||
/// </summary>
|
||||
/// <param name="paintEventArgs">PaintEventArgs</param>
|
||||
void Paint(PaintEventArgs paintEventArgs);
|
||||
|
||||
/// <summary>
|
||||
/// Called if the owner is transformed
|
||||
/// </summary>
|
||||
/// <param name="matrix">Matrix</param>
|
||||
void Transform(Matrix matrix);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,8 @@ using System.Drawing.Drawing2D;
|
|||
using System.Drawing.Imaging;
|
||||
using System.Windows.Forms;
|
||||
using System.ComponentModel;
|
||||
using System.Collections.Generic;
|
||||
using Greenshot.Plugin.Drawing.Adorners;
|
||||
|
||||
namespace Greenshot.Plugin.Drawing {
|
||||
public enum RenderMode {EDIT, EXPORT};
|
||||
|
@ -74,6 +76,10 @@ namespace Greenshot.Plugin.Drawing {
|
|||
get;
|
||||
}
|
||||
|
||||
void ApplyBounds(RectangleF newBounds);
|
||||
|
||||
void DoLayout();
|
||||
|
||||
bool hasFilters {
|
||||
get;
|
||||
}
|
||||
|
@ -85,8 +91,6 @@ namespace Greenshot.Plugin.Drawing {
|
|||
void AlignToParent(HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment);
|
||||
void Invalidate();
|
||||
bool ClickableAt(int x, int y);
|
||||
void HideGrippers();
|
||||
void ShowGrippers();
|
||||
void MoveBy(int x, int y);
|
||||
void Transform(Matrix matrix);
|
||||
bool HandleMouseDown(int x, int y);
|
||||
|
@ -97,6 +101,11 @@ namespace Greenshot.Plugin.Drawing {
|
|||
EditStatus DefaultEditMode {
|
||||
get;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Available adorners for the DrawableContainer
|
||||
/// </summary>
|
||||
IList<IAdorner> Adorners { get; }
|
||||
}
|
||||
|
||||
public interface ITextContainer: IDrawableContainer {
|
||||
|
|
|
@ -198,5 +198,7 @@ namespace Greenshot.Plugin {
|
|||
get;
|
||||
set;
|
||||
}
|
||||
int Width { get; }
|
||||
int Height { get; }
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue