/// <summary>
        /// This combines the conceptual and API intermediate TOC files into one file ready for transformation to
        /// the help format-specific TOC file formats and, if necessary, determines the default topic.
        /// </summary>
        private void CombineIntermediateTocFiles()
        {
            XmlAttribute attr;
            XmlDocument  conceptualXml = null, tocXml;
            XmlElement   docElement;
            XmlNodeList  allNodes;
            XmlNode      node, parent;
            int          insertionPoint;

            this.ReportProgress(BuildStep.CombiningIntermediateTocFiles,
                                "Combining conceptual and API intermediate TOC files...");

            if (!this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
            {
                this.ExecutePlugIns(ExecutionBehaviors.Before);

                // Load the TOC files
                if (toc != null && toc.Count != 0)
                {
                    conceptualXml = new XmlDocument();
                    conceptualXml.Load(Path.Combine(workingFolder, "_ConceptualTOC_.xml"));
                }

                tocXml = new XmlDocument();
                tocXml.Load(Path.Combine(workingFolder, "toc.xml"));

                // Merge the conceptual and API TOCs into one?
                if (conceptualXml != null)
                {
                    // Remove the root content container if present as we don't need it for the other formats
                    if ((project.HelpFileFormat & HelpFileFormats.MSHelpViewer) != 0 &&
                        !String.IsNullOrEmpty(this.RootContentContainerId))
                    {
                        docElement = conceptualXml.DocumentElement;
                        node       = docElement.FirstChild;
                        allNodes   = node.SelectNodes("topic");

                        foreach (XmlNode n in allNodes)
                        {
                            n.ParentNode.RemoveChild(n);
                            docElement.AppendChild(n);
                        }

                        node.ParentNode.RemoveChild(node);
                    }

                    if (String.IsNullOrEmpty(this.ApiTocParentId))
                    {
                        // If not parented, the API content is placed above or below the conceptual content based
                        // on the project's ContentPlacement setting.
                        if (project.ContentPlacement == ContentPlacement.AboveNamespaces)
                        {
                            docElement = conceptualXml.DocumentElement;

                            foreach (XmlNode n in tocXml.SelectNodes("topics/topic"))
                            {
                                node = conceptualXml.ImportNode(n, true);
                                docElement.AppendChild(node);
                            }

                            tocXml = conceptualXml;
                        }
                        else
                        {
                            docElement = tocXml.DocumentElement;

                            foreach (XmlNode n in conceptualXml.SelectNodes("topics/topic"))
                            {
                                node = tocXml.ImportNode(n, true);
                                docElement.AppendChild(node);
                            }
                        }
                    }
                    else
                    {
                        // Parent the API content to a conceptual topic
                        parent = conceptualXml.SelectSingleNode("//topic[@id='" + this.ApiTocParentId + "']");

                        // If not found, parent it to the root
                        if (parent == null)
                        {
                            parent = conceptualXml.DocumentElement;
                        }

                        insertionPoint = this.ApiTocOrder;

                        if (insertionPoint == -1 || insertionPoint >= parent.ChildNodes.Count)
                        {
                            insertionPoint = parent.ChildNodes.Count;
                        }

                        foreach (XmlNode n in tocXml.SelectNodes("topics/topic"))
                        {
                            node = conceptualXml.ImportNode(n, true);

                            if (insertionPoint >= parent.ChildNodes.Count)
                            {
                                parent.AppendChild(node);
                            }
                            else
                            {
                                parent.InsertBefore(node, parent.ChildNodes[insertionPoint]);
                            }

                            insertionPoint++;
                        }

                        tocXml = conceptualXml;
                    }

                    // Fix up empty container nodes by removing the file attribute and setting the ID attribute to
                    // the title attribute value.
                    foreach (XmlNode n in tocXml.SelectNodes("//topic[@title]"))
                    {
                        attr = n.Attributes["file"];

                        if (attr != null)
                        {
                            n.Attributes.Remove(attr);
                        }

                        attr = n.Attributes["id"];

                        if (attr != null)
                        {
                            attr.Value = n.Attributes["title"].Value;
                        }
                    }

                    tocXml.Save(Path.Combine(workingFolder, "toc.xml"));
                }

                this.ExecutePlugIns(ExecutionBehaviors.After);
            }

            // Determine the default topic for Help 1, website, and markdown output if one was not specified in a
            // site map or content layout file.
            if (defaultTopic == null && (project.HelpFileFormat & (HelpFileFormats.HtmlHelp1 |
                                                                   HelpFileFormats.Website | HelpFileFormats.Markdown)) != 0)
            {
                var defTopic = ComponentUtilities.XmlStreamAxis(Path.Combine(workingFolder, "toc.xml"), "topic").FirstOrDefault(
                    t => t.Attribute("file") != null);

                if (defTopic != null)
                {
                    // Find the file.  Could be .htm, .html, or .md so just look for any file with the given name.
                    defaultTopic = Directory.EnumerateFiles(workingFolder + "Output",
                                                            defTopic.Attribute("file").Value + ".*", SearchOption.AllDirectories).FirstOrDefault();

                    if (defaultTopic != null)
                    {
                        defaultTopic = defaultTopic.Substring(workingFolder.Length + 7);

                        if (defaultTopic.IndexOf('\\') != -1)
                        {
                            defaultTopic = defaultTopic.Substring(defaultTopic.IndexOf('\\') + 1);
                        }
                    }
                }

                // This shouldn't happen anymore, but just in case...
                if (defaultTopic == null)
                {
                    throw new BuilderException("BE0026", "Unable to determine default topic in toc.xml.  Mark " +
                                               "one as the default topic manually in the content layout file.");
                }
            }
        }
        //=====================================================================

        /// <summary>
        /// This is called to generate the namespace summary file
        /// </summary>
        private void GenerateNamespaceSummaries()
        {
            XmlNode member;
            NamespaceSummaryItem nsi;
            string nsName = null, summaryText;
            bool   isDocumented;

            this.ReportProgress(BuildStep.GenerateNamespaceSummaries, "Generating namespace summary information...");

            // Add a dummy file if there are no comments files specified.  This will contain the project and
            // namespace summaries.
            if (commentsFiles.Count == 0)
            {
                nsName = workingFolder + "_ProjNS_.xml";

                using (StreamWriter sw = new StreamWriter(nsName, false, Encoding.UTF8))
                {
                    sw.Write("<?xml version=\"1.0\"?>\r\n<doc>\r\n" +
                             "<assembly>\r\n<name>_ProjNS_</name>\r\n" +
                             "</assembly>\r\n<members/>\r\n</doc>\r\n");
                }

                commentsFiles.Add(new XmlCommentsFile(nsName));
            }

            // Replace any "NamespaceDoc" and "NamespaceGroupDoc" class IDs with their containing namespace.
            // The comments in these then become the comments for the namespaces and namespace groups.
            commentsFiles.ReplaceNamespaceDocEntries();

            if (this.ExecutePlugIns(ExecutionBehaviors.InsteadOf))
            {
                return;
            }

            this.ExecutePlugIns(ExecutionBehaviors.Before);

            // XML comments do not support summaries on namespace elements by default.  However, if Sandcastle
            // finds them, it will add them to the help file.  The same holds true for project comments on the
            // root namespaces page (R:Project_[HtmlHelpName]).  We can accomplish this by adding elements to
            // the first comments file or by supplying them in an external XML comments file.
            try
            {
                // Add the project comments if specified
                if (project.ProjectSummary.Length != 0)
                {
                    // Set the name in case it isn't valid
                    nsName = "R:Project_" + this.ResolvedHtmlHelpName.Replace(" ", "_");
                    member = commentsFiles.FindMember(nsName);
                    this.AddNamespaceComments(member, project.ProjectSummary);
                }

                // Get all the namespace and namespace group nodes from the reflection information file
                var nsElements =
                    ComponentUtilities.XmlStreamAxis(reflectionFile, "api").Where(el =>
                {
                    string id = el.Attribute("id").Value;

                    return(id.Length > 1 && id[1] == ':' && (id[0] == 'N' || id[0] == 'G') &&
                           el.Element("topicdata").Attribute("group").Value != "rootGroup");
                }).Select(el => el.Attribute("id").Value);

                // Add the namespace summaries
                foreach (var n in nsElements)
                {
                    nsName = n;

                    nsi = project.NamespaceSummaries[nsName.StartsWith("N:", StringComparison.Ordinal) ?
                                                     nsName.Substring(2) : nsName.Substring(2) + " (Group)"];

                    if (nsi != null)
                    {
                        isDocumented = nsi.IsDocumented;
                        summaryText  = nsi.Summary;
                    }
                    else
                    {
                        // The global namespace is not documented by default
                        isDocumented = (nsName != "N:");
                        summaryText  = String.Empty;
                    }

                    if (isDocumented)
                    {
                        // If documented, add the summary text
                        member = commentsFiles.FindMember(nsName);
                        this.AddNamespaceComments(member, summaryText);
                    }
                }
            }
            catch (Exception ex)
            {
                // Eat the error in a partial build so that the user can get into the namespace comments editor
                // to fix it.
                if (this.PartialBuildType != PartialBuildType.None)
                {
                    throw new BuilderException("BE0012", String.Format(CultureInfo.CurrentCulture,
                                                                       "Error generating namespace summaries (Namespace = {0}): {1}", nsName, ex.Message), ex);
                }
            }

            this.ExecutePlugIns(ExecutionBehaviors.After);
        }
示例#3
0
        //=====================================================================

        /// <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;
            }
        }
        /// <summary>
        /// This is called when the component cache has finished being loaded and is available for use
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">The event arguments</param>
        private void componentCache_ComponentContainerLoaded(object sender, EventArgs e)
        {
            BuildPropertiesNeededEventArgs projectSettings = new BuildPropertiesNeededEventArgs();

            this.BuildPropertiesNeeded?.Invoke(this, projectSettings);

            HashSet <string> generatorIds = new HashSet <string>(), presentationStyleIds = new HashSet <string>();

            try
            {
                Mouse.OverrideCursor = Cursors.Wait;
                isBinding            = true;

                cboPresentationStyle.IsEnabled   = lbSyntaxFilters.IsEnabled = lbHelpFileFormat.IsEnabled = true;
                cboPresentationStyle.ItemsSource = lbHelpFileFormat.ItemsSource = lbSyntaxFilters.ItemsSource = null;

                if (cboPresentationStyle.Items.Count != 0)
                {
                    cboPresentationStyle.Items.Clear();
                }

                if (lbHelpFileFormat.Items.Count != 0)
                {
                    lbHelpFileFormat.Items.Clear();
                }

                if (lbSyntaxFilters.Items.Count != 0)
                {
                    lbSyntaxFilters.Items.Clear();
                }

                syntaxGenerators   = new List <ISyntaxGeneratorMetadata>();
                presentationStyles = new List <IPresentationStyleMetadata>();

                var generators = componentCache.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);
                    }
                }

                var styles = componentCache.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);
                    }
                }

                allSyntaxFilters = new List <SyntaxFilterItem>();

                foreach (var filter in syntaxGenerators.OrderBy(f => f.Id))
                {
                    allSyntaxFilters.Add(new SyntaxFilterItem {
                        Id = filter.Id
                    });
                }

                lbSyntaxFilters.ItemsSource = allSyntaxFilters;

                cboPresentationStyle.ItemsSource = presentationStyles.OrderBy(s => s.IsDeprecated ? 1 : 0).ThenBy(
                    s => s.Id).ToList();
                cboPresentationStyle.SelectedValue = Constants.DefaultPresentationStyle;

                if (lbSyntaxFilters.Items.Count != 0)
                {
                    lbSyntaxFilters.SelectedIndex = 0;
                }
                else
                {
                    MessageBox.Show("No valid syntax generators found", Constants.AppName, MessageBoxButton.OK,
                                    MessageBoxImage.Information);
                }

                if (cboPresentationStyle.Items.Count == 0)
                {
                    MessageBox.Show("No valid presentation styles found", Constants.AppName, MessageBoxButton.OK,
                                    MessageBoxImage.Information);
                }

                if (projectSettings.ProjectLoaded)
                {
                    if (!String.IsNullOrWhiteSpace(projectSettings.PresentationStyle))
                    {
                        var match = cboPresentationStyle.Items.Cast <IPresentationStyleMetadata>().FirstOrDefault(p =>
                                                                                                                  p.Id.Equals(projectSettings.PresentationStyle, StringComparison.OrdinalIgnoreCase));

                        if (match != null)
                        {
                            cboPresentationStyle.SelectedValue = match.Id;
                        }
                    }

                    if (!String.IsNullOrWhiteSpace(projectSettings.SyntaxFilters))
                    {
                        foreach (string filter in ComponentUtilities.SyntaxFiltersFrom(syntaxGenerators,
                                                                                       projectSettings.SyntaxFilters).Select(f => f.Id))
                        {
                            var match = allSyntaxFilters.FirstOrDefault(f => f.Id == filter);

                            if (match != null)
                            {
                                match.IsSelected = true;
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());

                MessageBox.Show("Unexpected error loading syntax generators and presentation styles: " +
                                ex.Message, Constants.AppName, MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                Mouse.OverrideCursor = null;
                isBinding            = false;
            }
        }
        //=====================================================================

        /// <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("resourceItemsFile", "A resource items file name must be specified");
            }

            try
            {
                Mouse.OverrideCursor = Cursors.Wait;

                resourceItemFilename = resourceItemsFile;

                using (var container = ComponentUtilities.CreateComponentContainer(new[] { project.ComponentPath,
                                                                                           Path.GetDirectoryName(project.Filename) }))
                {
                    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,
                                        "Resource Item Editor", 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, "Resource Item Editor",
                                MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                Mouse.OverrideCursor = null;
            }
        }
        /// <summary>
        /// This is used to get an enumerable list of unique namespaces referenced in the XML comments files
        /// </summary>
        /// <param name="validNamespaces">An enumerable list of valid namespaces</param>
        /// <returns>An enumerable list of unique namespaces referenced in the XML comments files</returns>
        public IEnumerable <string> GetReferencedNamespaces(IEnumerable <string> validNamespaces)
        {
            HashSet <string> seenNamespaces = new HashSet <string>();
            string           ns;

            foreach (XmlCommentsFile f in this)
            {
                // Find all comments elements with a reference.  XML comments files may be ill-formed so
                // ignore any elements without a cref attribute.
                IEnumerable <string> crefs;

                try
                {
                    crefs = ComponentUtilities.XmlStreamAxis(f.SourcePath, new[] { "event", "exception",
                                                                                   "inheritdoc", "permission", "see", "seealso" }).Select(
                        el => (string)el.Attribute("cref")).Where(c => c != null).ToList();
                }
                catch (XmlException)
                {
                    yield break;
                }

                foreach (string refId in crefs)
                {
                    if (refId.Length > 2 && refId[1] == ':' && refId.IndexOfAny(new[] { '.', '(' }) != -1)
                    {
                        ns = refId.Trim();

                        // Strip off member name?
                        if (!ns.StartsWith("R:", StringComparison.OrdinalIgnoreCase) &&
                            !ns.StartsWith("G:", StringComparison.OrdinalIgnoreCase) &&
                            !ns.StartsWith("N:", StringComparison.OrdinalIgnoreCase) &&
                            !ns.StartsWith("T:", StringComparison.OrdinalIgnoreCase))
                        {
                            if (ns.IndexOf('(') != -1)
                            {
                                ns = ns.Substring(0, ns.IndexOf('('));
                            }

                            if (ns.IndexOf('.') != -1)
                            {
                                ns = ns.Substring(0, ns.LastIndexOf('.'));
                            }
                        }

                        if (ns.IndexOf('.') != -1)
                        {
                            ns = ns.Substring(2, ns.LastIndexOf('.') - 2);
                        }
                        else
                        {
                            ns = ns.Substring(2);
                        }

                        if (validNamespaces.Contains(ns) && !seenNamespaces.Contains(ns))
                        {
                            seenNamespaces.Add(ns);
                            yield return(ns);
                        }
                    }
                }
            }
        }
        /// <inheritdoc />
        protected override bool BindControlValue(Control control)
        {
            ProjectProperty projProp = null;
            List <string>   allFilters;
            int             idx;

#if !STANDALONEGUI
            if (this.ProjectMgr == null)
            {
                return(false);
            }
#else
            if (this.CurrentProject == null)
            {
                return(false);
            }
#endif
            // Add the project's selected language to the list if it is not there
            if (control.Name == "cboLanguage")
            {
#if !STANDALONEGUI
                projProp = this.ProjectMgr.BuildProject.GetProperty("Language");
#else
                projProp = this.CurrentProject.MSBuildProject.GetProperty("Language");
#endif
                if (projProp != null)
                {
                    cboLanguage.SelectedItem = this.AddLanguage(projProp.UnevaluatedValue ?? "en-US");
                }
                else
                {
                    cboLanguage.SelectedItem = LanguageResourceConverter.StandardValues.First(
                        c => c.Name.Equals("en-US", StringComparison.OrdinalIgnoreCase));
                }

                return(true);
            }

            // Set the selected syntax filters
            if (control.Name == "cblSyntaxFilters")
            {
                for (idx = 0; idx < cblSyntaxFilters.Items.Count; idx++)
                {
                    cblSyntaxFilters.SetItemChecked(idx, false);
                }

#if !STANDALONEGUI
                SandcastleProject currentProject = null;

                if (base.ProjectMgr != null)
                {
                    currentProject = ((SandcastleBuilderProjectNode)base.ProjectMgr).SandcastleProject;
                }

                if (syntaxGenerators == null || presentationStyles == null || currentProject == null ||
                    currentProject.Filename != lastProjectName)
                {
                    this.LoadAvailableSyntaxGeneratorsAndPresentationStyles();
                }

                if (base.ProjectMgr != null)
                {
                    projProp = base.ProjectMgr.BuildProject.GetProperty("SyntaxFilters");
                }
#else
                if (syntaxGenerators == null || presentationStyles == null || base.CurrentProject == null ||
                    base.CurrentProject.Filename != lastProjectName)
                {
                    this.LoadAvailableSyntaxGeneratorsAndPresentationStyles();
                }

                if (base.CurrentProject != null)
                {
                    projProp = base.CurrentProject.MSBuildProject.GetProperty("SyntaxFilters");
                }
#endif

                if (projProp != null)
                {
                    allFilters = ComponentUtilities.SyntaxFiltersFrom(syntaxGenerators,
                                                                      projProp.UnevaluatedValue).Select(f => f.Id).ToList();
                }
                else
                {
                    allFilters = ComponentUtilities.SyntaxFiltersFrom(syntaxGenerators, "Standard").Select(
                        f => f.Id).ToList();
                }

                foreach (string s in allFilters)
                {
                    idx = cblSyntaxFilters.FindStringExact(s);

                    if (idx != -1)
                    {
                        cblSyntaxFilters.SetItemChecked(idx, true);
                    }
                }

                return(true);
            }

            return(false);
        }
        //=====================================================================

        /// <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);
            }
        }