/// <summary> /// This is used to find a topic by filename and display it /// </summary> /// <param name="filename">The filename of the topic to display</param> public void FindAndDisplay(string filename) { if (tableOfContents == null) { if (this.IsVisible) { this.LoadTableOfContentsInfo(); } if (tableOfContents == null) { return; } } if (!String.IsNullOrEmpty(filename)) { var t = tableOfContents.Find(filename); if (t != null && !String.IsNullOrEmpty(t.Id)) { this.NavigateToTopic(new Uri("link://" + t.Id)); } } }
//===================================================================== /// <summary> /// This is used to mark the file as dirty when the collection changes /// </summary> /// <param name="sender">The sender of the event</param> /// <param name="e">The event arguments</param> void topics_ListChanged(object sender, ListChangedEventArgs e) { TocEntry selectedTopic = tvContent.SelectedItem as TocEntry; if (e.PropertyDescriptor != null) { switch (e.PropertyDescriptor.Name) { case "IsExpanded": case "IsSelected": // We don't care about changes to these properties as they are for the // editor and don't affect the state of the topic collection. return; case "ApiParentMode": // There can be only one API content parent if (selectedTopic != null && selectedTopic.ApiParentMode != ApiParentMode.None) { foreach (var match in topics.Find( t => t.ApiParentMode != ApiParentMode.None && t != selectedTopic, false)) { match.ApiParentMode = ApiParentMode.None; } } break; case "IsDefaultTopic": // There can be only one default topic if (selectedTopic != null && selectedTopic.IsDefaultTopic) { foreach (var match in topics.Find(t => t.IsDefaultTopic && t != selectedTopic, false)) { match.IsDefaultTopic = false; } } break; default: break; } } if (sender != this) { base.RaiseEvent(new RoutedEventArgs(ContentModifiedEvent, this)); } // Update control state based on the collection content tvContent.IsEnabled = expTopicProps.IsEnabled = (topics != null && topics.Count != 0); CommandManager.InvalidateRequerySuggested(); // We must clear the enumerator or it may throw an exception due to collection changes if (matchEnumerator != null) { matchEnumerator.Dispose(); matchEnumerator = null; } }
//===================================================================== /// <summary> /// Load a site map file for editing /// </summary> /// <param name="siteMapFile">The site map file item to load</param> public void LoadSiteMapFile(FileItem siteMapFile) { if (siteMapFile == null) { throw new ArgumentNullException("siteMapFile", "A site map file item must be specified"); } topics = new TocEntryCollection(siteMapFile.ToContentFile()); topics.Load(); // This works around a legacy support issue related to object equality foreach (var t in topics.All()) { t.UniqueId = Guid.NewGuid(); } topics.ListChanged += new ListChangedEventHandler(topics_ListChanged); if (topics.Count != 0 && topics.Find(t => t.IsSelected, false).Count() == 0) { topics[0].IsSelected = true; } tvContent.ItemsSource = topics; this.topics_ListChanged(this, new ListChangedEventArgs(ListChangedType.Reset, -1)); }
//===================================================================== /// <summary> /// Load a site map file for editing /// </summary> /// <param name="siteMapFile">The site map file item to load</param> public void LoadSiteMapFile(FileItem siteMapFile) { if(siteMapFile == null) throw new ArgumentNullException("siteMapFile", "A site map file item must be specified"); topics = new TocEntryCollection(siteMapFile.ToContentFile()); topics.Load(); // This works around a legacy support issue related to object equality foreach(var t in topics.All()) t.UniqueId = Guid.NewGuid(); topics.ListChanged += new ListChangedEventHandler(topics_ListChanged); if(topics.Count != 0 && topics.Find(t => t.IsSelected, false).Count() == 0) topics[0].IsSelected = true; tvContent.ItemsSource = topics; this.topics_ListChanged(this, new ListChangedEventArgs(ListChangedType.Reset, -1)); }
/// <summary> /// This is used to merge destination file information into the site /// map TOC. /// </summary> /// <param name="site">The site entry to update</param> /// <remarks>In addition, files in the site map that do not exist in /// the TOC built from the defined content will be processed and /// copied to the root folder.</remarks> private void MergeTocInfo(TocEntry site) { TocEntry match; string source, filename; if (site.SourceFile.Path.Length != 0) { match = toc.Find(site.SourceFile); if (match != null) { site.DestinationFile = match.DestinationFile; } else { source = site.SourceFile; site.DestinationFile = Path.GetFileName(source); filename = site.DestinationFile; // .topic files get transformed into .html files if (source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase)) { site.DestinationFile = Path.ChangeExtension(site.DestinationFile, ".html"); } // Check to see if anything needs resolving if (source.EndsWith(".htm", StringComparison.OrdinalIgnoreCase) || source.EndsWith(".html", StringComparison.OrdinalIgnoreCase) || source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase)) { match = BuildProcess.GetTocInfo(source); } foreach (string baseFolder in this.HelpFormatOutputFolders) { // If the file contains items that need to be resolved, it is handled separately if (match != null && (match.HasLinks || match.HasCodeBlocks || match.NeedsColorizing || match.HasProjectTags || source.EndsWith(".topic", StringComparison.OrdinalIgnoreCase))) { // Files are always copied to the root pathToRoot = String.Empty; this.ResolveLinksAndCopy(source, baseFolder + filename, match); } else { this.ReportProgress("{0} -> {1}{2}", source, baseFolder, filename); // All attributes are turned off so that we can delete it later File.Copy(source, baseFolder + filename, true); File.SetAttributes(baseFolder + filename, FileAttributes.Normal); } } } } if (site.Children.Count != 0) { foreach (TocEntry entry in site.Children) { this.MergeTocInfo(entry); } } }