/src/Menus/EffectMenuBase.cs
C# | 1130 lines | 890 code | 203 blank | 37 comment | 98 complexity | 9ab625413570c564abe4fc795ed4f164 MD5 | raw file
Possible License(s): Unlicense
- /////////////////////////////////////////////////////////////////////////////////
- // 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.Actions;
- 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.Runtime.InteropServices;
- using System.Text;
- using System.Threading;
- using System.Windows.Forms;
-
- namespace PaintDotNet.Menus
- {
- internal abstract class EffectMenuBase
- : PdnMenuItem
- {
- private const int tilesPerCpu = 75;
- private int renderingThreadCount = Math.Max(2, SystemLayer.Processor.LogicalCpuCount);
- private const int effectRefreshInterval = 15;
- private PdnRegion[] progressRegions;
- private int progressRegionsStartIndex;
-
- private PdnMenuItem sentinel;
- private bool menuPopulated = false;
- private EffectsCollection effects;
-
- private Effect lastEffect = null;
- private EffectConfigToken lastEffectToken = null;
- private Dictionary<Type, EffectConfigToken> effectTokens = new Dictionary<Type, EffectConfigToken>();
-
- private System.Windows.Forms.Timer invalidateTimer;
- private System.ComponentModel.Container components = null;
-
- protected abstract bool EnableEffectShortcuts
- {
- get;
- }
-
- protected abstract bool EnableRepeatEffectMenuItem
- {
- get;
- }
-
- protected abstract bool FilterEffects(Effect effect);
-
- private 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
-
- if (effectType.Assembly == effectBaseType.Assembly)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
-
- 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);
- }
- else
- {
- 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");
-
- TaskButton restartTB = new TaskButton(
- PdnResources.GetImageResource("Icons.RightArrowBlue.png").Reference,
- PdnResources.GetString("Effect.PluginErrorDialog.RestartTB.ActionText"),
- PdnResources.GetString("Effect.PluginErrorDialog.RestartTB.ExplanationText"));
-
- TaskButton 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(object sender, EventArgs e)
- {
- using (PdnBaseForm textBoxForm = new PdnBaseForm())
- {
- textBoxForm.Name = "EffectCrash";
-
- TextBox 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 TaskButton[] { restartTB, doNotRestartTB },
- restartTB,
- doNotRestartTB,
- TaskDialog.DefaultPixelWidth96Dpi * 2,
- auxButtonText,
- auxButtonClickHandler);
-
- if (clickedTB == restartTB)
- {
- // Next, apply restart logic
- CloseAllWorkspacesAction cawa = new CloseAllWorkspacesAction();
- cawa.PerformAction(appWorkspace);
-
- if (!cawa.Cancelled)
- {
- SystemLayer.Shell.RestartApplication();
- Startup.CloseApplication();
- }
- }
- }
- }
-
- public EffectMenuBase()
- {
- InitializeComponent();
- }
-
- private void InitializeComponent()
- {
- this.sentinel = new PdnMenuItem();
- //
- // sentinel
- //
- this.sentinel.Name = null;
- //
- // components
- //
- this.components = new System.ComponentModel.Container();
- //
- // invalidateTimer
- //
- this.invalidateTimer = new System.Windows.Forms.Timer(this.components);
- this.invalidateTimer.Enabled = false;
- this.invalidateTimer.Tick += InvalidateTimer_Tick;
- this.invalidateTimer.Interval = effectRefreshInterval;
- //
- // EffectMenuBase
- //
- this.DropDownItems.Add(sentinel);
- }
-
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (this.components != null)
- {
- this.components.Dispose();
- this.components = null;
- }
- }
-
- base.Dispose(disposing);
- }
-
- protected override void OnDropDownOpening(EventArgs e)
- {
- if (!this.menuPopulated)
- {
- PopulateMenu();
- }
-
- bool enabled = (AppWorkspace.ActiveDocumentWorkspace != null);
-
- foreach (ToolStripItem item in this.DropDownItems)
- {
- item.Enabled = enabled;
- }
-
- base.OnDropDownOpening(e);
- }
-
- public EffectsCollection Effects
- {
- get
- {
- if (this.effects == null)
- {
- this.effects = GatherEffects();
- }
-
- return this.effects;
- }
- }
-
- public void PopulateEffects()
- {
- PopulateMenu(false);
- }
-
- private void PopulateMenu(bool forceRepopulate)
- {
- if (forceRepopulate)
- {
- this.menuPopulated = false;
- }
-
- PopulateMenu();
- }
-
- private void PopulateMenu()
- {
- this.DropDownItems.Clear();
-
- if (EnableRepeatEffectMenuItem && this.lastEffect != null)
- {
- string repeatFormat = PdnResources.GetString("Effects.RepeatMenuItem.Format");
- string menuName = string.Format(repeatFormat, lastEffect.Name);
- PdnMenuItem pmi = new PdnMenuItem(menuName, this.lastEffect.Image, RepeatEffectMenuItem_Click);
- pmi.Name = "RepeatEffect(" + this.lastEffect.GetType().FullName + ")";
- pmi.ShortcutKeys = Keys.Control | Keys.F;
- this.DropDownItems.Add(pmi);
-
- ToolStripSeparator tss = new ToolStripSeparator();
- this.DropDownItems.Add(tss);
- }
-
- AddEffectsToMenu();
-
- Triple<Assembly, Type, Exception>[] errors = this.Effects.GetLoaderExceptions();
-
- for (int i = 0; i < errors.Length; ++i)
- {
- AppWorkspace.ReportEffectLoadError(errors[i]);
- }
- }
-
- 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);
- }
-
- PdnMenuItem mi = new PdnMenuItem(name, effect.Image, EffectMenuItem_Click);
-
- if (withShortcut)
- {
- mi.ShortcutKeys = GetEffectShortcutKeys(effect);
- }
- else
- {
- mi.ShortcutKeys = Keys.None;
- }
-
- mi.Tag = (object)effect.GetType();
- mi.Name = "Effect(" + effect.GetType().FullName + ")";
-
- PdnMenuItem addEffectHere = this;
-
- if (effect.SubMenuName != null)
- {
- PdnMenuItem subMenu = null;
-
- // search for this subMenu
- foreach (ToolStripItem sub in this.DropDownItems)
- {
- PdnMenuItem subpmi = sub as PdnMenuItem;
-
- if (subpmi != null)
- {
- if (subpmi.Text == effect.SubMenuName)
- {
- subMenu = subpmi;
- break;
- }
- }
- }
-
- if (subMenu == null)
- {
- subMenu = new PdnMenuItem(effect.SubMenuName, null, null);
- this.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 = this.Effects;
- Type[] effectTypes = effectsCollection.Effects;
- bool withShortcuts = EnableEffectShortcuts;
-
- List<Effect> newEffects = new List<Effect>();
- foreach (Type type in effectsCollection.Effects)
- {
- try
- {
- ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
- Effect 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(
- delegate(Effect lhs, Effect rhs)
- {
- return string.Compare(lhs.Name, rhs.Name, true);
- });
-
- List<string> subMenuNames = new List<string>();
-
- foreach (Effect effect in newEffects)
- {
- if (!string.IsNullOrEmpty(effect.SubMenuName))
- {
- subMenuNames.Add(effect.SubMenuName);
- }
- }
-
- subMenuNames.Sort(
- delegate(string lhs, string rhs)
- {
- return string.Compare(lhs, rhs, true);
- });
-
- string lastSubMenuName = null;
- foreach (string subMenuName in subMenuNames)
- {
- if (subMenuName == lastSubMenuName)
- {
- // skip duplicate names
- continue;
- }
-
- PdnMenuItem subMenu = new PdnMenuItem(subMenuName, null, null);
- DropDownItems.Add(subMenu);
- lastSubMenuName = subMenuName;
- }
-
- foreach (Effect effect in newEffects)
- {
- AddEffectToMenu(effect, withShortcuts);
- }
- }
-
- private static EffectsCollection GatherEffects()
- {
- List<Assembly> assemblies = new List<Assembly>();
-
- // PaintDotNet.Effects.dll
- assemblies.Add(Assembly.GetAssembly(typeof(Effect)));
-
- // 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)
- {
- string fileSpec = "*" + InvariantStrings.DllExtension;
- string[] filePaths = Directory.GetFiles(effectsDir, fileSpec);
-
- foreach (string filePath in filePaths)
- {
- Assembly pluginAssembly = null;
-
- try
- {
- pluginAssembly = Assembly.LoadFrom(filePath);
- assemblies.Add(pluginAssembly);
- }
-
- catch (Exception ex)
- {
- Tracing.Ping("Exception while loading " + filePath + ": " + ex.ToString());
- }
- }
- }
-
- EffectsCollection ec = new EffectsCollection(assemblies);
- return ec;
- }
-
- private void RepeatEffectMenuItem_Click(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(this.GetType() + ".RepeatEffectMenuItem_Click() utilizing scratch for rendering");
-
- try
- {
- using (new WaitCursorChanger(AppWorkspace))
- {
- copy.CopySurface(((BitmapLayer)activeDW.ActiveLayer).Surface);
- }
-
- PdnRegion selectedRegion = activeDW.Selection.CreateRegion();
-
- EffectEnvironmentParameters eep = new EffectEnvironmentParameters(
- AppWorkspace.AppEnvironment.PrimaryColor,
- AppWorkspace.AppEnvironment.SecondaryColor,
- AppWorkspace.AppEnvironment.PenInfo.Width,
- selectedRegion,
- copy);
-
- effect = (Effect)Activator.CreateInstance(this.lastEffect.GetType());
- effect.EnvironmentParameters = eep;
-
- EffectConfigToken token;
-
- if (this.lastEffectToken == null)
- {
- token = null;
- }
- else
- {
- token = (EffectConfigToken)this.lastEffectToken.Clone();
- }
-
- DoEffect(effect, token, selectedRegion, selectedRegion, copy, out exception);
- }
-
- finally
- {
- activeDW.ReturnScratchSurface(copy);
- }
- }
- }
-
- if (exception != null)
- {
- HandleEffectException(AppWorkspace, effect, exception);
- }
- }
-
- private void EffectMenuItem_Click(object sender, EventArgs e)
- {
- if (AppWorkspace.ActiveDocumentWorkspace == null)
- {
- return;
- }
-
- PdnMenuItem pmi = (PdnMenuItem)sender;
- Type 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;
-
- if (activeDW.Selection.IsEmpty)
- {
- selectedRegion = new PdnRegion(activeDW.Document.Bounds);
- }
- else
- {
- selectedRegion = activeDW.Selection.CreateRegion();
- }
-
- Exception exception = null;
- Effect effect = null;
- BitmapLayer 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(this.GetType() + ".RunEffect() using scratch surface for non-configurable rendering");
-
- try
- {
- using (new WaitCursorChanger(AppWorkspace))
- {
- copy.CopySurface(layer.Surface);
- }
-
- EffectEnvironmentParameters 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
- {
- PdnRegion previewRegion = (PdnRegion)selectedRegion.Clone();
- previewRegion.Intersect(RectangleF.Inflate(activeDW.VisibleDocumentRectangleF, 1, 1));
-
- Surface originalSurface = activeDW.BorrowScratchSurface(this.GetType() + ".RunEffect() using scratch surface for rendering during configuration");
-
- try
- {
- using (new WaitCursorChanger(AppWorkspace))
- {
- originalSurface.CopySurface(layer.Surface);
- }
-
- EffectEnvironmentParameters 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)
- {
- EffectConfigDialog ecf = (EffectConfigDialog)sender;
-
- if (ber != null)
- {
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBarAsync();
-
- try
- {
- ber.Start();
- }
-
- catch (Exception ex)
- {
- exception = ex;
- ecf.Close();
- }
- }
- };
-
- configDialog.EffectTokenChanged += eh;
-
- if (this.effectTokens.ContainsKey(effectType))
- {
- EffectConfigToken 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 += new RenderedTileEventHandler(RenderedTileHandler);
- ber.StartingRendering += new EventHandler(StartingRenderingHandler);
- ber.FinishedRendering += new EventHandler(FinishedRenderingHandler);
-
- invalidateTimer.Enabled = true;
-
- DialogResult dr;
-
- try
- {
- dr = Utility.ShowDialog(configDialog, AppWorkspace);
- }
-
- catch (Exception ex)
- {
- dr = DialogResult.None;
- exception = ex;
- }
-
- invalidateTimer.Enabled = false;
-
- this.InvalidateTimer_Tick(invalidateTimer, EventArgs.Empty);
-
- if (dr == DialogResult.OK)
- {
- this.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();
-
- for (int i = 0; i < this.progressRegions.Length; ++i)
- {
- if (this.progressRegions[i] == null)
- {
- break;
- }
- else
- {
- remainingToRender.Exclude(this.progressRegions[i]);
- alreadyRendered.Union(this.progressRegions[i]);
- }
- }
-
- 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)
- {
- this.lastEffect = effect;
-
- if (newLastToken == null)
- {
- this.lastEffectToken = null;
- }
- else
- {
- this.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 (this.progressRegions != null)
- {
- for (int i = 0; i < this.progressRegions.Length; ++i)
- {
- if (this.progressRegions[i] != null)
- {
- this.progressRegions[i].Dispose();
- this.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 (this.progressRegions[e.TileNumber] == null)
- {
- this.progressRegions[e.TileNumber] = e.RenderedRegion;
- }
- }
-
- private void InvalidateTimer_Tick(object sender, System.EventArgs e)
- {
- if (AppWorkspace.FindForm().WindowState == FormWindowState.Minimized)
- {
- return;
- }
-
- if (this.progressRegions == null)
- {
- return;
- }
-
- lock (this.progressRegions)
- {
- int min = this.progressRegionsStartIndex;
- int max;
-
- for (max = min; max < progressRegions.Length; ++max)
- {
- if (this.progressRegions[max] == null)
- {
- break;
- }
- }
-
- if (min != max)
- {
- using (PdnRegion updateRegion = PdnRegion.CreateEmpty())
- {
- for (int i = min; i < max; ++i)
- {
- updateRegion.Union(this.progressRegions[i]);
- }
-
- using (PdnRegion simplified = Utility.SimplifyAndInflateRegion(updateRegion))
- {
- AppWorkspace.ActiveDocumentWorkspace.ActiveLayer.Invalidate(simplified);
- }
-
- this.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 object[] { sender, e });
- }
- else
- {
- AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = true;
- }
- }
-
- private void StartingRenderingHandler(object sender, EventArgs e)
- {
- AppWorkspace.Widgets.StatusBarProgress.ResetProgressStatusBarAsync();
- AppWorkspace.ActiveDocumentWorkspace.EnableOutlineAnimation = false;
-
- if (this.progressRegions == null)
- {
- this.progressRegions = new PdnRegion[tilesPerCpu * renderingThreadCount];
- }
-
- lock (this.progressRegions)
- {
- for (int i = 0; i < progressRegions.Length; ++i)
- {
- progressRegions[i] = null;
- }
-
- this.progressRegionsStartIndex = 0;
- }
- }
-
- 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;
-
- if (effect.Image == null)
- {
- image = null;
- }
- else
- {
- image = ImageResource.FromImage(effect.Image);
- }
-
- bha = new BitmapHistoryMemento(effect.Name, image, this.AppWorkspace.ActiveDocumentWorkspace,
- this.AppWorkspace.ActiveDocumentWorkspace.ActiveLayerIndex, selectedRegionCopy, originalSurface);
- }
-
- finally
- {
- saveEvent.Set();
- selectedRegionCopy.Dispose();
- selectedRegionCopy = null;
- }
- });
-
- BackgroundEffectRenderer ber = new BackgroundEffectRenderer(
- effect,
- token,
- new RenderArgs(((BitmapLayer)AppWorkspace.ActiveDocumentWorkspace.ActiveLayer).Surface),
- new RenderArgs(originalSurface),
- regionToRender,
- tilesPerCpu * renderingThreadCount,
- renderingThreadCount);
-
- ber.RenderedTile += new RenderedTileEventHandler(aed.RenderedTileHandler);
- ber.RenderedTile += new RenderedTileEventHandler(RenderedTileHandler);
- ber.StartingRendering += new EventHandler(StartingRenderingHandler);
- ber.FinishedRendering += new EventHandler(aed.FinishedRenderingHandler);
- ber.FinishedRendering += new EventHandler(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();
- 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;
- }
- }
- }