/* Function: FindLanguageEntry * Returns the entry that contains the passed language, or null if there isn't one yet. */ protected MenuEntries.Classes.Language FindLanguageEntry(Languages.Language language) { if (rootClassMenu == null) { return(null); } // If the menu only had one language and it was condensed, the root class entry may have been replaced // by that language. else if (rootClassMenu is MenuEntries.Classes.Language) { MenuEntries.Classes.Language languageEntry = (MenuEntries.Classes.Language)rootClassMenu; if (languageEntry.WrappedLanguage == language) { return(languageEntry); } else { return(null); } } // The only other possibility is a container with a flat list of languages. else { foreach (var member in rootClassMenu.Members) { if (member is MenuEntries.Classes.Language) { MenuEntries.Classes.Language languageEntry = (MenuEntries.Classes.Language)member; if (languageEntry.WrappedLanguage == language) { return(languageEntry); } } } return(null); } }
/* Function: CreateLanguageEntry * Creates an entry for the language, adds it to the class menu, and returns it. It will also create the <rootClassMenu> * container if necessary. */ protected MenuEntries.Classes.Language CreateLanguageEntry(Languages.Language language) { #if DEBUG if (FindLanguageEntry(language) != null) { throw new Exception("Tried to create a language entry that already existed in the menu."); } #endif if (rootClassMenu == null) { rootClassMenu = new MenuEntries.Base.Container(); rootClassMenu.Title = Engine.Locale.Get("NaturalDocs.Engine", "Menu.Classes"); } MenuEntries.Classes.Language languageEntry = new MenuEntries.Classes.Language(language); languageEntry.Parent = rootClassMenu; rootClassMenu.Members.Add(languageEntry); return(languageEntry); }
/* 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; }
/* Function: AddClass * Adds a class to the menu tree. */ public void AddClass(Symbols.ClassString classString) { #if DEBUG if (isCondensed) { throw new Exception("Cannot add a class to the menu once it's been condensed."); } #endif string[] classSegments = classString.Symbol.SplitSegments(); MenuEntries.Base.Container container; bool ignoreCase; if (classString.Hierarchy == Symbols.ClassString.HierarchyType.Class) { MenuEntries.Classes.Language languageEntry = FindOrCreateLanguageEntryOf(classString); container = languageEntry; ignoreCase = (languageEntry.WrappedLanguage.CaseSensitive == false); } else // Database { if (rootDatabaseMenu == null) { rootDatabaseMenu = new MenuEntries.Base.Container(); rootDatabaseMenu.Title = Engine.Locale.Get("NaturalDocs.Engine", "Menu.Database"); } container = rootDatabaseMenu; ignoreCase = true; } // Create the class and find out where it goes. Create new scope containers as necessary. MenuEntries.Classes.Class classEntry = new MenuEntries.Classes.Class(classString); string scopeSoFar = null; // We only want to walk through the scope levels so we use length - 1 to ignore the last segment, which is the class name. for (int i = 0; i < classSegments.Length - 1; i++) { string classSegment = classSegments[i]; if (scopeSoFar == null) { scopeSoFar = classSegment; } else { scopeSoFar += Symbols.SymbolString.SeparatorChar + classSegment; } MenuEntries.Classes.Scope scopeEntry = null; foreach (var member in container.Members) { if (member is MenuEntries.Classes.Scope && string.Compare((member as MenuEntries.Classes.Scope).WrappedScopeString, scopeSoFar, ignoreCase) == 0) { scopeEntry = (MenuEntries.Classes.Scope)member; break; } } if (scopeEntry == null) { scopeEntry = new MenuEntries.Classes.Scope(Symbols.SymbolString.FromExportedString(scopeSoFar)); scopeEntry.Parent = container; container.Members.Add(scopeEntry); } container = scopeEntry; } classEntry.Parent = container; container.Members.Add(classEntry); }