EffectMenuBase.cs :  » GUI » Paint.net » PaintDotNet » Menus » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » GUI » Paint.net 
Paint.net » PaintDotNet » Menus » EffectMenuBase.cs
/////////////////////////////////////////////////////////////////////////////////
// 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;
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.