Wrappers/WatchedExplorer.cs
author Thomas
Thu, 06 Sep 2018 09:29:19 +0200
branchOUT-497
changeset 2359 0e6191d039e4
parent 2293 2dd69aea9675
child 2360 f01523e581fa
permissions -rw-r--r--
Major restructuration: - Remove FormRegionPrivacyStatus - Create new WatchedWindow as base class for WatchedExplorers and WatchedInspectors - Move all logic from FormRegionPrivacy to WatchedWindow - Use Explorer.SelectionChanged and Inspectors.Newinspector events instead of FormRegionPrivacyStatus.FormRegionShowing to detect opening of mail item. - Rework of RibbonCustomizations. State of pEp button now stored in WatchedWindow instead of FormRegionPrivacyStatus

´╗┐using System;
using Outlook = Microsoft.Office.Interop.Outlook;

namespace pEp
{
    /// <summary>
    /// Stores an Outlook Explorer with connected events.
    /// </summary>
    public class WatchedExplorer : WatchedWindow
    {
        private Outlook.Explorer        _Explorer               = null;

        private string                  lastProcessedEntryId    = null;
        private CryptableMailItem       inlineResponseItem      = null;

        /**************************************************************
         * 
         * Constructors/Destructors
         * 
         *************************************************************/

        /// <summary>
        /// Primary constructor.
        /// </summary>
        /// <param name="explorer">The explorer to watch.</param>
        public WatchedExplorer(Outlook.Explorer explorer)
        {
            this._Explorer = explorer;

            if (this._Explorer != null)
            {
                this.ConnectWatchedExplorerEvents(true);
            }
        }

        #region Properties

        /// <summary>
        /// Gets the Explorer that is wrapped by this WatchedExplorer.
        /// </summary>
        public Outlook.Explorer Explorer
        {
            get { return this._Explorer; }
        }

        /// <summary>
        /// Gets the Explorer that is wrapped by this WatchedExplorer.
        /// </summary>
        public override dynamic Window
        {
            get { return this.Explorer; }
        }

        #endregion

        #region Methods

        /**************************************************************
         * 
         * Methods
         * 
         *************************************************************/

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Disconnect all events
                this.ConnectWatchedExplorerEvents(false);

                // Set Outlook objects to null
                this._Explorer = null;

                // Dispose base class
                base.Dispose(disposing);
            }
        }

        /// <summary>
        /// Connects the events for this watched explorer.
        /// <param name="connect">Whether to connect or disconnect the events.</param>
        /// </summary>
        private void ConnectWatchedExplorerEvents(bool connect)
        {
            try
            {
                if (connect)
                {
                    ((Outlook.ExplorerEvents_10_Event)this._Explorer).Close += Explorer_Close;
                    ((Outlook.ExplorerEvents_10_Event)this._Explorer).InlineResponseClose += Explorer_InlineResponseClose;
                    ((Outlook.ExplorerEvents_10_Event)this._Explorer).SelectionChange += Explorer_SelectionChange;
                }
                else
                {
                    ((Outlook.ExplorerEvents_10_Event)this._Explorer).Close -= Explorer_Close;
                    ((Outlook.ExplorerEvents_10_Event)this._Explorer).InlineResponseClose -= Explorer_InlineResponseClose;
                    ((Outlook.ExplorerEvents_10_Event)this._Explorer).SelectionChange -= Explorer_SelectionChange;
                }
            }
            catch (Exception ex)
            {
                Log.Error("ConnectWatchedExplorerEvents: Error occured. " + ex.ToString());
            }
        }
        #endregion

        #region Event Handling
        /**************************************************************
         * 
         * Event Handling
         * 
         *************************************************************/

        /// <summary>
        /// Event handler for when a watched explorer is being closed.
        /// </summary>
        private void Explorer_Close()
        {
            Globals.ThisAddIn.RemoveFromWatchedExplorers(this);
            this.Dispose();
        }

        /// <summary>
        /// Event handler for when an inline response is being closed.
        /// </summary>
        private void Explorer_InlineResponseClose()
        {
            Outlook.MailItem omi = null;

            /* Create a new CryptableMailItem. This is needed so that its
             * MailItem_Write event gets called and the message will get saved
             * securely instead of to the server's draft folder.
             * Note: the form region's CMI is already disposed at this point,
             * so that its Write event will never be called.
             */
            try
            {
                omi = this._Explorer?.ActiveInlineResponse as Outlook.MailItem;

                if (omi != null)
                {
                    this.inlineResponseItem = new CryptableMailItem(omi, null, false);
                    this.inlineResponseItem.IsInlineResponse = true;
                }
            }
            catch (Exception ex)
            {
                Log.Error("WatchedExplorer_InlineResponseClose: Error setting new inline response item. " + ex.ToString());
            }
            finally
            {
                omi = null;
            }
        }

        private void Explorer_SelectionChange()
        {
            Outlook.Selection selection = null;
            try
            {
                // Process the newly selected item
                selection = this._Explorer.Selection;

                /* Do only process the item if one individual item is selected.
                 * Do not process a selected range of items.
                 */
                if (selection.Count == 1)
                {
                    this.CurrentMailItem = selection[1] as Outlook.MailItem;
                    if (this.CurrentMailItem != null)
                    {
                        // Check if inline response
                        Outlook.MailItem inlineResponse = null;
                        bool isInlineResponse = false;
                        try
                        {
                            inlineResponse = this._Explorer?.ActiveInlineResponse as Outlook.MailItem;
                            if (inlineResponse != null)
                            {
                                isInlineResponse = true;
                                this.CurrentMailItem = inlineResponse;
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.Error("Explorer_SelectionChange: Error determining whether it is an inline response. " + ex.ToString());
                        }
                        finally
                        {
                            inlineResponse = null;
                        }

                        /* If a different mail is clicked in an Window, the SelectionChange
                         * event is always called twice. To prevent a double processing, we only
                         * process a mail item if it is different from the last one that has been
                         * processed.
                         */
                        string entryId = isInlineResponse ? null : this.CurrentMailItem?.EntryID;
                        if (entryId?.Equals(lastProcessedEntryId, StringComparison.InvariantCultureIgnoreCase) == true)
                        {
                            Log.Verbose("Explorer_SelectionChange: Same EntryId as last item. Skipped processing of item with EntryId " + entryId);
                            return;
                        }
                        else
                        {
                            this.lastProcessedEntryId = entryId;
                        }

                        // Initialize mail item
                        this.InitializeMailItem(isInlineResponse);
                    }
                    else
                    {
                        Log.Error("Explorer_SelectionChange: Error getting current mail item.");
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error("Explorer_SelectionChange: Error. " + e.Message);
            }
            finally
            {
                selection = null;
            }
        }
        #endregion
    }
}