/// <summary> /// This handles the creation of the component container asynchronously /// </summary> /// <param name="searchFolders">The folders to search for component assemblies</param> private async void CreateComponentContainerInternal(IEnumerable <string> searchFolders) { try { this.LastError = null; cancellationTokenSource = new CancellationTokenSource(); var result = await Task.Run(() => ComponentUtilities.CreateComponentContainer(searchFolders, cancellationTokenSource.Token), cancellationTokenSource.Token).ConfigureAwait(true); lock (syncRoot) { componentContainer = result; } } catch (OperationCanceledException) { // Ignore this one } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); // Could have passed this in a derived EventArgs instance but I couldn't be bothered to create // one just for this since the probability of an exception is extremely low here. this.LastError = ex; this.ComponentContainerLoadFailed?.Invoke(this, EventArgs.Empty); } finally { lock (syncRoot) { if (cancellationTokenSource != null) { if (!cancellationTokenSource.IsCancellationRequested && this.LastError == null) { this.ComponentContainerLoaded?.Invoke(this, EventArgs.Empty); } cancellationTokenSource.Dispose(); cancellationTokenSource = null; } } } }
//===================================================================== /// <summary> /// Try to load information about all available syntax generators so that they can be selected for use /// in the project. /// </summary> /// <returns>True on success, false on failure or if no project is loaded</returns> private void LoadAvailableSyntaxGeneratorsAndPresentationStyles() { SandcastleProject currentProject = null; HashSet <string> generatorIds = new HashSet <string>(), presentationStyleIds = new HashSet <string>(); string[] searchFolders; try { Cursor.Current = Cursors.WaitCursor; syntaxGenerators = new List <ISyntaxGeneratorMetadata>(); presentationStyles = new List <IPresentationStyleMetadata>(); #if !STANDALONEGUI if (base.ProjectMgr != null) { currentProject = ((SandcastleBuilderProjectNode)base.ProjectMgr).SandcastleProject; } #else currentProject = base.CurrentProject; #endif lastProjectName = currentProject == null ? null : currentProject.Filename; if (currentProject != null) { searchFolders = new[] { currentProject.ComponentPath, Path.GetDirectoryName(currentProject.Filename) } } ; else { searchFolders = new string[] { } }; using (var componentContainer = ComponentUtilities.CreateComponentContainer(searchFolders)) { cblSyntaxFilters.Items.Clear(); var generators = componentContainer.GetExports <ISyntaxGeneratorFactory, ISyntaxGeneratorMetadata>().Select(g => g.Metadata).ToList(); // There may be duplicate generator IDs across the assemblies found. See // BuildComponentManger.GetComponentContainer() for the folder search precedence. Only the // first component for a unique ID will be used. foreach (var generator in generators) { if (!generatorIds.Contains(generator.Id)) { syntaxGenerators.Add(generator); generatorIds.Add(generator.Id); } } cboPresentationStyle.DataSource = null; var styles = componentContainer.GetExports <PresentationStyleSettings, IPresentationStyleMetadata>().Select(g => g.Metadata).ToList(); // As above for duplicates foreach (var style in styles) { if (!presentationStyleIds.Contains(style.Id)) { presentationStyles.Add(style); presentationStyleIds.Add(style.Id); } } } cblSyntaxFilters.Items.AddRange(syntaxGenerators.Select(f => f.Id).OrderBy(f => f).ToArray()); cboPresentationStyle.DataSource = presentationStyles.OrderBy(s => s.IsDeprecated ? 1 : 0).ThenBy( s => s.Id).ToList(); cboPresentationStyle.SelectedValue = Constants.DefaultPresentationStyle; // Resize the syntax filter columns to the widest entry int width, maxWidth = 0; foreach (string s in cblSyntaxFilters.Items) { width = TextRenderer.MeasureText(s, this.Font).Width; if (width > maxWidth) { maxWidth = width; } } cblSyntaxFilters.ColumnWidth = maxWidth + 20; } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); MessageBox.Show("Unexpected error loading syntax generators and presentation styles: " + ex.Message, messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { Cursor.Current = Cursors.Default; } if (cblSyntaxFilters.Items.Count != 0) { cblSyntaxFilters.SelectedIndex = 0; } else { MessageBox.Show("No valid syntax generators found", messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); } if (cboPresentationStyle.Items.Count == 0) { MessageBox.Show("No valid presentation styles found", messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); } }
//===================================================================== /// <summary> /// Try to load information about all available presentation styles so that their arguments can be loaded /// for use in the project. /// </summary> /// <returns>True on success, false on failure or if no project is loaded</returns> private void LoadAvailablePresentationStyles() { SandcastleProject currentProject = null; HashSet <string> presentationStyleIds = new HashSet <string>(); string[] searchFolders; try { Cursor.Current = Cursors.WaitCursor; if (componentContainer != null) { componentContainer.Dispose(); componentContainer = null; } presentationStyles = new List <Lazy <PresentationStyleSettings, IPresentationStyleMetadata> >(); #if !STANDALONEGUI if (base.ProjectMgr != null) { currentProject = ((SandcastleBuilderProjectNode)base.ProjectMgr).SandcastleProject; } #else currentProject = base.CurrentProject; #endif lastProjectName = currentProject == null ? null : currentProject.Filename; if (currentProject != null) { searchFolders = new[] { currentProject.ComponentPath, Path.GetDirectoryName(currentProject.Filename) } } ; else { searchFolders = new string[] { } }; componentContainer = ComponentUtilities.CreateComponentContainer(searchFolders); // There may be duplicate presentation style IDs across the assemblies found. See // BuildComponentManger.GetComponentContainer() for the folder search precedence. Only the // first component for a unique ID will be used. foreach (var style in componentContainer.GetExports <PresentationStyleSettings, IPresentationStyleMetadata>()) { if (!presentationStyleIds.Contains(style.Metadata.Id)) { presentationStyles.Add(style); presentationStyleIds.Add(style.Metadata.Id); } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); MessageBox.Show("Unexpected error loading presentation styles: " + ex.Message, messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { Cursor.Current = Cursors.Default; } }
//===================================================================== /// <summary> /// Load a resource items file for editing /// </summary> /// <param name="resourceItemsFile">The resource items file to load</param> /// <param name="project">The current Sandcastle Builder project</param> public void LoadResourceItemsFile(string resourceItemsFile, SandcastleProject project) { PresentationStyleSettings pss = null; string presentationStylePath, shfbStyleContent; List <string> syntaxGeneratorFiles = new List <string>(); if (resourceItemsFile == null) { throw new ArgumentNullException(nameof(resourceItemsFile)); } if (project == null) { throw new ArgumentNullException(nameof(project)); } try { Mouse.OverrideCursor = Cursors.Wait; resourceItemFilename = resourceItemsFile; using (var container = ComponentUtilities.CreateComponentContainer(project.ComponentSearchPaths, CancellationToken.None)) { var presentationStyles = container.GetExports <PresentationStyleSettings, IPresentationStyleMetadata>(); var style = presentationStyles.FirstOrDefault(s => s.Metadata.Id.Equals( project.PresentationStyle, StringComparison.OrdinalIgnoreCase)); if (style == null) { style = presentationStyles.FirstOrDefault(s => s.Metadata.Id.Equals( Constants.DefaultPresentationStyle, StringComparison.OrdinalIgnoreCase)); } if (style != null) { pss = style.Value; } else { MessageBox.Show("Unable to locate the presentation style ID " + project.PresentationStyle, Constants.AppName, MessageBoxButton.OK, MessageBoxImage.Error); return; } syntaxGeneratorFiles.AddRange(ComponentUtilities.SyntaxGeneratorResourceItemFiles(container, null)); } // Get the presentation style folders presentationStylePath = pss.ResolvePath(pss.ResourceItemsPath); shfbStyleContent = pss.ResolvePath(pss.ToolResourceItemsPath); // Use the language-specific files if they are present if (Directory.Exists(Path.Combine(presentationStylePath, project.Language.Name))) { presentationStylePath = Path.Combine(presentationStylePath, project.Language.Name); } if (File.Exists(Path.Combine(shfbStyleContent, project.Language.Name + ".xml"))) { shfbStyleContent = Path.Combine(shfbStyleContent, project.Language.Name + ".xml"); } else { shfbStyleContent = Path.Combine(shfbStyleContent, "en-US.xml"); } // Load the presentation style content files first followed by the syntax generator files, the // help file builder content items, and then the user's resource item file. foreach (string file in Directory.EnumerateFiles(presentationStylePath, "*.xml")) { this.LoadItemFile(file, false); } foreach (string file in syntaxGeneratorFiles) { this.LoadItemFile(file, false); } if (File.Exists(shfbStyleContent)) { this.LoadItemFile(shfbStyleContent, false); } this.LoadItemFile(resourceItemFilename, true); // Load everything into the list box resourceItems = new BindingList <ResourceItem>(allItems.Values.ToArray()); resourceItems.ListChanged += resourceItems_ListChanged; if (resourceItems.Count != 0) { resourceItems[0].IsSelected = true; } lbResourceItems.ItemsSource = resourceItems; this.resourceItems_ListChanged(this, new ListChangedEventArgs(ListChangedType.Reset, -1)); } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex); MessageBox.Show("Unable to load resource item files: " + ex.Message, Constants.AppName, MessageBoxButton.OK, MessageBoxImage.Error); } finally { Mouse.OverrideCursor = null; } }
//===================================================================== /// <summary> /// Try to load information about all available plug-ins so that they can be added to the project /// </summary> /// <returns>True on success, false on failure or if no project is loaded</returns> private void LoadAvailablePlugInMetadata() { SandcastleProject currentProject = null; HashSet <string> plugInIds = new HashSet <string>(); try { Cursor.Current = Cursors.WaitCursor; if (componentContainer != null) { componentContainer.Dispose(); componentContainer = null; availablePlugIns = null; } #if !STANDALONEGUI if (base.ProjectMgr != null) { currentProject = ((SandcastleBuilderProjectNode)base.ProjectMgr).SandcastleProject; } #else currentProject = base.CurrentProject; #endif lastProjectName = currentProject == null ? null : currentProject.Filename; if (currentProject != null) { componentContainer = ComponentUtilities.CreateComponentContainer(new[] { currentProject.ComponentPath, Path.GetDirectoryName(currentProject.Filename) }); } else { componentContainer = ComponentUtilities.CreateComponentContainer(new string[] { }); } lbProjectPlugIns.Items.Clear(); availablePlugIns = componentContainer.GetExports <IPlugIn, IPlugInMetadata>().ToList(); // There may be duplicate component IDs across the assemblies found. See // BuildComponentManger.GetComponentContainer() for the folder search precedence. Only the first // component for a unique ID will be used. We also ignore hidden plug-ins. foreach (var plugIn in availablePlugIns) { if (!plugIn.Metadata.IsHidden && !plugInIds.Contains(plugIn.Metadata.Id)) { lbAvailablePlugIns.Items.Add(plugIn.Metadata.Id); plugInIds.Add(plugIn.Metadata.Id); } } } catch (Exception ex) { System.Diagnostics.Debug.WriteLine(ex.ToString()); MessageBox.Show("Unexpected error loading plug-ins: " + ex.Message, messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); } finally { Cursor.Current = Cursors.Default; } if (lbAvailablePlugIns.Items.Count != 0) { lbAvailablePlugIns.SelectedIndex = 0; gbAvailablePlugIns.Enabled = gbProjectAddIns.Enabled = true; } else { MessageBox.Show("No valid plug-ins found", messageBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Information); gbAvailablePlugIns.Enabled = gbProjectAddIns.Enabled = false; } }