/src/tools/MoveToolBase.cs
C# | 1004 lines | 790 code | 189 blank | 25 comment | 90 complexity | 7304efc7e78712bc4ab28e27b5b8bb8a MD5 | raw file
- /////////////////////////////////////////////////////////////////////////////////
- // Paint.NET //
- // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
- // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
- // See src/Resources/Files/License.txt for full licensing and attribution //
- // details. //
- // . //
- /////////////////////////////////////////////////////////////////////////////////
-
- using PaintDotNet.Base;
- using PaintDotNet.HistoryMementos;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Runtime.Serialization;
- using System.Text;
- using System.Windows.Forms;
-
- namespace PaintDotNet.Tools
- {
- internal abstract class MoveToolBase
- : Tool
- {
- protected Cursor MoveToolCursor;
- protected bool DontDrop; // so that OnSelectionChanging() can tell who is raising the event ... don't drop the pixels if WE caused the event
- protected float AngleDelta;
- protected MoveNubRenderer[] MoveNubs;
- protected RotateNubRenderer RotateNub;
- protected bool Tracking;
- protected Context context;
- protected bool hostShouldShowAngle;
- protected float hostAngle;
- protected List<HistoryMemento> CurrentHistoryMementos = new List<HistoryMemento>();
- protected bool deactivateOnLayerChange = true;
- protected bool EnableOutline = true;
-
- public override bool DeactivateOnLayerChange
- {
- get
- {
- return deactivateOnLayerChange;
- }
- }
-
- protected enum Mode
- {
- Translate,
- Scale,
- Rotate
- }
-
- // Corresponds to array positions in moveNubs for easy mapping between the two
- protected enum Edge
- {
- TopLeft = 0,
- Top = 1,
- TopRight = 2,
- Right = 3,
- BottomRight = 4,
- Bottom = 5,
- BottomLeft = 6,
- Left = 7,
- None = 99
- }
-
- [Serializable]
- protected class Context
- : ICloneable,
- ISerializable,
- IDisposable
- {
- public bool Lifted;
- public Guid SeriesGuid;
- public Matrix BaseTransform; // a copy of the selection's interim transform at the time of mouse-down
- public Matrix LiftTransform; // a copy of the selection's interim transform at the time of lifting
- public Matrix DeltaTransform; // the transformations made since lifting
- public RectangleF LiftedBounds;
- public RectangleF StartBounds;
- public float StartAngle;
- public PdnGraphicsPath StartPath;
- public Mode CurrentMode;
- public Edge StartEdge;
- public Point StartMouseXY;
- public Point Offset;
-
- private static float[] GetMatrixElements(Matrix m)
- {
- return m == null ? null : m.Elements;
- }
-
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("lifted", Lifted);
- info.AddValue("seriesGuid", SeriesGuid);
- info.AddValue("baseTransform", GetMatrixElements(BaseTransform));
- info.AddValue("deltaTransform", GetMatrixElements(DeltaTransform));
- info.AddValue("liftTransform", GetMatrixElements(LiftTransform));
- info.AddValue("liftedBounds", LiftedBounds);
- info.AddValue("startBounds", StartBounds);
- info.AddValue("startAngle", StartAngle);
- info.AddValue("startPath", StartPath);
- info.AddValue("currentMode", CurrentMode);
- info.AddValue("startEdge", StartEdge);
- info.AddValue("startMouseXY", StartMouseXY);
- info.AddValue("offset", Offset);
- }
-
- private static Matrix ReadMatrix(SerializationInfo info, string name)
- {
- var e = (float[])info.GetValue(name, typeof(float[]));
-
- Matrix m = e == null ? null : new Matrix(e[0], e[1], e[2], e[3], e[4], e[5]);
-
- return m;
- }
-
- public Context(SerializationInfo info, StreamingContext context)
- {
- Lifted = (bool)info.GetValue("lifted", typeof(bool));
- SeriesGuid = (Guid)info.GetValue("seriesGuid", typeof(Guid));
- BaseTransform = ReadMatrix(info, "baseTransform");
- DeltaTransform = ReadMatrix(info, "deltaTransform");
- LiftTransform = ReadMatrix(info, "liftTransform");
- LiftedBounds = (RectangleF)info.GetValue("liftedBounds", typeof(RectangleF));
- StartBounds = (RectangleF)info.GetValue("startBounds", typeof(RectangleF));
- StartAngle = (float)info.GetValue("startAngle", typeof(float));
- StartPath = (PdnGraphicsPath)info.GetValue("startPath", typeof(PdnGraphicsPath));
- CurrentMode = (Mode)info.GetValue("currentMode", typeof(Mode));
- StartEdge = (Edge)info.GetValue("startEdge", typeof(Edge));
- StartMouseXY = (Point)info.GetValue("startMouseXY", typeof(Point));
- Offset = (Point)info.GetValue("offset", typeof(Point));
- }
-
- public Context()
- {
- }
-
- public Context(Context cloneMe)
- {
- Lifted = cloneMe.Lifted;
- SeriesGuid = cloneMe.SeriesGuid;
-
- if (cloneMe.BaseTransform != null)
- {
- BaseTransform = cloneMe.BaseTransform.Clone();
- }
-
- if (cloneMe.DeltaTransform != null)
- {
- DeltaTransform = cloneMe.DeltaTransform.Clone();
- }
-
- if (cloneMe.LiftTransform != null)
- {
- LiftTransform = cloneMe.LiftTransform.Clone();
- }
-
- LiftedBounds = cloneMe.LiftedBounds;
- StartBounds = cloneMe.StartBounds;
- StartAngle = cloneMe.StartAngle;
-
- if (cloneMe.StartPath != null)
- {
- StartPath = cloneMe.StartPath.Clone();
- }
-
- CurrentMode = cloneMe.CurrentMode;
- StartEdge = cloneMe.StartEdge;
-
- StartMouseXY = cloneMe.StartMouseXY;
- Offset = cloneMe.Offset;
- }
-
- ~Context()
- {
- Dispose(false);
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (!disposing) return;
- if (BaseTransform != null)
- {
- BaseTransform.Dispose();
- BaseTransform = null;
- }
-
- if (DeltaTransform != null)
- {
- DeltaTransform.Dispose();
- DeltaTransform = null;
- }
-
- if (LiftTransform != null)
- {
- LiftTransform.Dispose();
- LiftTransform = null;
- }
-
- if (StartPath == null) return;
- StartPath.Dispose();
- StartPath = null;
- }
-
- public virtual object Clone()
- {
- return new Context(this);
- }
- }
-
- protected class CompoundToolHistoryMemento
- : ToolHistoryMemento
- {
- public CompoundHistoryMemento CompoundHistoryMemento { get; private set; }
-
- protected override HistoryMemento OnToolUndo()
- {
- var chm = (CompoundHistoryMemento)CompoundHistoryMemento.PerformUndo();
- var cthm = new CompoundToolHistoryMemento(chm, DocumentWorkspace, Name, Image);
- return cthm;
- }
-
- public CompoundToolHistoryMemento(CompoundHistoryMemento chm, DocumentWorkspace documentWorkspace, string name, ImageResource image)
- : base(documentWorkspace, name, image)
- {
- CompoundHistoryMemento = chm;
- }
- }
-
- public bool HostShouldShowAngle
- {
- get
- {
- return hostShouldShowAngle;
- }
- }
-
- public float HostAngle
- {
- get
- {
- return hostAngle;
- }
- }
-
- protected void DestroyNubs()
- {
- if (MoveNubs != null)
- {
- for (int i = 0; i < MoveNubs.Length; ++i)
- {
- RendererList.Remove(MoveNubs[i]);
- MoveNubs[i].Dispose();
- MoveNubs[i] = null;
- }
-
- MoveNubs = null;
- }
-
- if (RotateNub == null) return;
- RendererList.Remove(RotateNub);
- RotateNub.Dispose();
- RotateNub = null;
- }
-
- protected PointF GetEdgeVector(Edge edge)
- {
- PointF u;
- switch (edge)
- {
- case Edge.TopLeft:
- u = new PointF(-1, -1);
- break;
-
- case Edge.Top:
- u = new PointF(0, -1);
- break;
-
- case Edge.TopRight:
- u = new PointF(1, -1);
- break;
-
- case Edge.Left:
- u = new PointF(-1, 0);
- break;
-
- case Edge.Right:
- u = new PointF(1, 0);
- break;
-
- case Edge.BottomLeft:
- u = new PointF(-1, 1);
- break;
-
- case Edge.BottomRight:
- u = new PointF(1, 1);
- break;
-
- case Edge.Bottom:
- u = new PointF(0, 1);
- break;
-
- default:
- throw new InvalidEnumArgumentException();
- }
-
- return u;
- }
-
- protected void DetermineMoveMode(MouseEventArgs e, out Mode mode, out Edge edge)
- {
- mode = Mode.Translate;
- edge = Edge.None;
-
- if (e.Button == MouseButtons.Right)
- {
- mode = Mode.Rotate;
- }
- else
- {
- float minDistance = float.MaxValue;
- var mousePt = new Point(e.X, e.Y);
-
- for (int i = 0; i < MoveNubs.Length; ++i)
- {
- MoveNubRenderer nub = MoveNubs[i];
-
- if (!nub.IsPointTouching(mousePt, true)) continue;
- float distance = Utility.Distance(mousePt, nub.Location);
-
- if (distance >= minDistance) continue;
- minDistance = distance;
- mode = Mode.Scale;
- edge = (Edge)i;
- }
- }
-
- return;
- }
-
- protected override void OnPulse()
- {
- if (MoveNubs != null)
- {
- for (int i = 0; i < MoveNubs.Length; ++i)
- {
- // Oscillate between 25% and 100% alpha over a period of 2 seconds
- // Alpha value of 100% is sustained for a large duration of this period
- const int period = 10000 * 2000; // 10000 ticks per ms, 2000ms per period
- long tick = (DateTime.Now.Ticks % period) + (i * (period / MoveNubs.Length));
- double sin = Math.Sin(((double)tick / (double)period) * (2.0 * Math.PI));
- // sin is [-1, +1]
-
- sin = Math.Min(0.5, sin);
- // sin is [-1, +0.5]
-
- sin += 1.0;
- // sin is [0, 1.5]
-
- sin /= 2.0;
- // sin is [0, 0.75]
-
- sin += 0.25;
- // sin is [0.25, 1]
-
- var newAlpha = (int)(sin * 255.0);
- int clampedAlpha = Utility.Clamp(newAlpha, 0, 255);
- MoveNubs[i].Alpha = clampedAlpha;
- }
- }
-
- base.OnPulse();
- }
-
- protected void PositionNubs(Mode currentMode)
- {
- if (MoveNubs == null)
- {
- MoveNubs = new MoveNubRenderer[8];
-
- for (int i = 0; i < MoveNubs.Length; ++i)
- {
- MoveNubs[i] = new MoveNubRenderer(RendererList);
- RendererList.Add(MoveNubs[i], false);
- }
-
- RectangleF bounds = Selection.GetBoundsF(false);
-
- MoveNubs[(int)Edge.TopLeft].Location = new PointF(bounds.Left, bounds.Top);
- MoveNubs[(int)Edge.TopLeft].Shape = MoveNubShape.Circle;
-
- MoveNubs[(int)Edge.Top].Location = new PointF((bounds.Left + bounds.Right) / 2.0f, bounds.Top);
-
- MoveNubs[(int)Edge.TopRight].Location = new PointF(bounds.Right, bounds.Top);
- MoveNubs[(int)Edge.TopRight].Shape = MoveNubShape.Circle;
-
- MoveNubs[(int)Edge.Left].Location = new PointF(bounds.Left, (bounds.Top + bounds.Bottom) / 2.0f);
- MoveNubs[(int)Edge.Right].Location = new PointF(bounds.Right, (bounds.Top + bounds.Bottom) / 2.0f);
-
- MoveNubs[(int)Edge.BottomLeft].Location = new PointF(bounds.Left, bounds.Bottom);
- MoveNubs[(int)Edge.BottomLeft].Shape = MoveNubShape.Circle;
-
- MoveNubs[(int)Edge.Bottom].Location = new PointF((bounds.Left + bounds.Right) / 2.0f, bounds.Bottom);
-
- MoveNubs[(int)Edge.BottomRight].Location = new PointF(bounds.Right, bounds.Bottom);
- MoveNubs[(int)Edge.BottomRight].Shape = MoveNubShape.Circle;
- }
-
- if (RotateNub == null)
- {
- RotateNub = new RotateNubRenderer(RendererList) {Visible = false};
- RendererList.Add(RotateNub, false);
- }
-
- if (Selection.IsEmpty)
- {
- foreach (MoveNubRenderer nub in MoveNubs)
- {
- nub.Visible = false;
- }
-
- RotateNub.Visible = false;
- }
- else
- {
- foreach (MoveNubRenderer nub in MoveNubs)
- {
- nub.Visible = !Tracking || currentMode == Mode.Scale;
- nub.Transform = Selection.GetInterimTransformReadOnly();
- }
- }
- }
-
- protected void HideNubs()
- {
- if (MoveNubs != null)
- {
- foreach (MoveNubRenderer sbr in MoveNubs)
- {
- sbr.Visible = false;
- }
- }
-
- if (RotateNub != null)
- {
- RotateNub.Visible = false;
- }
- }
-
- protected Edge FlipEdgeVertically(Edge flipMe)
- {
- Edge flippedEdge;
-
- switch (flipMe)
- {
- default:
- throw new InvalidEnumArgumentException();
-
- case Edge.Bottom:
- flippedEdge = Edge.Top;
- break;
-
- case Edge.BottomLeft:
- flippedEdge = Edge.TopLeft;
- break;
-
- case Edge.BottomRight:
- flippedEdge = Edge.TopRight;
- break;
-
- case Edge.Left:
- flippedEdge = Edge.Left;
- break;
-
- case Edge.None:
- flippedEdge = Edge.None;
- break;
-
- case Edge.Right:
- flippedEdge = Edge.Right;
- break;
-
- case Edge.Top:
- flippedEdge = Edge.Bottom;
- break;
-
- case Edge.TopLeft:
- flippedEdge = Edge.BottomLeft;
- break;
-
- case Edge.TopRight:
- flippedEdge = Edge.BottomRight;
- break;
- }
-
- return flippedEdge;
- }
-
-
- // Constrains the given width and height to the aspect ratio of liftedBounds
- protected void ConstrainScaling(RectangleF liftedBounds, float startWidth, float startHeight,
- float newWidth, float newHeight, out float newXScale, out float newYScale)
- {
- float hRatio = newWidth / liftedBounds.Width;
- float vRatio = newHeight / liftedBounds.Height;
-
- float bestScale = Math.Min(hRatio, vRatio);
- float bestWidth = liftedBounds.Width * bestScale;
- float bestHeight = liftedBounds.Height * bestScale;
-
- newXScale = bestWidth / startWidth;
- newYScale = bestHeight / startHeight;
- }
-
- // Constrains to nearest 15 degree angle
- protected float ConstrainAngle(float angle)
- {
- while (angle < 0)
- {
- angle += 360.0f;
- }
-
- var iangle = (int)angle;
- int lowerBound = (iangle / 15) * 15;
- int upperBound = lowerBound + 15;
- float lowerDiff = Math.Abs(angle - lowerBound);
- float upperDiff = Math.Abs(angle - upperBound);
-
- float newAngle = lowerDiff < upperDiff ? lowerBound : upperBound;
-
- if (newAngle > 180.0f)
- {
- newAngle -= 360.0f;
- }
-
- return newAngle;
- }
-
- protected override void OnKeyPress(Keys key)
- {
- if (!Tracking)
- {
- int dx = 0;
- int dy = 0;
-
- switch ((key & Keys.KeyCode))
- {
- case Keys.Left:
- dx = -1;
- break;
- case Keys.Right:
- dx = +1;
- break;
- case Keys.Up:
- dy = -1;
- break;
- case Keys.Down:
- dy = +1;
- break;
- }
-
- if ((key & Keys.Control) != Keys.None)
- {
- dx *= 10;
- dy *= 10;
- }
-
- // Simulate moving the selection
- if (dx != 0 || dy != 0)
- {
- Point pos = Cursor.Position;
- var docPos = new Point(-70000, -70000);
- var newDocPos = new Point(docPos.X + dx, docPos.Y + dy);
- OnMouseDown(new MouseEventArgs(MouseButtons.Left, 0, docPos.X, docPos.Y, 0));
- OnMouseMove(new MouseEventArgs(MouseButtons.Left, 0, newDocPos.X, newDocPos.Y, 0));
- OnMouseUp(new MouseEventArgs(MouseButtons.Left, 0, newDocPos.X, newDocPos.Y, 0));
- }
- }
- else
- {
- base.OnKeyPress(key);
- }
- }
-
- protected abstract void OnLift(MouseEventArgs e);
- protected abstract void Drop();
- protected abstract void PreRender();
- protected abstract void Render(Point newOffset, bool useNewOffset);
- protected abstract void PushContextHistoryMemento();
-
- protected void Lift(MouseEventArgs e)
- {
- PushContextHistoryMemento();
-
- context.SeriesGuid = Guid.NewGuid();
- DetermineMoveMode(e, out context.CurrentMode, out context.StartEdge);
-
- // lift!
- context.StartBounds = context.LiftedBounds;
- context.LiftedBounds = Selection.GetBoundsF(false);
- context.StartMouseXY = new Point(e.X, e.Y);
- context.Offset = new Point(0, 0);
- context.StartAngle = 0.0f;
- context.Lifted = true;
- context.LiftTransform = Selection.GetCumulativeTransformCopy();
-
- OnLift(e);
-
- PositionNubs(context.CurrentMode);
- }
-
- protected override void OnMouseDown(MouseEventArgs e)
- {
- base.OnMouseDown(e);
-
- if (Tracking)
- {
- return;
- }
-
- bool determinedMoveMode = false;
- Mode newMode = Mode.Translate;
- Edge newEdge = Edge.None;
-
- if (Selection.IsEmpty)
- {
- var shm = new SelectionHistoryMemento(
- HistoryFunctions.SelectAllFunction.StaticName,
- PdnResources.GetImageResource("Icons.MenuEditSelectAllIcon.png"),
- DocumentWorkspace);
-
- DocumentWorkspace.History.PushNewMemento(shm);
-
- DocumentWorkspace.Selection.PerformChanging();
- DocumentWorkspace.Selection.Reset();
- DocumentWorkspace.Selection.SetContinuation(Document.Bounds, CombineMode.Replace);
- DocumentWorkspace.Selection.CommitContinuation();
- DocumentWorkspace.Selection.PerformChanged();
-
- newMode = e.Button == MouseButtons.Right ? Mode.Rotate : Mode.Translate;
-
- newEdge = Edge.None;
-
- determinedMoveMode = true;
- }
-
- DocumentWorkspace.EnableSelectionOutline = EnableOutline;
-
- if (!context.Lifted)
- {
- Lift(e);
- }
-
- PushContextHistoryMemento();
-
- if (!determinedMoveMode)
- {
- DetermineMoveMode(e, out newMode, out newEdge);
- determinedMoveMode = true;
- }
-
- if (context.DeltaTransform != null)
- {
- context.DeltaTransform.Dispose();
- context.DeltaTransform = null;
- }
-
- context.DeltaTransform = new Matrix();
- context.DeltaTransform.Reset();
-
- if (newMode == Mode.Translate ||
- newMode == Mode.Scale ||
- newMode != context.CurrentMode ||
- newMode == Mode.Rotate)
- {
- context.StartBounds = Selection.GetBoundsF();
- context.StartMouseXY = new Point(e.X, e.Y);
- context.Offset = new Point(0, 0);
-
- if (context.BaseTransform != null)
- {
- context.BaseTransform.Dispose();
- context.BaseTransform = null;
- }
-
- context.BaseTransform = Selection.GetInterimTransformCopy();
- }
-
- context.StartEdge = newEdge;
- context.CurrentMode = newMode;
- PositionNubs(context.CurrentMode);
-
- Tracking = true;
- RotateNub.Visible = (context.CurrentMode == Mode.Rotate);
-
- if (context.StartPath != null)
- {
- context.StartPath.Dispose();
- context.StartPath = null;
- }
-
- context.StartPath = Selection.CreatePath();
- context.StartAngle = Utility.GetAngleOfTransform(Selection.GetInterimTransformReadOnly());
-
- var sha1 = new SelectionHistoryMemento(Name, Image, DocumentWorkspace);
- CurrentHistoryMementos.Add(sha1);
-
- OnMouseMove(e);
-
- if (EnableOutline)
- {
- DocumentWorkspace.ResetOutlineWhiteOpacity();
- }
- }
-
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- var sbLogger = new StringBuilder();
-
- try
- {
- OnMouseMoveImpl(e, sbLogger);
- }
-
- catch (Exception ex)
- {
- throw new ApplicationException("Tracing data: " + sbLogger, ex);
- }
- }
-
- private void OnMouseMoveImpl(MouseEventArgs e, StringBuilder sbLogger)
- {
- if (!Tracking)
- {
- sbLogger.Append("1 ");
- Cursor cursor = MoveToolCursor;
-
- foreach (MoveNubRenderer t in MoveNubs)
- {
- sbLogger.Append("2 ");
- MoveNubRenderer nub = t;
- sbLogger.Append("3 ");
-
- if (!nub.Visible || !nub.IsPointTouching(new Point(e.X, e.Y), true)) continue;
- sbLogger.Append("4 ");
- cursor = HandCursor;
- break;
- }
-
- Cursor = cursor;
- sbLogger.Append("5 ");
- }
- else
- {
- sbLogger.Append("6 ");
- if (context.CurrentMode != Mode.Translate)
- {
- sbLogger.Append("7 ");
- Cursor = HandCursorMouseDown;
- }
-
- sbLogger.Append("8 ");
- var newMouseXY = new Point(e.X, e.Y);
- var newOffset = new Point(newMouseXY.X - context.StartMouseXY.X, newMouseXY.Y - context.StartMouseXY.Y);
-
- PreRender();
-
- DontDrop = true;
-
- sbLogger.Append("9 ");
- Selection.PerformChanging();
-
- using (var translateMatrix = new Matrix())
- {
- RectangleF rect;
- translateMatrix.Reset();
-
- if (context.BaseTransform != null)
- {
- Selection.SetInterimTransform(context.BaseTransform);
- }
-
- Matrix interim = Selection.GetInterimTransformCopy();
-
- switch (context.CurrentMode)
- {
- case Mode.Translate:
- translateMatrix.Translate(newOffset.X, newOffset.Y, MatrixOrder.Append);
- break;
-
- case Mode.Rotate:
- rect = context.LiftedBounds;
- var center = new PointF(rect.X + (rect.Width / 2.0f), rect.Y + (rect.Height / 2.0f));
- center = Utility.TransformOnePoint(interim, center);
- double theta1 = Math.Atan2(context.StartMouseXY.Y - center.Y, context.StartMouseXY.X - center.X);
- double theta2 = Math.Atan2(e.Y - center.Y, e.X - center.X);
- double thetaDelta = theta2 - theta1;
- AngleDelta = (float)(thetaDelta * (180.0f / Math.PI));
- float angle = context.StartAngle + AngleDelta;
-
- if ((ModifierKeys & Keys.Shift) != 0)
- {
- angle = ConstrainAngle(angle);
- AngleDelta = angle - context.StartAngle;
- }
-
- translateMatrix.RotateAt(AngleDelta, center, MatrixOrder.Append);
- RotateNub.Location = center;
- RotateNub.Angle = context.StartAngle + AngleDelta;
- break;
-
- case Mode.Scale:
- PointF xyAxes = GetEdgeVector(context.StartEdge);
- var xAxis = new PointF(xyAxes.X, 0);
- var yAxis = new PointF(0, xyAxes.Y);
- PointF edgeX = Utility.TransformOneVector(interim, xAxis);
- PointF edgeY = Utility.TransformOneVector(interim, yAxis);
- PointF edgeXN = Utility.NormalizeVector2(edgeX);
- PointF edgeYN = Utility.NormalizeVector2(edgeY);
-
- PointF xu;
- float xulen;
- PointF xv;
- Utility.GetProjection(newOffset, edgeXN, out xu, out xulen, out xv);
-
- PointF yu;
- float yulen;
- PointF yv;
- Utility.GetProjection(newOffset, edgeYN, out yu, out yulen, out yv);
-
- PdnGraphicsPath startPath2 = context.StartPath.Clone();
- RectangleF sp2Bounds = startPath2.GetBounds();
-
- var sp2BoundsCenter = new PointF((sp2Bounds.Left + sp2Bounds.Right) / 2.0f,
- (sp2Bounds.Top + sp2Bounds.Bottom) / 2.0f);
-
- float tAngle = Utility.GetAngleOfTransform(interim);
- bool isFlipped = Utility.IsTransformFlipped(interim);
-
- using (var spm = new Matrix())
- {
- spm.Reset();
- spm.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append);
- translateMatrix.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append);
- startPath2.Transform(spm);
- }
-
- RectangleF spBounds2 = startPath2.GetBounds();
-
- startPath2.Dispose();
- startPath2 = null;
-
- float xTranslate;
- float yTranslate;
- bool allowConstrain;
-
- Edge theEdge = context.StartEdge;
-
- // If the transform is flipped, then GetTransformAngle will return 180 degrees
- // even though no rotation has actually taken place. Thus we have to scratch
- // our head and go "hmm, let's make some adjustments to " Otherwise stretching
- // the top and bottom nubs goes in the wrong direction.
- if (isFlipped)
- {
- theEdge = FlipEdgeVertically(theEdge);
- }
-
- switch (theEdge)
- {
- default:
- throw new InvalidEnumArgumentException();
-
- case Edge.TopLeft:
- allowConstrain = true;
- xTranslate = -spBounds2.X - spBounds2.Width;
- yTranslate = -spBounds2.Y - spBounds2.Height;
- break;
-
- case Edge.Top:
- allowConstrain = false;
- xTranslate = 0;
- yTranslate = -spBounds2.Y - spBounds2.Height;
- break;
-
- case Edge.TopRight:
- allowConstrain = true;
- xTranslate = -spBounds2.X;
- yTranslate = -spBounds2.Y - spBounds2.Height;
- break;
-
- case Edge.Left:
- allowConstrain = false;
- xTranslate = -spBounds2.X - spBounds2.Width;
- yTranslate = 0;
- break;
-
- case Edge.Right:
- allowConstrain = false;
- xTranslate = -spBounds2.X;
- yTranslate = 0;
- break;
-
- case Edge.BottomLeft:
- allowConstrain = true;
- xTranslate = -spBounds2.X - spBounds2.Width;
- yTranslate = -spBounds2.Y;
- break;
-
- case Edge.Bottom:
- allowConstrain = false;
- xTranslate = 0;
- yTranslate = -spBounds2.Y;
- break;
-
- case Edge.BottomRight:
- allowConstrain = true;
- xTranslate = -spBounds2.X;
- yTranslate = -spBounds2.Y;
- break;
- }
-
- translateMatrix.Translate(xTranslate, yTranslate, MatrixOrder.Append);
-
- float newWidth = spBounds2.Width + xulen;
- float newHeight = spBounds2.Height + yulen;
- float xScale = newWidth / spBounds2.Width;
- float yScale = newHeight / spBounds2.Height;
-
- if (allowConstrain && (ModifierKeys & Keys.Shift) != 0)
- {
- ConstrainScaling(context.LiftedBounds, spBounds2.Width, spBounds2.Height,
- newWidth, newHeight, out xScale, out yScale);
- }
-
- translateMatrix.Scale(xScale, yScale, MatrixOrder.Append);
- translateMatrix.Translate(-xTranslate, -yTranslate, MatrixOrder.Append);
- translateMatrix.RotateAt(+tAngle, sp2BoundsCenter, MatrixOrder.Append);
-
- break;
-
- default:
- throw new InvalidEnumArgumentException();
- }
-
- context.DeltaTransform.Reset();
- context.DeltaTransform.Multiply(context.LiftTransform, MatrixOrder.Append);
- context.DeltaTransform.Multiply(translateMatrix, MatrixOrder.Append);
-
- translateMatrix.Multiply(context.BaseTransform, MatrixOrder.Prepend);
-
- Selection.SetInterimTransform(translateMatrix);
-
- interim.Dispose();
- interim = null;
- }
-
- // advertise our angle of rotation to any host (i.e. mainform) that might want to use that information
- hostShouldShowAngle = RotateNub.Visible;
- hostAngle = -RotateNub.Angle;
-
- Selection.PerformChanged();
- DontDrop = false;
-
- Render(newOffset, true);
- Update();
-
- sbLogger.Append("a ");
- context.Offset = newOffset;
-
- sbLogger.Append("b ");
-
- if (EnableOutline)
- {
- DocumentWorkspace.ResetOutlineWhiteOpacity();
- }
-
- sbLogger.Append("c ");
- }
-
- sbLogger.Append("d ");
- }
-
- protected override void OnMouseUp(MouseEventArgs e)
- {
- DocumentWorkspace.EnableSelectionOutline = true;
- base.OnMouseUp (e);
- }
-
- protected MoveToolBase(DocumentWorkspace documentWorkspace, ImageResource toolBarImage, string name,
- string helpText, char hotKey, bool skipIfActiveOnHotKey, ToolBarConfigItems toolBarConfigItems)
- : base(documentWorkspace, toolBarImage, name, helpText, hotKey, skipIfActiveOnHotKey, toolBarConfigItems)
- {
- }
- }
- }