public CompoundHistoryMemento(string name, ImageResource image, HistoryMemento[] actions) : base(name, image) { this.actions = new List<HistoryMemento>(actions); }
private HistoryMemento ImportOneLayer(DocumentWorkspace documentWorkspace, BitmapLayer layer) { HistoryMemento retHA; List <HistoryMemento> historyMementos = new List <HistoryMemento>(); bool success = true; if (success) { if (!documentWorkspace.Selection.IsEmpty) { HistoryMemento ha = new DeselectFunction().Execute(documentWorkspace); historyMementos.Add(ha); } } if (success) { if (layer.Width > documentWorkspace.Document.Width || layer.Height > documentWorkspace.Document.Height) { HistoryMemento ha = DoCanvasResize(documentWorkspace, layer.Size); if (ha == null) { success = false; } else { historyMementos.Add(ha); } } } if (success) { if (layer.Size != documentWorkspace.Document.Size) { BitmapLayer newLayer; try { using (new WaitCursorChanger(documentWorkspace)) { Utility.GCFullCollect(); newLayer = CanvasSizeAction.ResizeLayer((BitmapLayer)layer, documentWorkspace.Document.Size, AnchorEdge.TopLeft, ColorBgra.White.NewAlpha(0)); } } catch (OutOfMemoryException) { Utility.ErrorBox(documentWorkspace, PdnResources.GetString("ImportFromFileAction.ImportOneLayer.OutOfMemory")); success = false; newLayer = null; } if (newLayer != null) { layer.Dispose(); layer = newLayer; } } } if (success) { NewLayerHistoryMemento nlha = new NewLayerHistoryMemento(string.Empty, null, documentWorkspace, documentWorkspace.Document.Layers.Count); documentWorkspace.Document.Layers.Add(layer); historyMementos.Add(nlha); } if (success) { HistoryMemento[] has = historyMementos.ToArray(); retHA = new CompoundHistoryMemento(string.Empty, null, has); } else { Rollback(historyMementos); retHA = null; } return(retHA); }
public void PushNewAction(HistoryMemento newHA) { actions.Add(newHA); }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { int height; int width; string str; string str2; switch (this.rotation) { case RotateType.Clockwise90: case RotateType.CounterClockwise90: height = historyWorkspace.Document.Height; width = historyWorkspace.Document.Width; break; case RotateType.Rotate180: height = historyWorkspace.Document.Width; width = historyWorkspace.Document.Height; break; default: throw ExceptionUtil.InvalidEnumArgumentException <RotateType>(this.rotation, "this.rotation"); } switch (this.rotation) { case RotateType.Clockwise90: str = "Icons.MenuImageRotate90CWIcon.png"; str2 = PdnResources.GetString("RotateAction.90CW"); break; case RotateType.CounterClockwise90: str = "Icons.MenuImageRotate90CCWIcon.png"; str2 = PdnResources.GetString("RotateAction.90CCW"); break; case RotateType.Rotate180: str = "Icons.MenuImageRotate180Icon.png"; str2 = PdnResources.GetString("RotateAction.180"); break; default: throw ExceptionUtil.InvalidEnumArgumentException <RotateType>(this.rotation, "this.rotation"); } string name = string.Format(PdnResources.GetString("RotateAction.HistoryMementoName.Format"), StaticName, str2); ImageResource imageResource = PdnResources.GetImageResource(str); List <HistoryMemento> actions = new List <HistoryMemento>(); Document document = new Document(height, width); if (!historyWorkspace.Selection.IsEmpty) { DeselectFunction function = new DeselectFunction(); base.EnterCriticalRegion(); HistoryMemento memento3 = function.Execute(historyWorkspace); actions.Add(memento3); } ReplaceDocumentHistoryMemento item = new ReplaceDocumentHistoryMemento(null, null, historyWorkspace); actions.Add(item); document.ReplaceMetadataFrom(historyWorkspace.Document); for (int i = 0; i < historyWorkspace.Document.Layers.Count; i++) { Layer at = historyWorkspace.Document.Layers.GetAt(i); if (!(at is BitmapLayer)) { throw new InvalidOperationException("Cannot Rotate non-BitmapLayers"); } Layer layer2 = this.RotateLayer((BitmapLayer)at, this.rotation, height, width); document.Layers.Add(layer2); } CompoundHistoryMemento memento2 = new CompoundHistoryMemento(name, imageResource, actions); base.EnterCriticalRegion(); historyWorkspace.Document = document; return(memento2); }
/// <summary> /// Presents a user interface and performs the operations required for importing an entire document. /// </summary> /// <param name="document"></param> /// <returns></returns> /// <remarks> /// This function will take ownership of the Document given to it, and will Dispose() of it. /// </remarks> private HistoryMemento ImportDocument(DocumentWorkspace documentWorkspace, Document document, out Rectangle lastLayerBounds) { List <HistoryMemento> historyMementos = new List <HistoryMemento>(); bool[] selected; selected = new bool[document.Layers.Count]; for (int i = 0; i < selected.Length; ++i) { selected[i] = true; } lastLayerBounds = Rectangle.Empty; if (selected != null) { List <Layer> layers = new List <Layer>(); for (int i = 0; i < selected.Length; ++i) { if (selected[i]) { layers.Add((Layer)document.Layers[i]); } } foreach (Layer layer in layers) { document.Layers.Remove(layer); } document.Dispose(); document = null; foreach (Layer layer in layers) { lastLayerBounds = layer.Bounds; HistoryMemento ha = ImportOneLayer(documentWorkspace, (BitmapLayer)layer); if (ha != null) { historyMementos.Add(ha); } else { Rollback(historyMementos); historyMementos.Clear(); break; } } } if (document != null) { document.Dispose(); document = null; } if (historyMementos.Count > 0) { HistoryMemento[] has = historyMementos.ToArray(); return(new CompoundHistoryMemento(string.Empty, null, has)); } else { lastLayerBounds = Rectangle.Empty; return(null); } }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { int newWidth; int newHeight; // Get new width and Height switch (rotation) { case RotateType.Clockwise90: case RotateType.CounterClockwise90: newWidth = historyWorkspace.Document.Height; newHeight = historyWorkspace.Document.Width; break; case RotateType.Rotate180: newWidth = historyWorkspace.Document.Width; newHeight = historyWorkspace.Document.Height; break; default: throw new InvalidEnumArgumentException("invalid RotateType"); } // Figure out which icon and text to use string iconResName; string suffix; switch (rotation) { case RotateType.Rotate180: iconResName = "Icons.MenuImageRotate180Icon.png"; suffix = PdnResources.GetString("RotateAction.180"); break; case RotateType.Clockwise90: iconResName = "Icons.MenuImageRotate90CWIcon.png"; suffix = PdnResources.GetString("RotateAction.90CW"); break; case RotateType.CounterClockwise90: iconResName = "Icons.MenuImageRotate90CCWIcon.png"; suffix = PdnResources.GetString("RotateAction.90CCW"); break; default: throw new InvalidEnumArgumentException("invalid RotateType"); } // Initialize the new Doc string haNameFormat = PdnResources.GetString("RotateAction.HistoryMementoName.Format"); string haName = string.Format(haNameFormat, StaticName, suffix); ImageResource haImage = PdnResources.GetImageResource(iconResName); List <HistoryMemento> actions = new List <HistoryMemento>(); // do the memory allocation now: if this fails, we can still bail out cleanly Document newDoc = new Document(newWidth, newHeight); if (!historyWorkspace.Selection.IsEmpty) { DeselectFunction da = new DeselectFunction(); EnterCriticalRegion(); HistoryMemento hm = da.Execute(historyWorkspace); actions.Add(hm); } ReplaceDocumentHistoryMemento rdha = new ReplaceDocumentHistoryMemento(null, null, historyWorkspace); actions.Add(rdha); newDoc.ReplaceMetaDataFrom(historyWorkspace.Document); // TODO: serialize oldDoc to disk, and let the GC purge it if needed OnProgress(0.0); for (int i = 0; i < historyWorkspace.Document.Layers.Count; ++i) { Layer layer = historyWorkspace.Document.Layers.GetAt(i); double progressStart = 100.0 * ((double)i / (double)historyWorkspace.Document.Layers.Count); double progressEnd = 100.0 * ((double)(i + 1) / (double)historyWorkspace.Document.Layers.Count); if (layer is BitmapLayer) { Layer nl = RotateLayer((BitmapLayer)layer, rotation, newWidth, newHeight, progressStart, progressEnd); newDoc.Layers.Add(nl); } else { throw new InvalidOperationException("Cannot Rotate non-BitmapLayers"); } if (this.PleaseCancel) { break; } OnProgress(progressEnd); } CompoundHistoryMemento chm = new CompoundHistoryMemento( haName, haImage, actions); if (this.PleaseCancel) { chm = null; } else { EnterCriticalRegion(); historyWorkspace.Document = newDoc; } return(chm); }
public void BeginDrawing(TransactedToolDrawingAgent <TChanges> agent, TChanges initialChanges, HistoryMemento beforeDrawingMemento) { Validate.Begin().IsNotNull <TransactedToolDrawingAgent <TChanges> >(agent, "agent").IsNotNull <TChanges>(initialChanges, "changes").IsNotNull <HistoryMemento>(beforeDrawingMemento, "beforeDrawingMemento").Check(); ((TransactedTool <TDerived, TChanges>) this).VerifyAccess <TransactedTool <TDerived, TChanges> >(); agent.VerifyIsNotActive(); if (this.State != TransactedToolState.Idle) { throw new InvalidOperationException($"Can only BeginDrawing when State is Idle (State={this.State}, Tool={base.GetType().Name})"); } if (this.beforeDrawingMemento != null) { throw new InternalErrorException($"this.beforeDrawingMemento != null (Tool={base.GetType().Name})"); } this.beforeDrawingMemento = beforeDrawingMemento; TransactedToolDrawingTransactionTokenPrivate <TDerived, TChanges> @private = new TransactedToolDrawingTransactionTokenPrivate <TDerived, TChanges>((TDerived)this); agent.TransactionToken = @private; this.drawingAgent = agent; this.SetState(TransactedToolState.Drawing); this.Changes = initialChanges.Clone(); }
public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace) { historyWorkspace.VerifyAccess(); BitmapLayer layer = (BitmapLayer)historyWorkspace.Document.Layers[this.layerIndex]; Surface layerSurface = layer.Surface; TileMathHelper tileMathHelper = new TileMathHelper(layerSurface.Width, layerSurface.Height, this.rendererTileEdgeLog2); TileMathHelper tileGroupMathHelper = new TileMathHelper(layerSurface.Width, layerSurface.Height, this.rendererTileEdgeLog2 + 3); HistoryMemento actionHM = null; ManualResetEvent taskFinishedEvent = new ManualResetEvent(false); ThreadTask <Unit> commitTask = historyWorkspace.TaskManager.StartNewThreadTask(delegate(Task task) { SegmentedList <RectInt32> list = tileGroupMathHelper.EnumerateTilesClippedToSourceRect(this.rendererClipRect).ToSegmentedList <RectInt32>(); ListUtil.FisherYatesShuffle <RectInt32>(list); ConcurrentQueue <ISurface <ColorBgra> > queue = new ConcurrentQueue <ISurface <ColorBgra> >(); ConcurrentQueue <RectInt32> changedTiles = new ConcurrentQueue <RectInt32>(); ConcurrentQueue <TupleStruct <RectInt32, ISurface <ColorBgra> > > changedTileGroups = new ConcurrentQueue <TupleStruct <RectInt32, ISurface <ColorBgra> > >(); double progressIncrement = 1.0 / ((double)Math.Max(1, list.Count)); task.Progress = 0.0; Work.ParallelForEach <RectInt32>(WaitType.Blocking, list, delegate(RectInt32 tileGroupRect) { ISurface <ColorBgra> dst = RetryManager.RunMemorySensitiveOperation <ISurfaceRef <ColorBgra> >(() => SurfaceAllocator.Bgra.Allocate <ColorBgra>(tileGroupRect.Size, AllocationOptions.ZeroFillNotRequired)); this.renderer.Render(dst, tileGroupRect.Location); bool flag = false; foreach (RectInt32 num in tileMathHelper.EnumerateTilesClippedToSourceRect(tileGroupRect)) { RectInt32 bounds = RectInt32.Offset(num, -tileGroupRect.Location); using (ISurface <ColorBgra> surface2 = layerSurface.CreateWindow(num)) { using (ISurface <ColorBgra> surface3 = dst.CreateWindow <ColorBgra>(bounds)) { if (!SurfaceBgraUtil.ArePixelsEqual(surface2, surface3)) { flag = true; changedTiles.Enqueue(num); } } } } if (flag) { changedTileGroups.Enqueue(TupleStruct.Create <RectInt32, ISurface <ColorBgra> >(tileGroupRect, dst)); } else { DisposableUtil.Free <ISurface <ColorBgra> >(ref dst); } task.IncrementProgressBy(progressIncrement); }, WorkItemQueuePriority.Normal, null); task.Progress = null; if (changedTiles.Count == 0) { actionHM = null; } else { SegmentedList <RectInt32> scans = new SegmentedList <RectInt32>(changedTiles.Count, 7); scans.AddRange(changedTiles); ScansHelpers.SortScansByTopLeft(scans); ScansHelpers.ConsolidateSortedScansInPlace(scans); actionHM = new BitmapHistoryMemento(this.historyMementoName, this.historyMementoImage, historyWorkspace, this.layerIndex, scans); this.EnterCriticalRegion(); Work.ParallelForEach <TupleStruct <RectInt32, ISurface <ColorBgra> > >(WaitType.Blocking, changedTileGroups, delegate(TupleStruct <RectInt32, ISurface <ColorBgra> > tileInfo) { using (ISurface <ColorBgra> surface = layerSurface.CreateWindow(tileInfo.Item1)) { tileInfo.Item2.Render(surface, PointInt32.Zero); } tileInfo.Item2.Dispose(); }, WorkItemQueuePriority.Normal, null); foreach (RectInt32 num in scans) { layer.Invalidate(num); } } }, ApartmentState.MTA); commitTask.ResultAsync <Unit>().Receive(delegate(Result <Unit> r) { taskFinishedEvent.Set(); }).Observe(); if (!taskFinishedEvent.WaitOne(this.delayUntilProgressDialogMs)) { string headerText = PdnResources.GetString("ApplyRendererToBitmapLayerHistoryFunction.ProgressDialog.HeaderText"); string headerTextFormat = PdnResources.GetString("ApplyRendererToBitmapLayerHistoryFunction.ProgressDialog.HeaderText.Format"); using (TaskProgressDialog progressDialog = new TaskProgressDialog()) { Action updateHeaderText = delegate { progressDialog.VerifyAccess(); if (!progressDialog.IsDisposed) { string text1; double?progress = commitTask.Progress; if (!progress.HasValue) { text1 = headerText; } else { text1 = string.Format(headerTextFormat, (progress.Value * 100.0).ToString("N0")); } progressDialog.HeaderText = text1; } }; progressDialog.Text = this.historyMementoName; progressDialog.Icon = this.historyMementoImage.Reference.ToIcon(); progressDialog.CloseOnFinished = true; progressDialog.ShowCancelButton = false; progressDialog.Task = commitTask; updateHeaderText(); commitTask.ProgressChanged += delegate(object s, ValueEventArgs <double?> e) { PdnSynchronizationContext.Instance.EnsurePosted(updateHeaderText); }; progressDialog.ShowDialog(historyWorkspace.Window); } } if (!commitTask.TaskResult.IsError) { return(actionHM); } if (commitTask.TaskResult.Error is OutOfMemoryException) { throw new OutOfMemoryException(null, commitTask.TaskResult.Error); } throw new AggregateException(null, commitTask.TaskResult.Error); }
private bool DoEffect(Effect effect, EffectConfigToken token, PdnRegion selectedRegion, PdnRegion regionToRender, Surface originalSurface, out Exception exception) { exception = null; bool oldDirtyValue = AppWorkspace.ActiveDocumentWorkspace.Document.Dirty; bool resetDirtyValue = false; bool returnVal = false; AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = false; try { using (ProgressDialog aed = new ProgressDialog()) { if (effect.Image != null) { aed.Icon = Utility.ImageToIcon(effect.Image, Utility.TransparentKey); } aed.Opacity = 0.9; aed.Value = 0; aed.Text = effect.Name; aed.Description = string.Format(PdnResources.GetString("Effects.ApplyingDialog.Description"), effect.Name); InvalidateTimer.Enabled = true; using (new WaitCursorChanger(AppWorkspace)) { HistoryMemento ha = null; DialogResult result = DialogResult.None; AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar(); AppWorkspace.Widgets.LayerControl.SuspendLayerPreviewUpdates(); try { ManualResetEvent saveEvent = new ManualResetEvent(false); BitmapHistoryMemento bha = null; // perf bug #1445: save this data in a background thread PdnRegion selectedRegionCopy = selectedRegion.Clone(); PaintDotNet.Threading.ThreadPool.Global.QueueUserWorkItem( delegate(object context) { try { ImageResource image = effect.Image == null ? null : ImageResource.FromImage(effect.Image); bha = new BitmapHistoryMemento(effect.Name, image, AppWorkspace.ActiveDocumentWorkspace, AppWorkspace.ActiveDocumentWorkspace.ActiveLayerIndex, selectedRegionCopy, originalSurface); } finally { saveEvent.Set(); selectedRegionCopy.Dispose(); selectedRegionCopy = null; } }); Surface activeLayerSurface = ((BitmapLayer)AppWorkspace.ActiveDocumentWorkspace.ActiveLayer).Surface; int pixelCount = activeLayerSurface.Height; int threadCount = effect.CheckForEffectFlags(EffectFlags.SingleThreaded) ? 1 : RenderingThreadCount; int maxTiles = TilesPerCpu * threadCount; int tileCount = Math.Min(maxTiles, pixelCount); BackgroundEffectRenderer renderer = new BackgroundEffectRenderer( effect, token, new RenderArgs(activeLayerSurface), new RenderArgs(originalSurface), regionToRender, tileCount, threadCount); renderer.RenderedTile += new RenderedTileEventHandler(aed.RenderedTileHandler); renderer.RenderedTile += new RenderedTileEventHandler(RenderedTileHandler); renderer.StartingRendering += new EventHandler(StartingRenderingHandler); renderer.FinishedRendering += new EventHandler(aed.FinishedRenderingHandler); renderer.FinishedRendering += new EventHandler(FinishedRenderingHandler); renderer.Start(); result = Utility.ShowDialog(aed, AppWorkspace); if (result == DialogResult.Cancel) { resetDirtyValue = true; using (new WaitCursorChanger(AppWorkspace)) { try { renderer.Abort(); renderer.Join(); } catch (Exception ex) { exception = ex; } activeLayerSurface.CopySurface(originalSurface); } } InvalidateTimer.Enabled = false; try { renderer.Join(); } catch (Exception ex) { exception = ex; } renderer.Dispose(); saveEvent.WaitOne(); saveEvent.Close(); saveEvent = null; ha = bha; } catch (Exception) { using (new WaitCursorChanger(AppWorkspace)) { ((BitmapLayer)AppWorkspace.ActiveDocumentWorkspace.ActiveLayer).Surface.CopySurface(originalSurface); ha = null; } } finally { AppWorkspace.Widgets.LayerControl.ResumeLayerPreviewUpdates(); } using (PdnRegion simplifiedRenderRegion = Utility.SimplifyAndInflateRegion(selectedRegion)) { using (new WaitCursorChanger(AppWorkspace)) { AppWorkspace.ActiveDocumentWorkspace.ActiveLayer.Invalidate(simplifiedRenderRegion); } } using (new WaitCursorChanger(AppWorkspace)) { if (result == DialogResult.OK) { if (ha != null) { AppWorkspace.ActiveDocumentWorkspace.History.PushNewMemento(ha); } AppWorkspace.Update(); returnVal = true; } else { Utility.GCFullCollect(); } } } // using } // using } finally { AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true; if (resetDirtyValue) { AppWorkspace.ActiveDocumentWorkspace.Document.Dirty = oldDirtyValue; } } AppWorkspace.Widgets.StatusBarProgress.EraseProgressStatusBarAsync(); return(returnVal); }
public static HistoryFunctionResult ApplyFunction(this DocumentWorkspace dw, HistoryFunction function) { HistoryFunctionResult successNoOp; bool flag = false; if ((function.ActionFlags & ActionFlags.KeepToolActive) != ActionFlags.KeepToolActive) { dw.PushNullTool(); dw.Update(); flag = true; } try { using (new WaitCursorChanger(dw)) { string localizedErrorText; HistoryMemento memento = null; Exception exception = null; try { memento = function.Execute(dw); if (memento == null) { successNoOp = HistoryFunctionResult.SuccessNoOp; } else { successNoOp = HistoryFunctionResult.Success; } localizedErrorText = null; } catch (HistoryFunctionNonFatalException exception2) { exception = exception2; if (exception2.InnerException is OutOfMemoryException) { successNoOp = HistoryFunctionResult.OutOfMemory; } else { successNoOp = HistoryFunctionResult.NonFatalError; } if (exception2.LocalizedErrorText != null) { localizedErrorText = exception2.LocalizedErrorText; } else if (exception2.InnerException is OutOfMemoryException) { localizedErrorText = PdnResources.GetString("ExecuteFunction.GenericOutOfMemory"); } else { localizedErrorText = PdnResources.GetString("ExecuteFunction.GenericError"); } } if ((localizedErrorText != null) && (exception != null)) { ExceptionDialog.ShowErrorDialog(dw, localizedErrorText, exception); } else if ((localizedErrorText != null) && (exception == null)) { MessageBoxUtil.ErrorBox(dw, localizedErrorText); } if (memento != null) { dw.History.PushNewMemento(memento); } } } finally { if (flag) { dw.PopNullTool(); } } return(successNoOp); }