using System; using System.Collections.Generic; using System.ComponentModel; using System.Reflection; using System.Windows.Documents; using System.Windows.Media; using System35; using JetBrains.Annotations; using JetBrains.Omea.OpenAPI; using OmniaMea; namespace JetBrains.Omea.Plugins { /// /// Omea Plugin Page, list view entries that represent plugin assemblies. /// internal class OmeaPluginsPageListEntryPlugin : OmeaPluginsPageListEntry { #region Data [NotNull] private OmeaPluginsPageAssemblyInfo _assemblyinfo; [NotNull] private readonly Func _funcLoadAssembly; /// /// Even though is not , we're currently in progress of loading it. /// UI-thread-only access. /// private bool _isBusyLoading; private readonly PluginLoader.PossiblyPluginFileInfo _pluginfileinfo; private readonly string _sRuntimeLoadError; #endregion #region Init /// /// Ctor. /// ) /// Raw name of the plugin assembly. /// A funtion to load the assembly on-demand. /// A cached instance for getting the initial value. /// Info about the file the plugin were loaded from. /// If the plugin failed to be loaded at runtime, records the load error. public OmeaPluginsPageListEntryPlugin([NotNull] string sPluginAssemblyName, [NotNull] Func funcLoadAssembly, PluginLoader.PossiblyPluginFileInfo pluginfileinfo, [NotNull] string sRuntimeLoadError, [NotNull] PluginLoader.DisabledPlugins disabledplugins) { if(sPluginAssemblyName == null) throw new ArgumentNullException("sPluginAssemblyName"); if(funcLoadAssembly == null) throw new ArgumentNullException("funcLoadAssembly"); if(disabledplugins == null) throw new ArgumentNullException("disabledplugins"); if(sRuntimeLoadError == null) throw new ArgumentNullException("sRuntimeLoadError"); _funcLoadAssembly = funcLoadAssembly; _pluginfileinfo = pluginfileinfo; _sRuntimeLoadError = sRuntimeLoadError; _assemblyinfo = OmeaPluginsPageAssemblyInfo.CreateNotLoaded(sPluginAssemblyName, _pluginfileinfo, _sRuntimeLoadError); _bIsEnabledInitially = !disabledplugins.Contains(sPluginAssemblyName); IsEnabled = _bIsEnabledInitially; } #endregion #region Attributes /// /// Plugin file origin data. /// public PluginLoader.PossiblyPluginFileInfo PluginFileInfo { get { return _pluginfileinfo; } } #endregion #region Operations /// /// Applies the edited changes. /// public bool Commit(PluginLoader.DisabledPlugins disabledplugins) { // Not changed? if(IsEnabled == _bIsEnabledInitially) return false; // Apply the new state if(IsEnabled) disabledplugins.Remove(AssemblyInfo.PluginAssemblyName); else disabledplugins.Add(AssemblyInfo.PluginAssemblyName); // Mark as non-dirty _bIsEnabledInitially = IsEnabled; return true; // Were changes } /// /// Loads the , if not loaded yet. /// /// Executed after loading (or skipping) the item, on the UI thread. public void Load([NotNull] Action funcOnDone) { // Don't start second time if((AssemblyInfo.IsLoaded) || (_isBusyLoading)) { funcOnDone(); return; } _isBusyLoading = true; // Load async Assembly assembly = null; List plugintypes = null; Action funcPreloadOnOtherThread = delegate { assembly = _funcLoadAssembly(); // Plugin types in this assembly plugintypes = new List(); foreach(Type type in assembly.GetExportedTypes()) { if(PluginLoader.IsOmeaPluginType(type)) plugintypes.Add(type); } }; Action funcRenderOnUiThread = delegate { _isBusyLoading = false; // Create visual objects on the UI thread try { if((assembly != null) && (plugintypes != null)) AssemblyInfo = OmeaPluginsPageAssemblyInfo.CreateFromAssembly(assembly, plugintypes, PluginFileInfo, _sRuntimeLoadError); } catch(Exception ex) { Core.ReportBackgroundException(ex); } funcOnDone(); }; // Schedulle Core.NetworkAP.QueueJob(Stringtable.JobLoadPluginAssemblyInfo, delegate { try { funcPreloadOnOtherThread(); } finally { // Commit on the home thread Core.UserInterfaceAP.QueueJob(Stringtable.JobLoadPluginAssemblyInfo, funcRenderOnUiThread); } }); } #endregion #region Implementation /// /// Contains the info that has to be loaded from the assembly. First, a stub, then it's replaced with real info. Hence . /// [NotNull] protected OmeaPluginsPageAssemblyInfo AssemblyInfo { get { return _assemblyinfo; } set { _assemblyinfo = value; // AssemblyInfo has changed FirePropertyChanged("AssemblyInfo"); // Presentation has changed FirePropertyChanged("Description"); FirePropertyChanged("Icon"); FirePropertyChanged("IsPrimary"); FirePropertyChanged("Title"); } } #endregion #region Overrides public override FlowDocument Description { get { return AssemblyInfo.Description; } } public override ImageSource Icon { get { return AssemblyInfo.PluginAssemblyIcon; } } public override bool? IsPrimary { get { return AssemblyInfo.IsLoaded ? AssemblyInfo.IsPrimary : (bool?)null; } } public override bool SupportsIsEnabled { get { return true; } } public override string Title { get { return AssemblyInfo.PluginAssemblyDisplayName; } } #endregion } }