123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687 |
- // Leave uncommented to always use bilinear rendering. Otherwise nearest neighbor
- // is used while interacting with the selection via the mouse, for better performance.
- //#define ALWAYSHIGHQUALITY
- using PaintDotNet.Measurement.Enum;
- using PaintDotNet.Measurement.HistoryMementos;
- using System;
- using System.ComponentModel;
- using System.Drawing;
- using System.Drawing.Drawing2D;
- using System.Runtime.Serialization;
- using System.Windows.Forms;
- namespace PaintDotNet.Measurement.Tools
- {
- public class MoveTool : MoveToolBase
- {
- public static string StaticName
- {
- get
- {
- return PdnResources.GetString("MoveTool.Name");
- }
- }
- // if this equals false, then Render() will always use NearestNeighbor, regardless of AppEnvironment.ResamplingAlgorithm
- private bool fullQuality = false;
- private BitmapLayer activeLayer;
- private RenderArgs renderArgs;
- private bool didPaste = false;
- private MoveToolContext ourContext
- {
- get
- {
- return (MoveToolContext)this.context;
- }
- }
- [Serializable]
- private sealed class MoveToolContext
- : MoveToolBase.Context
- {
- [NonSerialized]
- private MaskedSurface liftedPixels;
- [NonSerialized]
- public PersistedObject<MaskedSurface> poLiftedPixels;
- public Guid poLiftedPixelsGuid;
- public MaskedSurface LiftedPixels
- {
- get
- {
- if (this.liftedPixels == null)
- {
- if (this.poLiftedPixels != null)
- {
- this.liftedPixels = (MaskedSurface)poLiftedPixels.Object;
- }
- }
- return this.liftedPixels;
- }
- set
- {
- if (value == null)
- {
- this.poLiftedPixels = null;
- this.liftedPixels = null;
- }
- else
- {
- this.poLiftedPixels = new PersistedObject<MaskedSurface>(value, true);
- this.poLiftedPixelsGuid = PersistedObjectLocker.Add(this.poLiftedPixels);
- this.liftedPixels = null;
- }
- }
- }
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("poLiftedPixelsGuid", this.poLiftedPixelsGuid);
- }
- public MoveToolContext(SerializationInfo info, StreamingContext context)
- : base(info, context)
- {
- this.poLiftedPixelsGuid = (Guid)info.GetValue("poLiftedPixelsGuid", typeof(Guid));
- this.poLiftedPixels = PersistedObjectLocker.Get<MaskedSurface>(this.poLiftedPixelsGuid);
- }
- public MoveToolContext(MoveToolContext cloneMe)
- : base(cloneMe)
- {
- this.poLiftedPixelsGuid = cloneMe.poLiftedPixelsGuid;
- this.poLiftedPixels = cloneMe.poLiftedPixels; // do not clone
- this.liftedPixels = cloneMe.liftedPixels; // do not clone
- }
- public MoveToolContext()
- {
- }
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- }
- base.Dispose(disposing);
- }
- public override object Clone()
- {
- return new MoveToolContext(this);
- }
- }
- private class ContextHistoryMemento
- : ToolHistoryMemento
- {
- private int layerIndex;
- private object liftedPixelsRef; // prevent this from being GC'd
- [Serializable]
- private class OurContextHistoryMementoData
- : HistoryMementoData
- {
- public MoveToolContext context;
- public OurContextHistoryMementoData(Context context)
- {
- this.context = (MoveToolContext)context.Clone();
- }
- }
- protected override HistoryMemento OnToolUndo()
- {
- MoveTool moveTool = DocumentWorkspace.GetTool() as MoveTool;
- if (moveTool == null)
- {
- throw new InvalidOperationException("Current Tool is not the MoveTool");
- }
- ContextHistoryMemento cha = new ContextHistoryMemento(DocumentWorkspace, moveTool.ourContext, this.Name, this.Image);
- OurContextHistoryMementoData ohad = (OurContextHistoryMementoData)this.Data;
- Context newContext = ohad.context;
- if (moveTool.ActiveLayerIndex != this.layerIndex)
- {
- bool oldDOLC = moveTool.deactivateOnLayerChange;
- moveTool.deactivateOnLayerChange = false;
- moveTool.ActiveLayerIndex = this.layerIndex;
- moveTool.deactivateOnLayerChange = oldDOLC;
- moveTool.activeLayer = (BitmapLayer)moveTool.ActiveLayer;
- moveTool.renderArgs = new RenderArgs(moveTool.activeLayer.Surface);
- moveTool.ClearSavedMemory();
- }
- moveTool.context.Dispose();
- moveTool.context = newContext;
- moveTool.DestroyNubs();
- if (moveTool.context.lifted)
- {
- moveTool.PositionNubs(moveTool.context.currentMode);
- }
- return cha;
- }
- public ContextHistoryMemento(IDocumentWorkspace documentWorkspace, MoveToolContext context, string name, ImageResource image)
- : base(documentWorkspace, name, image)
- {
- this.Data = new OurContextHistoryMementoData(context);
- this.layerIndex = this.DocumentWorkspace.GetActiveLayerIndex();
- this.liftedPixelsRef = context.poLiftedPixels;
- }
- }
- protected override void OnActivate()
- {
- AppEnvironment.ResamplingAlgorithmChanged += AppEnvironment_ResamplingAlgorithmChanged;
- this.moveToolCursor = new Cursor(PdnResources.GetResourceStream("Cursors.MoveToolCursor.cur"));
- this.Cursor = this.moveToolCursor;
- this.context.lifted = false;
- this.ourContext.LiftedPixels = null;
- this.context.offset = new Point(0, 0);
- this.context.liftedBounds = Selection.GetBoundsF();
- this.activeLayer = (BitmapLayer)ActiveLayer;
- if (this.renderArgs != null)
- {
- this.renderArgs.Dispose();
- this.renderArgs = null;
- }
- if (this.activeLayer == null)
- {
- this.renderArgs = null;
- }
- else
- {
- this.renderArgs = new RenderArgs(this.activeLayer.Surface);
- }
- this.tracking = false;
- PositionNubs(this.context.currentMode);
- #if ALWAYSHIGHQUALITY
- this.fullQuality = true;
- #endif
- base.OnActivate();
- }
- protected override void OnDeactivate()
- {
- AppEnvironment.ResamplingAlgorithmChanged -= AppEnvironment_ResamplingAlgorithmChanged;
- if (this.moveToolCursor != null)
- {
- this.moveToolCursor.Dispose();
- this.moveToolCursor = null;
- }
- if (context.lifted)
- {
- Drop();
- }
- this.activeLayer = null;
- if (this.renderArgs != null)
- {
- this.renderArgs.Dispose();
- this.renderArgs = null;
- }
- this.tracking = false;
- DestroyNubs();
- base.OnDeactivate();
- }
- private void AppEnvironment_ResamplingAlgorithmChanged(object sender, EventArgs e)
- {
- if (this.ourContext.LiftedPixels != null)
- {
- bool oldHQ = this.fullQuality;
- this.fullQuality = true;
- PreRender();
- Render(this.context.offset, true);
- Update();
- this.fullQuality = oldHQ;
- }
- }
- protected override void Drop()
- {
- RestoreSavedRegion();
- PdnRegion regionCopy = Selection.CreateRegion();
- using (PdnRegion simplifiedRegion = Utility.SimplifyAndInflateRegion(regionCopy,
- Utility.DefaultSimplificationFactor, 2))
- {
- HistoryMemento bitmapAction2 = new BitmapHistoryMemento(Name, Image, DocumentWorkspace,
- ActiveLayerIndex, simplifiedRegion);
- bool oldHQ = this.fullQuality;
- this.fullQuality = true;
- Render(this.context.offset, true);
- this.fullQuality = oldHQ;
- this.currentHistoryMementos.Add(bitmapAction2);
- activeLayer.Invalidate(simplifiedRegion);
- Update();
- }
- regionCopy.Dispose();
- regionCopy = null;
- ContextHistoryMemento cha = new ContextHistoryMemento(this.DocumentWorkspace, this.ourContext, this.Name, this.Image);
- this.currentHistoryMementos.Add(cha);
- string name;
- ImageResource image;
- if (didPaste)
- {
- name = EnumLocalizer.EnumValueToLocalizedName(typeof(CommonAction), CommonAction.Paste);
- image = PdnResources.GetImageResource("Icons.MenuEditPasteIcon.png");
- }
- else
- {
- name = this.Name;
- image = this.Image;
- }
- didPaste = false;
- SelectionHistoryMemento sha = new SelectionHistoryMemento(this.Name, this.Image, this.DocumentWorkspace);
- this.currentHistoryMementos.Add(sha);
- this.context.Dispose();
- this.context = new MoveToolContext();
- this.FlushHistoryMementos(PdnResources.GetString("MoveTool.HistoryMemento.DropPixels"));
- }
- protected override void OnSelectionChanging()
- {
- base.OnSelectionChanging();
- if (!dontDrop)
- {
- if (context.lifted)
- {
- Drop();
- }
- if (tracking)
- {
- tracking = false;
- }
- }
- }
- protected override void OnSelectionChanged()
- {
- if (!context.lifted)
- {
- DestroyNubs();
- PositionNubs(this.context.currentMode);
- }
- base.OnSelectionChanged();
- }
- /// <summary>
- /// Provided as a special entry point so that Paste can work well.
- /// </summary>
- /// <param name="surface">What you want to paste.</param>
- /// <param name="offset">Where you want to paste it.</param>
- public void PasteMouseDown(SurfaceForClipboard sfc, Point offset)
- {
- if (this.context.lifted)
- {
- Drop();
- }
- MaskedSurface pixels = sfc.MaskedSurface;
- PdnGraphicsPath pastePath = pixels.CreatePath();
- PdnRegion pasteRegion = new PdnRegion(pastePath);
- PdnRegion simplifiedPasteRegion = Utility.SimplifyAndInflateRegion(pasteRegion);
- HistoryMemento bitmapAction = new BitmapHistoryMemento(Name, Image,
- DocumentWorkspace, ActiveLayerIndex, simplifiedPasteRegion); // SLOW (110ms)
- this.currentHistoryMementos.Add(bitmapAction);
- PushContextHistoryMemento();
- this.context.seriesGuid = Guid.NewGuid();
- this.context.currentMode = Mode.Translate;
- this.context.startEdge = Edge.None;
- this.context.startAngle = 0.0f;
- this.ourContext.LiftedPixels = pixels;
- this.context.lifted = true;
- this.context.liftTransform = new Matrix();
- this.context.liftTransform.Reset();
- this.context.deltaTransform = new Matrix();
- this.context.deltaTransform.Reset();
- this.context.offset = new Point(0, 0);
- bool oldDD = this.dontDrop;
- this.dontDrop = true;
- SelectionHistoryMemento sha = new SelectionHistoryMemento(null, null, DocumentWorkspace);
- this.currentHistoryMementos.Add(sha);
- Selection.PerformChanging();
- Selection.Reset();
- Selection.SetContinuation(pastePath, CombineMode.Replace, true);
- pastePath = null;
- Selection.CommitContinuation();
- Selection.PerformChanged();
- PushContextHistoryMemento();
- this.context.liftedBounds = Selection.GetBoundsF(false);
- this.context.startBounds = this.context.liftedBounds;
- this.context.baseTransform = new Matrix();
- this.context.baseTransform.Reset();
- this.tracking = true;
- this.dontDrop = oldDD;
- this.didPaste = true;
- this.tracking = true;
- DestroyNubs();
- PositionNubs(this.context.currentMode);
- // we use the value 70,000 to simulate mouse input because that's guaranteed to be out of bounds of where
- // the mouse can actually be -- PDN is limited to 65536 x 65536 images by design
- MouseEventArgs mea1 = new MouseEventArgs(MouseButtons.Left, 0, 70000, 70000, 0);
- MouseEventArgs mea2 = new MouseEventArgs(MouseButtons.Left, 0, 70000 + offset.X, 70000 + offset.Y, 0);
- this.context.startMouseXY = new Point(70000, 70000);
- OnMouseDown(mea1);
- OnMouseMove(mea2); // SLOW (200ms)
- OnMouseUp(mea2);
- }
- protected override void OnLift(MouseEventArgs e)
- {
- PdnGraphicsPath liftPath = Selection.CreatePath();
- PdnRegion liftRegion = Selection.CreateRegion();
- this.ourContext.LiftedPixels = new MaskedSurface(activeLayer.Surface, liftPath);
- HistoryMemento bitmapAction = new BitmapHistoryMemento(
- Name,
- Image,
- DocumentWorkspace,
- ActiveLayerIndex,
- this.ourContext.poLiftedPixelsGuid);
- this.currentHistoryMementos.Add(bitmapAction);
- // If the user is holding down the control key, we want to *copy* the pixels
- // and not "lift and erase"
- if ((ModifierKeys & Keys.Control) == Keys.None)
- {
- ColorBgra fill = AppEnvironment.SecondaryColor();
- fill.A = 0;
- UnaryPixelOp op = new UnaryPixelOps.Constant(fill);
- op.Apply(this.renderArgs.Surface, liftRegion);
- }
- liftRegion.Dispose();
- liftRegion = null;
- liftPath.Dispose();
- liftPath = null;
- }
- protected override void PushContextHistoryMemento()
- {
- ContextHistoryMemento cha = new ContextHistoryMemento(this.DocumentWorkspace, this.ourContext, null, null);
- this.currentHistoryMementos.Add(cha);
- }
- protected override void Render(Point newOffset, bool useNewOffset)
- {
- Render(newOffset, useNewOffset, true);
- }
- protected void Render(Point newOffset, bool useNewOffset, bool saveRegion)
- {
- Rectangle saveBounds = Selection.GetBounds();
- PdnRegion selectedRegion = Selection.CreateRegion();
- PdnRegion simplifiedRegion = Utility.SimplifyAndInflateRegion(selectedRegion);
- if (saveRegion)
- {
- SaveRegion(simplifiedRegion, saveBounds);
- }
- WaitCursorChanger wcc = null;
- if (this.fullQuality && AppEnvironment.ResamplingAlgorithm() == ResamplingAlgorithm.Bilinear)
- {
- wcc = new WaitCursorChanger(DocumentWorkspace.GetThis());
- }
- this.ourContext.LiftedPixels.Draw(
- this.renderArgs.Surface,
- this.context.deltaTransform,
- this.fullQuality ?
- AppEnvironment.ResamplingAlgorithm() :
- ResamplingAlgorithm.NearestNeighbor);
- if (wcc != null)
- {
- wcc.Dispose();
- wcc = null;
- }
- activeLayer.Invalidate(simplifiedRegion);
- PositionNubs(this.context.currentMode);
- simplifiedRegion.Dispose();
- selectedRegion.Dispose();
- }
- protected override void PreRender()
- {
- RestoreSavedRegion();
- }
- protected override void OnMouseUp(MouseEventArgs e)
- {
- base.OnMouseUp(e);
- if (!tracking)
- {
- return;
- }
- this.fullQuality = true;
- OnMouseMove(e);
- #if !ALWAYSHIGHQUALITY
- this.fullQuality = false;
- #endif
- this.rotateNub.Visible = false;
- tracking = false;
- PositionNubs(this.context.currentMode);
- string resourceName;
- switch (this.context.currentMode)
- {
- default:
- throw new InvalidEnumArgumentException();
- case Mode.Rotate:
- resourceName = "MoveTool.HistoryMemento.Rotate";
- break;
- case Mode.Scale:
- resourceName = "MoveTool.HistoryMemento.Scale";
- break;
- case Mode.Translate:
- resourceName = "MoveTool.HistoryMemento.Translate";
- break;
- }
- this.context.startAngle += this.angleDelta;
- if (this.context.liftTransform == null)
- {
- this.context.liftTransform = new Matrix();
- }
- this.context.liftTransform.Reset();
- this.context.liftTransform.Multiply(this.context.deltaTransform, MatrixOrder.Append);
- string actionName = PdnResources.GetString(resourceName);
- FlushHistoryMementos(actionName);
- }
- private void FlushHistoryMementos(string name)
- {
- if (this.currentHistoryMementos.Count > 0)
- {
- CompoundHistoryMemento cha = new CompoundHistoryMemento(null, null,
- this.currentHistoryMementos.ToArray());
- string haName;
- ImageResource image;
- if (this.didPaste)
- {
- haName = PdnResources.GetString("CommonAction.Paste");
- image = PdnResources.GetImageResource("Icons.MenuEditPasteIcon.png");
- this.didPaste = false;
- }
- else
- {
- if (name == null)
- {
- haName = this.Name;
- }
- else
- {
- haName = name;
- }
- image = this.Image;
- }
- CompoundToolHistoryMemento ctha = new CompoundToolHistoryMemento(cha, this.DocumentWorkspace, haName, image);
- ctha.SeriesGuid = context.seriesGuid;
- //HistoryStack.PushNewMemento(ctha);
- this.currentHistoryMementos.Clear();
- }
- }
- public MoveTool(IDocumentWorkspace documentWorkspace)
- : base(documentWorkspace,
- PdnResources.GetImageResource("Icons.MoveToolIcon.png"),
- MoveTool.StaticName,
- PdnResources.GetString("MoveTool.HelpText"), // "Click and drag to move a selected region",
- 'm',
- false,
- ToolBarConfigItems.Resampling)
- {
- this.context = new MoveToolContext();
- this.enableOutline = false;
- }
- protected override void Dispose(bool disposing)
- {
- base.Dispose(disposing);
- if (disposing)
- {
- DestroyNubs();
- if (this.renderArgs != null)
- {
- this.renderArgs.Dispose();
- this.renderArgs = null;
- }
- if (this.context != null)
- {
- this.context.Dispose();
- this.context = null;
- }
- }
- }
- protected override void OnExecutingHistoryMemento(ExecutingHistoryMementoEventArgs e)
- {
- this.dontDrop = true;
- RestoreSavedRegion();
- ClearSavedMemory();
- if (e.MayAlterSuspendTool)
- {
- e.SuspendTool = false;
- }
- }
- protected override void OnExecutedHistoryMemento(ExecutedHistoryMementoEventArgs e)
- {
- if (context.lifted)
- {
- bool oldHQ = this.fullQuality;
- this.fullQuality = false;
- Render(context.offset, true);
- ClearSavedMemory();
- this.fullQuality = oldHQ;
- }
- else
- {
- DestroyNubs();
- PositionNubs(this.context.currentMode);
- }
- this.dontDrop = false;
- }
- protected override void OnFinishedHistoryStepGroup()
- {
- if (context.lifted)
- {
- bool oldHQ = this.fullQuality;
- this.fullQuality = true;
- Render(context.offset, true, false);
- this.fullQuality = oldHQ;
- }
- base.OnFinishedHistoryStepGroup();
- }
- }
- }
|