1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045 |
- using PaintDotNet.Measurement.HistoryFunctions;
- using PaintDotNet.Measurement.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.Measurement.Tools
- {
- public abstract class MoveToolBase : Tool
- {
- protected Cursor moveToolCursor;
- protected bool dontDrop = false; // 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 this.deactivateOnLayerChange;
- }
- }
- protected enum Mode
- {
- Translate,
- Scale,
- Rotate
- }
- // Corresponds to array positions in this.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 float[] GetMatrixElements(Matrix m)
- {
- if (m == null)
- {
- return null;
- }
- else
- {
- return m.Elements;
- }
- }
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("lifted", this.lifted);
- info.AddValue("seriesGuid", this.seriesGuid);
- info.AddValue("baseTransform", GetMatrixElements(this.baseTransform));
- info.AddValue("deltaTransform", GetMatrixElements(this.deltaTransform));
- info.AddValue("liftTransform", GetMatrixElements(this.liftTransform));
- info.AddValue("liftedBounds", this.liftedBounds);
- info.AddValue("startBounds", this.startBounds);
- info.AddValue("startAngle", this.startAngle);
- info.AddValue("startPath", this.startPath);
- info.AddValue("currentMode", this.currentMode);
- info.AddValue("startEdge", this.startEdge);
- info.AddValue("startMouseXY", this.startMouseXY);
- info.AddValue("offset", this.offset);
- }
- private Matrix ReadMatrix(SerializationInfo info, StreamingContext context, string name)
- {
- Matrix m;
- float[] e = (float[])info.GetValue(name, typeof(float[]));
- if (e == null)
- {
- m = null;
- }
- else
- {
- m = new Matrix(e[0], e[1], e[2], e[3], e[4], e[5]);
- }
- return m;
- }
- public Context(SerializationInfo info, StreamingContext context)
- {
- this.lifted = (bool)info.GetValue("lifted", typeof(bool));
- this.seriesGuid = (Guid)info.GetValue("seriesGuid", typeof(Guid));
- this.baseTransform = ReadMatrix(info, context, "baseTransform");
- this.deltaTransform = ReadMatrix(info, context, "deltaTransform");
- this.liftTransform = ReadMatrix(info, context, "liftTransform");
- this.liftedBounds = (RectangleF)info.GetValue("liftedBounds", typeof(RectangleF));
- this.startBounds = (RectangleF)info.GetValue("startBounds", typeof(RectangleF));
- this.startAngle = (float)info.GetValue("startAngle", typeof(float));
- this.startPath = (PdnGraphicsPath)info.GetValue("startPath", typeof(PdnGraphicsPath));
- this.currentMode = (Mode)info.GetValue("currentMode", typeof(Mode));
- this.startEdge = (Edge)info.GetValue("startEdge", typeof(Edge));
- this.startMouseXY = (Point)info.GetValue("startMouseXY", typeof(Point));
- this.offset = (Point)info.GetValue("offset", typeof(Point));
- }
- public Context()
- {
- }
- public Context(Context cloneMe)
- {
- this.lifted = cloneMe.lifted;
- this.seriesGuid = cloneMe.seriesGuid;
- if (cloneMe.baseTransform != null)
- {
- this.baseTransform = cloneMe.baseTransform.Clone();
- }
- if (cloneMe.deltaTransform != null)
- {
- this.deltaTransform = cloneMe.deltaTransform.Clone();
- }
- if (cloneMe.liftTransform != null)
- {
- this.liftTransform = cloneMe.liftTransform.Clone();
- }
- this.liftedBounds = cloneMe.liftedBounds;
- this.startBounds = cloneMe.startBounds;
- this.startAngle = cloneMe.startAngle;
- if (cloneMe.startPath != null)
- {
- this.startPath = cloneMe.startPath.Clone();
- }
- this.currentMode = cloneMe.currentMode;
- this.startEdge = cloneMe.startEdge;
- this.startMouseXY = cloneMe.startMouseXY;
- this.offset = cloneMe.offset;
- }
- ~Context()
- {
- Dispose(false);
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (this.baseTransform != null)
- {
- this.baseTransform.Dispose();
- this.baseTransform = null;
- }
- if (this.deltaTransform != null)
- {
- this.deltaTransform.Dispose();
- this.deltaTransform = null;
- }
- if (this.liftTransform != null)
- {
- this.liftTransform.Dispose();
- this.liftTransform = null;
- }
- if (this.startPath != null)
- {
- this.startPath.Dispose();
- this.startPath = null;
- }
- }
- }
- public virtual object Clone()
- {
- return new Context(this);
- }
- }
- protected class CompoundToolHistoryMemento
- : ToolHistoryMemento
- {
- private CompoundHistoryMemento compoundHistoryMemento;
- public CompoundHistoryMemento CompoundHistoryMemento
- {
- get
- {
- return this.compoundHistoryMemento;
- }
- }
- protected override HistoryMemento OnToolUndo()
- {
- CompoundHistoryMemento chm = (CompoundHistoryMemento)this.compoundHistoryMemento.PerformUndo();
- CompoundToolHistoryMemento cthm = new CompoundToolHistoryMemento(chm, DocumentWorkspace, this.Name, this.Image);
- return cthm;
- }
- public CompoundToolHistoryMemento(CompoundHistoryMemento chm, IDocumentWorkspace documentWorkspace, string name, ImageResource image)
- : base(documentWorkspace, name, image)
- {
- this.compoundHistoryMemento = chm;
- }
- }
- public bool HostShouldShowAngle
- {
- get
- {
- return this.hostShouldShowAngle;
- }
- }
- public float HostAngle
- {
- get
- {
- return this.hostAngle;
- }
- }
- protected void DestroyNubs()
- {
- if (this.moveNubs != null)
- {
- for (int i = 0; i < this.moveNubs.Length; ++i)
- {
- this.RendererList.Remove(this.moveNubs[i]);
- this.moveNubs[i].Dispose();
- this.moveNubs[i] = null;
- }
- this.moveNubs = null;
- }
- if (this.rotateNub != null)
- {
- this.RendererList.Remove(this.rotateNub);
- this.rotateNub.Dispose();
- this.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;
- Point mousePt = new Point(e.X, e.Y);
- for (int i = 0; i < this.moveNubs.Length; ++i)
- {
- MoveNubRenderer nub = this.moveNubs[i];
- if (nub.IsPointTouching(mousePt, true))
- {
- float distance = Utility.Distance((PointF)mousePt, nub.Location);
- if (distance < minDistance)
- {
- minDistance = distance;
- mode = Mode.Scale;
- edge = (Edge)i;
- }
- }
- }
- }
- return;
- }
- protected override void OnPulse()
- {
- if (this.moveNubs != null)
- {
- for (int i = 0; i < this.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 / this.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]
- int newAlpha = (int)(sin * 255.0);
- int clampedAlpha = Utility.Clamp(newAlpha, 0, 255);
- this.moveNubs[i].Alpha = clampedAlpha;
- }
- }
- base.OnPulse();
- }
- protected void PositionNubs(Mode currentMode)
- {
- if (this.moveNubs == null)
- {
- this.moveNubs = new MoveNubRenderer[8];
- for (int i = 0; i < this.moveNubs.Length; ++i)
- {
- this.moveNubs[i] = new MoveNubRenderer(this.RendererList);
- this.RendererList.Add(this.moveNubs[i], false);
- }
- RectangleF bounds = Selection.GetBoundsF(false);
- this.moveNubs[(int)Edge.TopLeft].Location = new PointF(bounds.Left, bounds.Top);
- this.moveNubs[(int)Edge.TopLeft].Shape = MoveNubShape.Circle;
- this.moveNubs[(int)Edge.Top].Location = new PointF((bounds.Left + bounds.Right) / 2.0f, bounds.Top);
- this.moveNubs[(int)Edge.TopRight].Location = new PointF(bounds.Right, bounds.Top);
- this.moveNubs[(int)Edge.TopRight].Shape = MoveNubShape.Circle;
- this.moveNubs[(int)Edge.Left].Location = new PointF(bounds.Left, (bounds.Top + bounds.Bottom) / 2.0f);
- this.moveNubs[(int)Edge.Right].Location = new PointF(bounds.Right, (bounds.Top + bounds.Bottom) / 2.0f);
- this.moveNubs[(int)Edge.BottomLeft].Location = new PointF(bounds.Left, bounds.Bottom);
- this.moveNubs[(int)Edge.BottomLeft].Shape = MoveNubShape.Circle;
- this.moveNubs[(int)Edge.Bottom].Location = new PointF((bounds.Left + bounds.Right) / 2.0f, bounds.Bottom);
- this.moveNubs[(int)Edge.BottomRight].Location = new PointF(bounds.Right, bounds.Bottom);
- this.moveNubs[(int)Edge.BottomRight].Shape = MoveNubShape.Circle;
- }
- if (this.rotateNub == null)
- {
- this.rotateNub = new RotateNubRenderer(this.RendererList);
- rotateNub.Visible = false;
- this.RendererList.Add(this.rotateNub, false);
- }
- if (Selection.IsEmpty)
- {
- foreach (SurfaceBoxRenderer nub in this.moveNubs)
- {
- nub.Visible = false;
- }
- this.rotateNub.Visible = false;
- }
- else
- {
- foreach (MoveNubRenderer nub in this.moveNubs)
- {
- nub.Visible = !tracking || currentMode == Mode.Scale;
- nub.Transform = Selection.GetInterimTransformReadOnly();
- }
- }
- }
- protected void HideNubs()
- {
- if (this.moveNubs != null)
- {
- foreach (SurfaceBoxRenderer sbr in this.moveNubs)
- {
- sbr.Visible = false;
- }
- }
- if (this.rotateNub != null)
- {
- this.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 this.liftedBounds
- protected void ConstrainScaling(RectangleF liftedBounds, float startWidth, float startHeight,
- float newWidth, float newHeight, out float newXScale, out float newYScale)
- {
- float hRatio = newWidth / (float)liftedBounds.Width;
- float vRatio = newHeight / (float)liftedBounds.Height;
- float bestScale = Math.Min(hRatio, vRatio);
- float bestWidth = (float)liftedBounds.Width * bestScale;
- float bestHeight = (float)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;
- }
- int iangle = (int)angle;
- int lowerBound = (iangle / 15) * 15;
- int upperBound = lowerBound + 15;
- float lowerDiff = Math.Abs(angle - (float)lowerBound);
- float upperDiff = Math.Abs(angle - (float)upperBound);
- float newAngle;
- if (lowerDiff < upperDiff)
- {
- newAngle = (float)lowerBound;
- }
- else
- {
- newAngle = (float)upperBound;
- }
- if (newAngle > 180.0f)
- {
- newAngle -= 360.0f;
- }
- return newAngle;
- }
- protected override void OnKeyPress(Keys key)
- {
- if (!tracking)
- {
- int dx = 0;
- int dy = 0;
- if ((key & Keys.KeyCode) == Keys.Left)
- {
- dx = -1;
- }
- else if ((key & Keys.KeyCode) == Keys.Right)
- {
- dx = +1;
- }
- else if ((key & Keys.KeyCode) == Keys.Up)
- {
- dy = -1;
- }
- else if ((key & Keys.KeyCode) == Keys.Down)
- {
- dy = +1;
- }
- if ((key & Keys.Control) != Keys.None)
- {
- dx *= 10;
- dy *= 10;
- }
- // Simulate moving the selection
- if (dx != 0 || dy != 0)
- {
- Point pos = Cursor.Position;
- Point docPos = new Point(-70000, -70000);
- Point 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)
- {
- this.PushContextHistoryMemento();
- this.context.seriesGuid = Guid.NewGuid();
- DetermineMoveMode(e, out this.context.currentMode, out this.context.startEdge);
- // lift!
- this.context.startBounds = this.context.liftedBounds;
- this.context.liftedBounds = Selection.GetBoundsF(false);
- this.context.startMouseXY = new Point(e.X, e.Y);
- this.context.offset = new Point(0, 0);
- this.context.startAngle = 0.0f;
- this.context.lifted = true;
- this.context.liftTransform = Selection.GetCumulativeTransformCopy();
- OnLift(e);
- PositionNubs(this.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)
- {
- SelectionHistoryMemento shm = new SelectionHistoryMemento(
- SelectAllFunction.StaticName,
- PdnResources.GetImageResource("Icons.MenuEditSelectAllIcon.png"),
- DocumentWorkspace);
- DocumentWorkspace.GetSelection().PerformChanging();
- DocumentWorkspace.GetSelection().Reset();
- DocumentWorkspace.GetSelection().SetContinuation(Document.Bounds, CombineMode.Replace);
- DocumentWorkspace.GetSelection().CommitContinuation();
- DocumentWorkspace.GetSelection().PerformChanged();
- if (e.Button == MouseButtons.Right)
- {
- newMode = Mode.Rotate;
- }
- else
- {
- newMode = Mode.Translate;
- }
- newEdge = Edge.None;
- determinedMoveMode = true;
- }
- DocumentWorkspace.SetEnableSelectionOutline(this.enableOutline);
- if (!context.lifted)
- {
- Lift(e);
- }
- PushContextHistoryMemento();
- if (!determinedMoveMode)
- {
- DetermineMoveMode(e, out newMode, out newEdge);
- determinedMoveMode = true;
- }
- if (this.context.deltaTransform != null)
- {
- this.context.deltaTransform.Dispose();
- this.context.deltaTransform = null;
- }
- this.context.deltaTransform = new Matrix();
- this.context.deltaTransform.Reset();
- if (newMode == Mode.Translate ||
- newMode == Mode.Scale ||
- newMode != this.context.currentMode ||
- newMode == Mode.Rotate)
- {
- this.context.startBounds = Selection.GetBoundsF();
- this.context.startMouseXY = new Point(e.X, e.Y);
- this.context.offset = new Point(0, 0);
- if (this.context.baseTransform != null)
- {
- this.context.baseTransform.Dispose();
- this.context.baseTransform = null;
- }
- this.context.baseTransform = Selection.GetInterimTransformCopy();
- }
- this.context.startEdge = newEdge;
- this.context.currentMode = newMode;
- PositionNubs(this.context.currentMode);
- tracking = true;
- this.rotateNub.Visible = (this.context.currentMode == Mode.Rotate);
- if (this.context.startPath != null)
- {
- this.context.startPath.Dispose();
- this.context.startPath = null;
- }
- this.context.startPath = Selection.CreatePath();
- this.context.startAngle = Utility.GetAngleOfTransform(Selection.GetInterimTransformReadOnly());
- SelectionHistoryMemento sha1 = new SelectionHistoryMemento(this.Name, this.Image, this.DocumentWorkspace);
- this.currentHistoryMementos.Add(sha1);
- OnMouseMove(e);
- if (this.enableOutline)
- {
- DocumentWorkspace.ResetOutlineWhiteOpacity();
- }
- }
- protected override void OnMouseMove(MouseEventArgs e)
- {
- base.OnMouseMove(e);
- StringBuilder sbLogger = new StringBuilder();
- try
- {
- OnMouseMoveImpl(e, sbLogger);
- }
- catch (Exception ex)
- {
- throw new ApplicationException("Tracing data: " + sbLogger.ToString(), ex);
- }
- }
- private void OnMouseMoveImpl(MouseEventArgs e, StringBuilder sbLogger)
- {
- if (!this.tracking)
- {
- sbLogger.Append("1 ");
- Cursor cursor = this.moveToolCursor;
- for (int i = 0; i < this.moveNubs.Length; ++i)
- {
- sbLogger.Append("2 ");
- MoveNubRenderer nub = this.moveNubs[i];
- sbLogger.Append("3 ");
- if (nub.Visible && nub.IsPointTouching(new Point(e.X, e.Y), true))
- {
- sbLogger.Append("4 ");
- cursor = this.handCursor;
- break;
- }
- }
- this.Cursor = cursor;
- sbLogger.Append("5 ");
- }
- else
- {
- sbLogger.Append("6 ");
- if (this.context.currentMode != Mode.Translate)
- {
- sbLogger.Append("7 ");
- this.Cursor = this.handCursorMouseDown;
- }
- sbLogger.Append("8 ");
- Point newMouseXY = new Point(e.X, e.Y);
- Point newOffset = new Point(newMouseXY.X - context.startMouseXY.X, newMouseXY.Y - context.startMouseXY.Y);
- PreRender();
- this.dontDrop = true;
- sbLogger.Append("9 ");
- Selection.PerformChanging();
- using (Matrix translateMatrix = new Matrix())
- {
- RectangleF rect;
- translateMatrix.Reset();
- if (this.context.baseTransform != null)
- {
- Selection.SetInterimTransform(this.context.baseTransform);
- }
- Matrix interim = Selection.GetInterimTransformCopy();
- switch (this.context.currentMode)
- {
- case Mode.Translate:
- translateMatrix.Translate((float)newOffset.X, (float)newOffset.Y, MatrixOrder.Append);
- break;
- case Mode.Rotate:
- rect = this.context.liftedBounds;
- PointF 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;
- this.angleDelta = (float)(thetaDelta * (180.0f / Math.PI));
- float angle = this.context.startAngle + this.angleDelta;
- if ((ModifierKeys & Keys.Shift) != 0)
- {
- angle = ConstrainAngle(angle);
- angleDelta = angle - this.context.startAngle;
- }
- translateMatrix.RotateAt(angleDelta, center, MatrixOrder.Append);
- this.rotateNub.Location = center;
- this.rotateNub.Angle = this.context.startAngle + angleDelta;
- break;
- case Mode.Scale:
- PointF xyAxes = GetEdgeVector(this.context.startEdge);
- PointF xAxis = new PointF(xyAxes.X, 0);
- PointF 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((PointF)newOffset, edgeXN, out xu, out xulen, out xv);
- PointF yu;
- float yulen;
- PointF yv;
- Utility.GetProjection((PointF)newOffset, edgeYN, out yu, out yulen, out yv);
- PdnGraphicsPath startPath2 = this.context.startPath.Clone();
- RectangleF sp2Bounds = startPath2.GetBounds();
- PointF 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 (Matrix 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 = this.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 this." 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 && (this.ModifierKeys & Keys.Shift) != 0)
- {
- ConstrainScaling(this.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();
- }
- this.context.deltaTransform.Reset();
- this.context.deltaTransform.Multiply(this.context.liftTransform, MatrixOrder.Append);
- this.context.deltaTransform.Multiply(translateMatrix, MatrixOrder.Append);
- translateMatrix.Multiply(this.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
- this.hostShouldShowAngle = this.rotateNub.Visible;
- this.hostAngle = -this.rotateNub.Angle;
- Selection.PerformChanged();
- dontDrop = false;
- Render(newOffset, true);
- Update();
- sbLogger.Append("a ");
- this.context.offset = newOffset;
- sbLogger.Append("b ");
- if (this.enableOutline)
- {
- DocumentWorkspace.ResetOutlineWhiteOpacity();
- }
- sbLogger.Append("c ");
- }
- sbLogger.Append("d ");
- }
- protected override void OnMouseUp(MouseEventArgs e)
- {
- DocumentWorkspace.SetEnableSelectionOutline(true);
- base.OnMouseUp(e);
- }
- public MoveToolBase(IDocumentWorkspace documentWorkspace, ImageResource toolBarImage, string name,
- string helpText, char hotKey, bool skipIfActiveOnHotKey, ToolBarConfigItems toolBarConfigItems)
- : base(documentWorkspace, toolBarImage, name, helpText, hotKey, skipIfActiveOnHotKey, toolBarConfigItems)
- {
- }
- }
- }
|