//============================================================================= // // Option Search Menu class. // This menu contains search field, and is dynamically filled with search // results. // //============================================================================= class os_Menu : OptionMenu { override void Init(Menu parent, OptionMenuDescriptor desc) { Super.Init(parent, desc); mDesc.mItems.clear(); addSearchField(); mDesc.mScrollPos = 0; mDesc.mSelectedItem = 0; mDesc.CalcIndent(); } void search() { string text = mSearchField.GetText(); let query = os_Query.fromString(text); bool isAnyTermMatches = mIsAnyOfItem.mCVar.GetBool(); mDesc.mItems.clear(); addSearchField(text); Dictionary searchedMenus = Dictionary.Create(); bool found = listOptions(mDesc, "MainMenu", query, "", isAnyTermMatches, searchedMenus); if (!found) { addNoResultsItem(mDesc); } mDesc.CalcIndent(); } private void addSearchField(string query = "") { string searchLabel = StringTable.Localize("$OS_LABEL"); mSearchField = new("os_SearchField").Init(searchLabel, self, query); mIsAnyOfItem = new("os_AnyOrAllOption").Init(self); mDesc.mItems.push(mSearchField); mDesc.mItems.push(mIsAnyOfItem); addEmptyLine(mDesc); } private static bool listOptions(OptionMenuDescriptor targetDesc, string menuName, os_Query query, string path, bool isAnyTermMatches, Dictionary searchedMenus) { if (searchedMenus.At(menuName).length() > 0) { return false; } searchedMenus.Insert(menuName, "1"); let desc = MenuDescriptor.GetDescriptor(menuName); let listMenuDesc = ListMenuDescriptor(desc); if (listMenuDesc) { return listOptionsListMenu(listMenuDesc, targetDesc, query, path, isAnyTermMatches, searchedMenus); } let optionMenuDesc = OptionMenuDescriptor(desc); if (optionMenuDesc) { return listOptionsOptionMenu(optionMenuDesc, targetDesc, query, path, isAnyTermMatches, searchedMenus); } return false; } private static bool listOptionsListMenu(ListMenuDescriptor sourceDesc, OptionMenuDescriptor targetDesc, os_Query query, string path, bool isAnyTermMatches, Dictionary searchedMenus) { int nItems = sourceDesc.mItems.size(); bool found = false; for (int i = 0; i < nItems; ++i) { let item = sourceDesc.mItems[i]; string actionN = item.GetAction(); let textItem = ListMenuItemTextItem(item); string newPath = textItem ? makePath(path, StringTable.Localize(textItem.mText)) : path; found |= listOptions(targetDesc, actionN, query, newPath, isAnyTermMatches, searchedMenus); } return found; } private static bool listOptionsOptionMenu(OptionMenuDescriptor sourceDesc, OptionMenuDescriptor targetDesc, os_Query query, string path, bool isAnyTermMatches, Dictionary searchedMenus) { if (sourceDesc == targetDesc) { return false; } int nItems = sourceDesc.mItems.size(); bool first = true; bool found = false; for (int i = 0; i < nItems; ++i) { let item = sourceDesc.mItems[i]; if (item is "OptionMenuItemStaticText") { continue; } string label = StringTable.Localize(item.mLabel); if (!query.matches(label, isAnyTermMatches)) { continue; } found = true; if (first) { addEmptyLine(targetDesc); addPathItem(targetDesc, path); first = false; } let itemOptionBase = OptionMenuItemOptionBase(item); if (itemOptionBase) { itemOptionBase.mCenter = false; } targetDesc.mItems.push(item); } for (int i = 0; i < nItems; ++i) { let item = sourceDesc.mItems[i]; string label = StringTable.Localize(item.mLabel); string optionSearchTitle = StringTable.Localize("$OS_TITLE"); if (label == optionSearchTitle) { continue; } if (item is "OptionMenuItemSubMenu") { string newPath = makePath(path, label); found |= listOptions(targetDesc, item.GetAction(), query, newPath, isAnyTermMatches, searchedMenus); } } return found; } private static string makePath(string path, string label) { if (path.length() == 0) { return label; } int pathWidth = SmallFont.StringWidth(path .. "/" .. label); int screenWidth = Screen.GetWidth(); bool isTooWide = (pathWidth > screenWidth / 3); string newPath = isTooWide ? path .. "/" .. "\n" .. label : path .. "/" .. label; return newPath; } private static void addPathItem(OptionMenuDescriptor desc, string path) { Array lines; path.split(lines, "\n"); int nLines = lines.size(); for (int i = 0; i < nLines; ++i) { OptionMenuItemStaticText text = new("OptionMenuItemStaticText").Init(lines[i], 1); desc.mItems.push(text); } } private static void addEmptyLine(OptionMenuDescriptor desc) { int nItems = desc.mItems.size(); if (nItems > 0) { let staticText = OptionMenuItemStaticText(desc.mItems[nItems - 1]); if (staticText != null && staticText.mLabel == "") { return; } } let item = new("OptionMenuItemStaticText").Init(""); desc.mItems.push(item); } private static void addNoResultsItem(OptionMenuDescriptor desc) { string noResults = StringTable.Localize("$OS_NO_RESULTS"); let text = new("OptionMenuItemStaticText").Init(noResults, 0); addEmptyLine(desc); desc.mItems.push(text); } private os_AnyOrAllOption mIsAnyOfItem; private os_SearchField mSearchField; }