/src/Menus/EffectMenuBase.cs
C# | 1039 lines | 807 code | 195 blank | 37 comment | 85 complexity | 14944d9accf0dc5a88c16b2c76671aa7 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 System.Linq;
- using PaintDotNet.Actions;
- using PaintDotNet.Base;
- using PaintDotNet.Effects;
- using PaintDotNet.HistoryMementos;
- using PaintDotNet.SystemLayer;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- using System.IO;
- using System.Reflection;
- using System.Threading;
- using System.Windows.Forms;
-
- namespace PaintDotNet.Menus
- {
- internal abstract class EffectMenuBase
- : PdnMenuItem
- {
- private const int TilesPerCpu = 75;
- private readonly int _renderingThreadCount = Math.Max(2, Processor.LogicalCpuCount);
- private const int EffectRefreshInterval = 15;
- private PdnRegion[] _progressRegions;
- private int _progressRegionsStartIndex;
-
- private PdnMenuItem _sentinel;
- private bool _menuPopulated;
- private EffectsCollection _effects;
-
- private Effect _lastEffect;
- private EffectConfigToken _lastEffectToken;
- private readonly Dictionary<Type, EffectConfigToken> _effectTokens = new Dictionary<Type, EffectConfigToken>();
-
- private System.Windows.Forms.Timer _invalidateTimer;
- private System.ComponentModel.Container _components;
-
- protected abstract bool EnableEffectShortcuts
- {
- get;
- }
-
- protected abstract bool EnableRepeatEffectMenuItem
- {
- get;
- }
-
- protected abstract bool FilterEffects(Effect effect);
-
- private static bool IsBuiltInEffect(Effect effect)
- {
- if (effect == null)
- {
- return true;
- }
-
- Type effectType = effect.GetType();
- Type effectBaseType = typeof(Effect);
-
- // Built-in effects only live in PaintDotNet.Effects.dll
-
- return effectType.Assembly == effectBaseType.Assembly;
- }
-
- private void HandleEffectException(AppWorkspace appWorkspace, Effect effect, Exception ex)
- {
- try
- {
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar();
- AppWorkspace.Widgets.StatusBarProgress.EraseProgressStatusBar();
- }
-
- catch (Exception)
- {
- }
-
- // Figure out if it's a built-in effect, or a plug-in
- bool builtIn = IsBuiltInEffect(effect);
-
- if (builtIn)
- {
- // For built-in effects, tear down Paint.NET which will result in a crash log
- throw new ApplicationException("Effect threw an exception", ex);
- }
- Icon formIcon = Utility.ImageToIcon(PdnResources.GetImageResource("Icons.BugWarning.png").Reference);
-
- string formTitle = PdnResources.GetString("Effect.PluginErrorDialog.Title");
-
- Image taskImage = null;
-
- string introText = PdnResources.GetString("Effect.PluginErrorDialog.IntroText");
-
- var restartTB = new TaskButton(
- PdnResources.GetImageResource("Icons.RightArrowBlue.png").Reference,
- PdnResources.GetString("Effect.PluginErrorDialog.RestartTB.ActionText"),
- PdnResources.GetString("Effect.PluginErrorDialog.RestartTB.ExplanationText"));
-
- var doNotRestartTB = new TaskButton(
- PdnResources.GetImageResource("Icons.WarningIcon.png").Reference,
- PdnResources.GetString("Effect.PluginErrorDialog.DoNotRestartTB.ActionText"),
- PdnResources.GetString("Effect.PluginErrorDialog.DoNotRestartTB.ExplanationText"));
-
- string auxButtonText = PdnResources.GetString("Effect.PluginErrorDialog.AuxButton1.Text");
-
- EventHandler auxButtonClickHandler =
- delegate
- {
- using (var textBoxForm = new PdnBaseForm())
- {
- textBoxForm.Name = "EffectCrash";
-
- var exceptionBox = new TextBox();
-
- textBoxForm.Icon = Utility.ImageToIcon(PdnResources.GetImageResource("Icons.WarningIcon.png").Reference);
- textBoxForm.Text = PdnResources.GetString("Effect.PluginErrorDialog.Title");
-
- exceptionBox.Dock = DockStyle.Fill;
- exceptionBox.ReadOnly = true;
- exceptionBox.Multiline = true;
-
- string exceptionText = AppWorkspace.GetLocalizedEffectErrorMessage(effect.GetType().Assembly, effect.GetType(), ex);
-
- exceptionBox.Font = new Font(FontFamily.GenericMonospace, exceptionBox.Font.Size);
- exceptionBox.Text = exceptionText;
- exceptionBox.ScrollBars = ScrollBars.Vertical;
-
- textBoxForm.StartPosition = FormStartPosition.CenterParent;
- textBoxForm.ShowInTaskbar = false;
- textBoxForm.MinimizeBox = false;
- textBoxForm.Controls.Add(exceptionBox);
- textBoxForm.Width = UI.ScaleWidth(700);
-
- textBoxForm.ShowDialog();
- }
- };
-
- TaskButton clickedTB = TaskDialog.Show(
- appWorkspace,
- formIcon,
- formTitle,
- taskImage,
- true,
- introText,
- new[] { restartTB, doNotRestartTB },
- restartTB,
- doNotRestartTB,
- TaskDialog.DefaultPixelWidth96Dpi * 2,
- auxButtonText,
- auxButtonClickHandler);
-
- if (clickedTB != restartTB) return;
- // Next, apply restart logic
- var cawa = new CloseAllWorkspacesAction();
- cawa.PerformAction(appWorkspace);
-
- if (cawa.Cancelled) return;
- Shell.RestartApplication();
- Startup.CloseApplication();
- }
-
- protected EffectMenuBase()
- {
- InitializeComponent();
- }
-
- private void InitializeComponent()
- {
- _sentinel = new PdnMenuItem {Name = null};
- //
- // sentinel
- //
- //
- // components
- //
- _components = new System.ComponentModel.Container();
- //
- // invalidateTimer
- //
- _invalidateTimer = new System.Windows.Forms.Timer(_components) {Enabled = false};
- _invalidateTimer.Tick += InvalidateTimerTick;
- _invalidateTimer.Interval = EffectRefreshInterval;
- //
- // EffectMenuBase
- //
- DropDownItems.Add(_sentinel);
- }
-
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (_components != null)
- {
- _components.Dispose();
- _components = null;
- }
- }
-
- base.Dispose(disposing);
- }
-
- protected override void OnDropDownOpening(EventArgs e)
- {
- if (!_menuPopulated)
- {
- PopulateMenu();
- }
-
- bool enabled = (AppWorkspace.ActiveDocumentWorkspace != null);
-
- foreach (ToolStripItem item in DropDownItems)
- {
- item.Enabled = enabled;
- }
-
- base.OnDropDownOpening(e);
- }
-
- public EffectsCollection Effects
- {
- get { return _effects ?? (_effects = GatherEffects()); }
- }
-
- public void PopulateEffects()
- {
- PopulateMenu(false);
- }
-
- private void PopulateMenu(bool forceRepopulate)
- {
- if (forceRepopulate)
- {
- _menuPopulated = false;
- }
-
- PopulateMenu();
- }
-
- private void PopulateMenu()
- {
- DropDownItems.Clear();
-
- if (EnableRepeatEffectMenuItem && _lastEffect != null)
- {
- string repeatFormat = PdnResources.GetString("Effects.RepeatMenuItem.Format");
- string menuName = string.Format(repeatFormat, _lastEffect.Name);
- var pmi = new PdnMenuItem(menuName, _lastEffect.Image, RepeatEffectMenuItemClick)
- {
- Name = "RepeatEffect(" + _lastEffect.GetType().FullName + ")",
- ShortcutKeys = Keys.Control | Keys.F
- };
- DropDownItems.Add(pmi);
-
- var tss = new ToolStripSeparator();
- DropDownItems.Add(tss);
- }
-
- AddEffectsToMenu();
-
- Triple<Assembly, Type, Exception>[] errors = Effects.GetLoaderExceptions();
-
- foreach (Triple<Assembly, Type, Exception> t in errors)
- {
- AppWorkspace.ReportEffectLoadError(t);
- }
- }
-
- protected virtual Keys GetEffectShortcutKeys(Effect effect)
- {
- return Keys.None;
- }
-
- private void AddEffectToMenu(Effect effect, bool withShortcut)
- {
- if (!FilterEffects(effect))
- {
- return;
- }
-
- string name = effect.Name;
-
- if (effect.CheckForEffectFlags(EffectFlags.Configurable))
- {
- string configurableFormat = PdnResources.GetString("Effects.Name.Format.Configurable");
- name = string.Format(configurableFormat, name);
- }
-
- var mi = new PdnMenuItem(name, effect.Image, EffectMenuItemClick)
- {
- ShortcutKeys = withShortcut ? GetEffectShortcutKeys(effect) : Keys.None,
- Tag = effect.GetType(),
- Name = "Effect(" + effect.GetType().FullName + ")"
- };
-
- PdnMenuItem addEffectHere = this;
-
- if (effect.SubMenuName != null)
- {
- PdnMenuItem subMenu = DropDownItems.OfType<PdnMenuItem>().FirstOrDefault(subpmi => subpmi.Text == effect.SubMenuName);
-
- // search for this subMenu
-
- if (subMenu == null)
- {
- subMenu = new PdnMenuItem(effect.SubMenuName, null, null);
- DropDownItems.Add(subMenu);
- }
-
- addEffectHere = subMenu;
- }
-
- addEffectHere.DropDownItems.Add(mi);
- }
-
- private void AddEffectsToMenu()
- {
- // Fill the menu with the effect names, and "..." if it is configurable
- EffectsCollection effectsCollection = Effects;
- Type[] effectTypes = effectsCollection.Effects;
- bool withShortcuts = EnableEffectShortcuts;
-
- var newEffects = new List<Effect>();
- foreach (Type type in effectsCollection.Effects)
- {
- try
- {
- ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
- var effect = (Effect)ci.Invoke(null);
-
- if (FilterEffects(effect))
- {
- newEffects.Add(effect);
- }
- }
-
- catch (Exception ex)
- {
- // We don't want a DLL that can't be figured out to cause the app to crash
- //continue;
- AppWorkspace.ReportEffectLoadError(Triple.Create(type.Assembly, type, ex));
- }
- }
-
- newEffects.Sort(
- (lhs, rhs) => string.Compare(lhs.Name, rhs.Name, true));
-
- var subMenuNames = (from effect in newEffects where !string.IsNullOrEmpty(effect.SubMenuName) select effect.SubMenuName).ToList();
-
- subMenuNames.Sort(
- (lhs, rhs) => string.Compare(lhs, rhs, true));
-
- string lastSubMenuName = null;
- foreach (string subMenuName in subMenuNames)
- {
- if (subMenuName == lastSubMenuName)
- {
- // skip duplicate names
- continue;
- }
-
- var subMenu = new PdnMenuItem(subMenuName, null, null);
- DropDownItems.Add(subMenu);
- lastSubMenuName = subMenuName;
- }
-
- foreach (Effect effect in newEffects)
- {
- AddEffectToMenu(effect, withShortcuts);
- }
- }
-
- private static EffectsCollection GatherEffects()
- {
- var assemblies = new List<Assembly> {Assembly.GetAssembly(typeof (Effect))};
-
- // PaintDotNet.Effects.dll
-
- // TARGETDIR\Effects\*.dll
- string homeDir = PdnInfo.GetApplicationDir();
- string effectsDir = Path.Combine(homeDir, InvariantStrings.EffectsSubDir);
- bool dirExists;
-
- try
- {
- dirExists = Directory.Exists(effectsDir);
- }
-
- catch
- {
- dirExists = false;
- }
-
- if (dirExists)
- {
- const string fileSpec = "*" + InvariantStrings.DllExtension;
- string[] filePaths = Directory.GetFiles(effectsDir, fileSpec);
-
- foreach (string filePath in filePaths)
- {
- try
- {
- Assembly pluginAssembly = Assembly.LoadFrom(filePath);
- assemblies.Add(pluginAssembly);
- }
-
- catch (Exception ex)
- {
- Tracing.Ping("Exception while loading " + filePath + ": " + ex.ToString());
- }
- }
- }
-
- var ec = new EffectsCollection(assemblies);
- return ec;
- }
-
- private void RepeatEffectMenuItemClick(object sender, EventArgs e)
- {
- Exception exception = null;
- Effect effect = null;
- DocumentWorkspace activeDW = AppWorkspace.ActiveDocumentWorkspace;
-
- if (activeDW != null)
- {
- using (new PushNullToolMode(activeDW))
- {
- Surface copy = activeDW.BorrowScratchSurface(GetType() + ".RepeatEffectMenuItem_Click() utilizing scratch for rendering");
-
- try
- {
- using (new WaitCursorChanger(AppWorkspace))
- {
- copy.CopySurface(((BitmapLayer)activeDW.ActiveLayer).Surface);
- }
-
- PdnRegion selectedRegion = activeDW.Selection.CreateRegion();
-
- var eep = new EffectEnvironmentParameters(
- AppWorkspace.AppEnvironment.PrimaryColor,
- AppWorkspace.AppEnvironment.SecondaryColor,
- AppWorkspace.AppEnvironment.PenInfo.Width,
- selectedRegion,
- copy);
-
- effect = (Effect)Activator.CreateInstance(_lastEffect.GetType());
- effect.EnvironmentParameters = eep;
-
- EffectConfigToken token;
-
- if (_lastEffectToken == null)
- {
- token = null;
- }
- else
- {
- token = (EffectConfigToken)_lastEffectToken.Clone();
- }
-
- DoEffect(effect, token, selectedRegion, selectedRegion, copy, out exception);
- }
-
- finally
- {
- activeDW.ReturnScratchSurface(copy);
- }
- }
- }
-
- if (exception != null)
- {
- HandleEffectException(AppWorkspace, effect, exception);
- }
- }
-
- private void EffectMenuItemClick(object sender, EventArgs e)
- {
- if (AppWorkspace.ActiveDocumentWorkspace == null)
- {
- return;
- }
-
- var pmi = (PdnMenuItem)sender;
- var effectType = (Type)pmi.Tag;
-
- RunEffect(effectType);
- }
-
- public void RunEffect(Type effectType)
- {
- bool oldDirtyValue = AppWorkspace.ActiveDocumentWorkspace.Document.Dirty;
- bool resetDirtyValue = false;
-
- AppWorkspace.Update(); // make sure the window is done 'closing'
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar();
- DocumentWorkspace activeDW = AppWorkspace.ActiveDocumentWorkspace;
-
- PdnRegion selectedRegion = activeDW.Selection.IsEmpty ? new PdnRegion(activeDW.Document.Bounds) : activeDW.Selection.CreateRegion();
-
- Exception exception = null;
- Effect effect = null;
- var layer = (BitmapLayer)activeDW.ActiveLayer;
-
- using (new PushNullToolMode(activeDW))
- {
- try
- {
- effect = (Effect)Activator.CreateInstance(effectType);
-
- string name = effect.Name;
- EffectConfigToken newLastToken = null;
-
- if (!(effect.CheckForEffectFlags(EffectFlags.Configurable)))
- {
- Surface copy = activeDW.BorrowScratchSurface(GetType() + ".RunEffect() using scratch surface for non-configurable rendering");
-
- try
- {
- using (new WaitCursorChanger(AppWorkspace))
- {
- copy.CopySurface(layer.Surface);
- }
-
- var eep = new EffectEnvironmentParameters(
- AppWorkspace.AppEnvironment.PrimaryColor,
- AppWorkspace.AppEnvironment.SecondaryColor,
- AppWorkspace.AppEnvironment.PenInfo.Width,
- selectedRegion,
- copy);
-
- effect.EnvironmentParameters = eep;
-
- DoEffect(effect, null, selectedRegion, selectedRegion, copy, out exception);
- }
-
- finally
- {
- activeDW.ReturnScratchSurface(copy);
- }
- }
- else
- {
- var previewRegion = selectedRegion.Clone();
- previewRegion.Intersect(RectangleF.Inflate(activeDW.VisibleDocumentRectangleF, 1, 1));
-
- Surface originalSurface = activeDW.BorrowScratchSurface(GetType() + ".RunEffect() using scratch surface for rendering during configuration");
-
- try
- {
- using (new WaitCursorChanger(AppWorkspace))
- {
- originalSurface.CopySurface(layer.Surface);
- }
-
- var eep = new EffectEnvironmentParameters(
- AppWorkspace.AppEnvironment.PrimaryColor,
- AppWorkspace.AppEnvironment.SecondaryColor,
- AppWorkspace.AppEnvironment.PenInfo.Width,
- selectedRegion,
- originalSurface);
-
- effect.EnvironmentParameters = eep;
-
- //
- IDisposable resumeTUFn = AppWorkspace.SuspendThumbnailUpdates();
- //
-
- using (EffectConfigDialog configDialog = effect.CreateConfigDialog())
- {
- configDialog.Opacity = 0.9;
- configDialog.Effect = effect;
- configDialog.EffectSourceSurface = originalSurface;
- configDialog.Selection = selectedRegion;
-
- BackgroundEffectRenderer ber = null;
-
- EventHandler eh =
- delegate(object sender, EventArgs e)
- {
- var ecf = (EffectConfigDialog)sender;
-
- if (ber == null) return;
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBarAsync();
-
- try
- {
- ber.Start();
- }
-
- catch (Exception ex)
- {
- exception = ex;
- ecf.Close();
- }
- };
-
- configDialog.EffectTokenChanged += eh;
-
- if (_effectTokens.ContainsKey(effectType))
- {
- var oldToken = (EffectConfigToken)_effectTokens[effectType].Clone();
- configDialog.EffectToken = oldToken;
- }
-
- ber = new BackgroundEffectRenderer(
- effect,
- configDialog.EffectToken,
- new RenderArgs(layer.Surface),
- new RenderArgs(originalSurface),
- previewRegion,
- TilesPerCpu * _renderingThreadCount,
- _renderingThreadCount);
-
- ber.RenderedTile += RenderedTileHandler;
- ber.StartingRendering += StartingRenderingHandler;
- ber.FinishedRendering += FinishedRenderingHandler;
-
- _invalidateTimer.Enabled = true;
-
- DialogResult dr;
-
- try
- {
- dr = Utility.ShowDialog(configDialog, AppWorkspace);
- }
-
- catch (Exception ex)
- {
- dr = DialogResult.None;
- exception = ex;
- }
-
- _invalidateTimer.Enabled = false;
-
- InvalidateTimerTick(_invalidateTimer, EventArgs.Empty);
-
- if (dr == DialogResult.OK)
- {
- _effectTokens[effectType] = (EffectConfigToken)configDialog.EffectToken.Clone();
- }
-
- using (new WaitCursorChanger(AppWorkspace))
- {
- try
- {
- ber.Abort();
- ber.Join();
- }
-
- catch (Exception ex)
- {
- exception = ex;
- }
-
- ber.Dispose();
- ber = null;
-
- if (dr != DialogResult.OK)
- {
- ((BitmapLayer)activeDW.ActiveLayer).Surface.CopySurface(originalSurface);
- activeDW.ActiveLayer.Invalidate();
- }
-
- configDialog.EffectTokenChanged -= eh;
- configDialog.Hide();
- AppWorkspace.Update();
- previewRegion.Dispose();
- }
-
- //
- resumeTUFn.Dispose();
- resumeTUFn = null;
- //
-
- if (dr == DialogResult.OK)
- {
- PdnRegion remainingToRender = selectedRegion.Clone();
- PdnRegion alreadyRendered = PdnRegion.CreateEmpty();
-
- foreach (PdnRegion t in _progressRegions.TakeWhile(t => t != null))
- {
- remainingToRender.Exclude(t);
- alreadyRendered.Union(t);
- }
-
- activeDW.ActiveLayer.Invalidate(alreadyRendered);
- newLastToken = (EffectConfigToken)configDialog.EffectToken.Clone();
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar();
- DoEffect(effect, newLastToken, selectedRegion, remainingToRender, originalSurface, out exception);
- }
- else // if (dr == DialogResult.Cancel)
- {
- using (new WaitCursorChanger(AppWorkspace))
- {
- activeDW.ActiveLayer.Invalidate();
- Utility.GCFullCollect();
- }
-
- resetDirtyValue = true;
- return;
- }
- }
- }
-
- catch (Exception ex)
- {
- exception = ex;
- }
-
- finally
- {
- activeDW.ReturnScratchSurface(originalSurface);
- }
- }
-
- // if it was from the Effects menu, save it as the "Repeat ...." item
- if (effect.Category == EffectCategory.Effect)
- {
- _lastEffect = effect;
-
- if (newLastToken == null)
- {
- _lastEffectToken = null;
- }
- else
- {
- _lastEffectToken = (EffectConfigToken)newLastToken.Clone();
- }
-
- PopulateMenu(true);
- }
- }
-
- catch (Exception ex)
- {
- exception = ex;
- }
-
- finally
- {
- selectedRegion.Dispose();
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar();
- AppWorkspace.Widgets.StatusBarProgress.EraseProgressStatusBar();
- AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true;
-
- if (_progressRegions != null)
- {
- for (int i = 0; i < _progressRegions.Length; ++i)
- {
- if (_progressRegions[i] == null) continue;
- _progressRegions[i].Dispose();
- _progressRegions[i] = null;
- }
- }
-
- if (resetDirtyValue)
- {
- AppWorkspace.ActiveDocumentWorkspace.Document.Dirty = oldDirtyValue;
- }
-
- if (exception != null)
- {
- HandleEffectException(AppWorkspace, effect, exception);
- }
- }
- }
- }
-
- private void RenderedTileHandler(object sender, RenderedTileEventArgs e)
- {
- if (_progressRegions[e.TileNumber] == null)
- {
- _progressRegions[e.TileNumber] = e.RenderedRegion;
- }
- }
-
- private void InvalidateTimerTick(object sender, EventArgs e)
- {
- if (AppWorkspace.FindForm().WindowState == FormWindowState.Minimized)
- {
- return;
- }
-
- if (_progressRegions == null)
- {
- return;
- }
-
- lock (_progressRegions)
- {
- int min = _progressRegionsStartIndex;
- int max;
-
- for (max = min; max < _progressRegions.Length; ++max)
- {
- if (_progressRegions[max] == null)
- {
- break;
- }
- }
-
- if (min != max)
- {
- using (PdnRegion updateRegion = PdnRegion.CreateEmpty())
- {
- for (int i = min; i < max; ++i)
- {
- updateRegion.Union(_progressRegions[i]);
- }
-
- using (PdnRegion simplified = Utility.SimplifyAndInflateRegion(updateRegion))
- {
- AppWorkspace.ActiveDocumentWorkspace.ActiveLayer.Invalidate(simplified);
- }
-
- _progressRegionsStartIndex = max;
- }
- }
-
- double progress = 100.0 * (double)max / (double)_progressRegions.Length;
- AppWorkspace.Widgets.StatusBarProgress.SetProgressStatusBar(progress);
- }
- }
-
- private void FinishedRenderingHandler(object sender, EventArgs e)
- {
- if (AppWorkspace.InvokeRequired)
- {
- AppWorkspace.BeginInvoke(new EventHandler(FinishedRenderingHandler), new[] { sender, e });
- }
- else
- {
- AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true;
- }
- }
-
- private void StartingRenderingHandler(object sender, EventArgs e)
- {
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBarAsync();
- AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = false;
-
- if (_progressRegions == null)
- {
- _progressRegions = new PdnRegion[TilesPerCpu * _renderingThreadCount];
- }
-
- lock (_progressRegions)
- {
- for (int i = 0; i < _progressRegions.Length; ++i)
- {
- _progressRegions[i] = null;
- }
-
- _progressRegionsStartIndex = 0;
- }
- }
-
- private void 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;
-
- AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = false;
-
- try
- {
- using (var 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;
- DialogResult result = DialogResult.None;
-
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBar();
- AppWorkspace.Widgets.LayerControl.SuspendLayerPreviewUpdates();
-
- try
- {
- var saveEvent = new ManualResetEvent(false);
- BitmapHistoryMemento bha = null;
-
- // perf bug #1445: save this data in a background thread
- PdnRegion selectedRegionCopy = selectedRegion.Clone();
- Threading.ThreadPool.Global.QueueUserWorkItem(
- delegate
- {
- 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;
- }
- });
-
- var ber = new BackgroundEffectRenderer(
- effect,
- token,
- new RenderArgs(((BitmapLayer)AppWorkspace.ActiveDocumentWorkspace.ActiveLayer).Surface),
- new RenderArgs(originalSurface),
- regionToRender,
- TilesPerCpu * _renderingThreadCount,
- _renderingThreadCount);
-
- ber.RenderedTile += aed.RenderedTileHandler;
- ber.RenderedTile += RenderedTileHandler;
- ber.StartingRendering += StartingRenderingHandler;
- ber.FinishedRendering += aed.FinishedRenderingHandler;
- ber.FinishedRendering += FinishedRenderingHandler;
- ber.Start();
-
- result = Utility.ShowDialog(aed, AppWorkspace);
-
- if (result == DialogResult.Cancel)
- {
- resetDirtyValue = true;
-
- using (new WaitCursorChanger(AppWorkspace))
- {
- try
- {
- ber.Abort();
- ber.Join();
- }
-
- catch (Exception ex)
- {
- exception = ex;
- }
-
- ((BitmapLayer)AppWorkspace.ActiveDocumentWorkspace.ActiveLayer).Surface.CopySurface(originalSurface);
- }
- }
-
- _invalidateTimer.Enabled = false;
-
- try
- {
- ber.Join();
- }
-
- catch (Exception ex)
- {
- exception = ex;
- }
-
- ber.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();
- }
- else
- {
- Utility.GCFullCollect();
- }
- }
- } // using
- } // using
- }
-
- finally
- {
- AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true;
-
- if (resetDirtyValue)
- {
- AppWorkspace.ActiveDocumentWorkspace.Document.Dirty = oldDirtyValue;
- }
- }
-
- AppWorkspace.Widgets.StatusBarProgress.EraseProgressStatusBarAsync();
- return;
- }
- }
- }