/* Function: FindFileSourceEntry * Returns the menu entry that contains the passed file source, or null if there isn't one yet. */ protected MenuEntries.Files.FileSource FindFileSourceEntry(Files.FileSource fileSource) { if (rootFileMenu == null) { return(null); } // If the menu only had one file source and it was condensed, the root file entry may have been replaced // by that file source. else if (rootFileMenu is MenuEntries.Files.FileSource) { MenuEntries.Files.FileSource fileSourceEntry = (MenuEntries.Files.FileSource)rootFileMenu; if (fileSourceEntry.WrappedFileSource == fileSource) { return(fileSourceEntry); } else { return(null); } } // We're assuming that the only other possibility is a container with a flat list of FileSources. If we later allow // FileSources to be put in nested groups this will need to be updated. else { foreach (var member in rootFileMenu.Members) { if (member is MenuEntries.Files.FileSource) { MenuEntries.Files.FileSource fileSourceEntry = (MenuEntries.Files.FileSource)member; if (fileSourceEntry.WrappedFileSource == fileSource) { return(fileSourceEntry); } } } return(null); } }
/* Function: CreateFileSourceEntry * Creates an entry for the file source, adds it to the menu, and returns it. It will also create the <rootFileMenu> * container if necessary. */ protected MenuEntries.Files.FileSource CreateFileSourceEntry(Files.FileSource fileSource) { #if DEBUG if (FindFileSourceEntry(fileSource) != null) { throw new Exception("Tried to create a file source entry that already existed in the menu."); } #endif if (rootFileMenu == null) { rootFileMenu = new MenuEntries.Base.Container(); rootFileMenu.Title = Engine.Locale.Get("NaturalDocs.Engine", "Menu.Files"); } MenuEntries.Files.FileSource fileSourceEntry = new MenuEntries.Files.FileSource(fileSource); fileSourceEntry.Parent = rootFileMenu; rootFileMenu.Members.Add(fileSourceEntry); return(fileSourceEntry); }
/* Function: AddFile * Adds a file to the menu tree. */ public void AddFile(Files.File file) { #if DEBUG if (isCondensed) { throw new Exception("Cannot add a file to the menu once it's been condensed."); } #endif // Find which file source owns this file and generate a relative path to it. MenuEntries.Files.FileSource fileSourceEntry = FindOrCreateFileSourceEntryOf(file); Path relativePath = fileSourceEntry.WrappedFileSource.MakeRelative(file.FileName); // Split off the file name and split the rest into individual folder names. string prefix; List <string> pathSegments; relativePath.Split(out prefix, out pathSegments); string fileName = pathSegments[pathSegments.Count - 1]; pathSegments.RemoveAt(pathSegments.Count - 1); // Create the file entry and find out where it goes. Create new folder levels as necessary. MenuEntries.Files.File fileEntry = new MenuEntries.Files.File(file); MenuEntries.Base.Container container = fileSourceEntry; foreach (string pathSegment in pathSegments) { Path pathFromFileSource; if (container == fileSourceEntry) { pathFromFileSource = pathSegment; } else { pathFromFileSource = (container as MenuEntries.Files.Folder).PathFromFileSource + '/' + pathSegment; } MenuEntries.Files.Folder folderEntry = null; foreach (var member in container.Members) { if (member is MenuEntries.Files.Folder && (member as MenuEntries.Files.Folder).PathFromFileSource == pathFromFileSource) { folderEntry = (MenuEntries.Files.Folder)member; break; } } if (folderEntry == null) { folderEntry = new MenuEntries.Files.Folder(pathFromFileSource); folderEntry.Parent = container; container.Members.Add(folderEntry); } container = folderEntry; } fileEntry.Parent = container; container.Members.Add(fileEntry); }
/* Function: Condense * Removes unnecessary levels in the menu. Only call this function after everything has been added. */ public void Condense() { if (rootFileMenu != null) { rootFileMenu.Condense(); // If there's only one file source we can remove the top level container. if (rootFileMenu.Members.Count == 1) { MenuEntries.Files.FileSource fileSourceEntry = (MenuEntries.Files.FileSource)rootFileMenu.Members[0]; // Overwrite the file source name with the tab title, especially since it might not be defined if there was only one. // We don't need an unnecessary level for a single file source. fileSourceEntry.Title = rootFileMenu.Title; // Get rid of unnecessary levels as there's no point in displaying them. fileSourceEntry.CondensedTitles = null; rootFileMenu = fileSourceEntry; } } if (rootClassMenu != null) { rootClassMenu.Condense(); // If there's only one language we can remove the top level container. if (rootClassMenu.Members.Count == 1) { MenuEntries.Classes.Language languageEntry = (MenuEntries.Classes.Language)rootClassMenu.Members[0]; // We can overwrite the language name with the tab title. We're not going to preserve an unnecessary level // for the language. languageEntry.Title = rootClassMenu.Title; // However, we are going to keep CondensedTitles because we want all scope levels to be visible, even if // they're empty. rootClassMenu = languageEntry; } } if (rootDatabaseMenu != null) { rootDatabaseMenu.Condense(); // If the only top level entry is a scope we can merge it if (rootDatabaseMenu.Members.Count == 1 && rootDatabaseMenu.Members[0] is MenuEntries.Classes.Scope) { MenuEntries.Classes.Scope scopeEntry = (MenuEntries.Classes.Scope)rootDatabaseMenu.Members[0]; // Move the scope title into CondensedTitles since we want it to be visible. if (scopeEntry.CondensedTitles == null) { scopeEntry.CondensedTitles = new List <string>(1); scopeEntry.CondensedTitles.Add(scopeEntry.Title); } else { scopeEntry.CondensedTitles.Insert(0, scopeEntry.Title); } // Now overwrite the original title with the tab title. scopeEntry.Title = rootDatabaseMenu.Title; rootDatabaseMenu = scopeEntry; } } isCondensed = true; }