/// Copyright 2016 Kopano b.v. /// /// This program is free software: you can redistribute it and/or modify /// it under the terms of the GNU Affero General Public License, version 3, /// as published by the Free Software Foundation. /// /// This program is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the /// GNU Affero General Public License for more details. /// /// You should have received a copy of the GNU Affero General Public License /// along with this program.If not, see. /// /// Consult LICENSE file for details using Microsoft.Office.Interop.Outlook; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Acacia.UI; using Acacia.Utils; using System.Windows.Forms; using Acacia.ZPush; using System.ComponentModel; using Acacia.Features.DebugSupport; using Microsoft.Win32; using Acacia.UI.Outlook; using Acacia.Stubs; namespace Acacia.Features { /// /// A feature represents a modular piece of functionality that can be enabled in the plugin. /// As all hooks must be registered from the same callback (Startup in ThisAddIn), the /// Feature class is used to allow modules to register their hooks. /// [TypeConverter(typeof(FeatureObjectConverter))] abstract public class Feature : LogContext { public readonly string Name; protected Feature() { this.Name = GetFeatureName(GetType()); } [Browsable(false)] public string DisplayName { get { return StringUtil.GetResourceString("Feature_" + Name); } } public virtual FeatureSettings GetSettings() { return null; } protected static Microsoft.Office.Interop.Outlook.Application App { get { return ThisAddIn.Instance.Application; } } #region Debug options public static string GetFeatureName(Type featureType) { return featureType.Name.StripPrefix("Feature"); } public static string GetDebugTokens(Type featureType) { return DebugOptions.GetOptions(GetFeatureName(featureType)); } public static bool IsEnabled(Type featureType) { bool defaultEnabled = !typeof(FeatureDisabled).IsAssignableFrom(featureType); return DebugOptions.GetOption(GetFeatureName(featureType), defaultEnabled ? DebugOptions.ENABLED : DebugOptions.FEATURE_DISABLED_DEFAULT); } public ValueType GetOption(DebugOptions.Option option) { return DebugOptions.GetOption(Name, option); } public static ValueType GetOption(Type featureType, DebugOptions.Option option) { return DebugOptions.GetOption(GetFeatureName(featureType), option); } public void SetOption(DebugOptions.Option option, ValueType value) { DebugOptions.SetOption(Name, option, value); } public static void SetOption(Type featureType, DebugOptions.Option option, ValueType value) { DebugOptions.SetOption(GetFeatureName(featureType), option, value); } [AcaciaOption("Completely enables or disables the feature. Note that if the feature is enabled, it's components may still be disabled")] virtual public bool Enabled { get { return GetOption(DebugOptions.ENABLED); } set { SetOption(DebugOptions.ENABLED, value); } } #endregion #region Outlook UI /// /// Returns the Outlook UI. May be null if modifications to the UI are disabled. /// private OutlookUI OutlookUI { get { return ThisAddIn.Instance.OutlookUI; } } /// /// Helper which registers only if allowed through options /// /// public RibbonButton RegisterButton(FeatureWithRibbon feature, string id, bool large, System.Action callback, ZPushBehaviour zpushBehaviour = ZPushBehaviour.None) { if (OutlookUI == null || !UI_Ribbon || !GlobalOptions.INSTANCE.UI_Ribbon) return null; return OutlookUI.Register(new RibbonButton(feature, id, large, callback, zpushBehaviour)); } public RibbonToggleButton RegisterToggleButton(FeatureWithRibbon feature, string id, bool large, System.Action callback, ZPushBehaviour zpushBehaviour = ZPushBehaviour.None) { if (OutlookUI == null || !UI_Ribbon || !GlobalOptions.INSTANCE.UI_Ribbon) return null; return OutlookUI.Register(new RibbonToggleButton(feature, id, large, callback, zpushBehaviour)); } public MenuItem RegisterMenuItem(FeatureWithContextMenu feature, string id, string menuId, System.Action callback, ZPushBehaviour zpushBehaviour = ZPushBehaviour.None) where ItemType : IBase { if (OutlookUI == null || !UI_ContextMenu || !GlobalOptions.INSTANCE.UI_ContextMenu) return null; if (menuId == null) menuId = GetDefaultMenuId(); return OutlookUI.Register(new MenuItem(feature, id, menuId, callback, zpushBehaviour)); } private string GetDefaultMenuId() where ItemType : IBase { if (typeof(ItemType) == typeof(IFolder)) return "ContextMenuFolder"; else throw new System.Exception("Unknown context menu: " + typeof(ItemType)); } [AcaciaOption("Enables or disables modifications to the Outlook UI for this feature." + "Note that where applicable, the Ribbon and Context Menu options also control UI modifications.", Interface = typeof(FeatureWithUI))] virtual public bool UI { get { return GetOption(DebugOptions.OUTLOOK_UI); } set { SetOption(DebugOptions.OUTLOOK_UI, value); } } [AcaciaOption("Enables or disables modifications to the Outlook Ribbon for this feature." + "Note that if the UI option is disabled, Ribbon modifications will not be made either.", Interface = typeof(FeatureWithRibbon))] virtual public bool UI_Ribbon { get { return GetOption(DebugOptions.OUTLOOK_UI_RIBBON); } set { SetOption(DebugOptions.OUTLOOK_UI_RIBBON, value); } } [AcaciaOption("Enables or disables modifications to the Outlook Context Menus for this feature." + "Note that if the UI option is disabled, Context Menu modifications will not be made either.", Interface = typeof(FeatureWithContextMenu))] virtual public bool UI_ContextMenu { get { return GetOption(DebugOptions.OUTLOOK_UI_CONTEXT_MENU); } set { SetOption(DebugOptions.OUTLOOK_UI_CONTEXT_MENU, value); } } #endregion #region Event helpers private static MailEvents _mailEvents; protected static MailEvents MailEvents { get { if (_mailEvents == null) _mailEvents = new MailEvents(App); return _mailEvents; } } protected ZPushWatcher Watcher { get { return ThisAddIn.Instance.Watcher; } } #endregion #region Startup /// /// Invoked when the feature is started. The application object is accessible through /// App /// public virtual void Startup() { } #endregion #region Z-Push channels private static ZPushChannels _zPushChannels; protected static ZPushChannels ZPushChannels { get { if (_zPushChannels == null) _zPushChannels = new ZPushChannels(ThisAddIn.Instance.Watcher); return _zPushChannels; } } #endregion #region Debug support [Browsable(false)] public string LogContextId { get { return Name; } } public virtual string ToDebugString() { return ""; } #endregion } }