1 /* 2 * Copyright 2019-2024, Andrew Lindesay <apl@lindesay.co.nz>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 #include "LanguageMenuUtils.h" 6 7 #include <algorithm> 8 9 #include <string.h> 10 11 #include <Application.h> 12 #include <Collator.h> 13 #include <MenuItem.h> 14 #include <Messenger.h> 15 16 #include "AppUtils.h" 17 #include "HaikuDepotConstants.h" 18 #include "LocaleUtils.h" 19 #include "Logger.h" 20 21 22 static const char* kLanguageIdKey = "id"; 23 24 25 /*! This method will add the supplied languages to the menu. It will 26 add first the popular languages, followed by a separator and then 27 other less popular languages. 28 */ 29 30 /* static */ void 31 LanguageMenuUtils::AddLanguagesToMenu(const LanguageRepository* repository, BMenu* menu) 32 { 33 if (repository->IsEmpty()) 34 HDINFO("there are no languages defined"); 35 36 // collect all of the languages into a vector so that they can be sorted 37 // and used. 38 39 std::vector<LanguageRef> languages(repository->CountLanguages()); 40 41 for (int32 i = repository->CountLanguages(); i >= 0; i--) 42 languages[i] = repository->LanguageAtIndex(i); 43 44 std::sort(languages.begin(), languages.end(), IsLanguageBefore); 45 46 // now add the sorted languages to the menu. 47 48 int32 addedPopular = LanguageMenuUtils::_AddLanguagesToMenu(languages, menu, true); 49 50 if (addedPopular > 0) 51 menu->AddSeparatorItem(); 52 53 int32 addedNonPopular = LanguageMenuUtils::_AddLanguagesToMenu(languages, menu, false); 54 55 HDDEBUG("did add %" B_PRId32 " popular languages and %" B_PRId32 56 " non-popular languages to a menu", addedPopular, 57 addedNonPopular); 58 } 59 60 61 /* static */ void 62 LanguageMenuUtils::MarkLanguageInMenu( 63 const BString& languageId, BMenu* menu) { 64 AppUtils::MarkItemWithKeyValueInMenuOrFirst(menu, kLanguageIdKey, languageId); 65 } 66 67 68 /* static */ void 69 LanguageMenuUtils::_AddLanguageToMenu( 70 const BString& id, const BString& name, BMenu* menu) 71 { 72 BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED); 73 message->AddString(kLanguageIdKey, id); 74 BMenuItem* item = new BMenuItem(name, message); 75 menu->AddItem(item); 76 } 77 78 79 /* static */ void 80 LanguageMenuUtils::_AddLanguageToMenu( 81 const LanguageRef& language, BMenu* menu) 82 { 83 BString name; 84 if (language->GetName(name) != B_OK || name.IsEmpty()) 85 name.SetTo("???"); 86 LanguageMenuUtils::_AddLanguageToMenu(language->ID(), name, menu); 87 } 88 89 90 /* static */ int32 91 LanguageMenuUtils::_AddLanguagesToMenu(const std::vector<LanguageRef>& languages, 92 BMenu* menu, bool isPopular) 93 { 94 int32 count = 0; 95 96 for (uint32 i = 0; i < languages.size(); i++) { 97 const LanguageRef language = languages[i]; 98 99 if (languages[i]->IsPopular() == isPopular) { 100 LanguageMenuUtils::_AddLanguageToMenu(languages[i], menu); 101 count++; 102 } 103 } 104 105 return count; 106 } 107 108 109 /*static*/ int 110 LanguageMenuUtils::_LanguagesPresentationCompareFn(const LanguageRef& l1, const LanguageRef& l2) 111 { 112 BCollator* collator = LocaleUtils::GetSharedCollator(); 113 BString name1; 114 BString name2; 115 int32 result = 0; 116 117 if (l1->GetName(name1) == B_OK && l2->GetName(name2) == B_OK) 118 result = collator->Compare(name1.String(), name2.String()); 119 if (0 == result) 120 result = strcmp(l1->ID(), l2->ID()); 121 122 return result; 123 } 124 125 126 /*static*/ bool 127 LanguageMenuUtils::_IsLanguagePresentationBefore(const LanguageRef& l1, const LanguageRef& l2) 128 { 129 return _LanguagesPresentationCompareFn(l1, l2) < 0; 130 }