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( 32 const LanguageModel* languageModel, BMenu* menu) 33 { 34 if (languageModel->CountSupportedLanguages() == 0) 35 HDINFO("there are no languages defined"); 36 37 // collect all of the languages into a vector so that they can be sorted 38 // and used. 39 40 std::vector<LanguageRef> languages(languageModel->CountSupportedLanguages()); 41 42 for (int32 i = 0; i < languageModel->CountSupportedLanguages(); i++) { 43 languages[i] = languageModel->SupportedLanguageAt(i); 44 } 45 46 std::sort(languages.begin(), languages.end(), _IsLanguagePresentationBefore); 47 48 // now add the sorted languages to the menu. 49 50 int32 addedPopular = LanguageMenuUtils::_AddLanguagesToMenu(languages, menu, true); 51 52 if (addedPopular > 0) 53 menu->AddSeparatorItem(); 54 55 int32 addedNonPopular = LanguageMenuUtils::_AddLanguagesToMenu(languages, menu, false); 56 57 HDDEBUG("did add %" B_PRId32 " popular languages and %" B_PRId32 58 " non-popular languages to a menu", addedPopular, 59 addedNonPopular); 60 } 61 62 63 /* static */ void 64 LanguageMenuUtils::MarkLanguageInMenu( 65 const BString& languageId, BMenu* menu) { 66 AppUtils::MarkItemWithKeyValueInMenuOrFirst(menu, kLanguageIdKey, languageId); 67 } 68 69 70 /* static */ void 71 LanguageMenuUtils::_AddLanguageToMenu( 72 const BString& id, const BString& name, BMenu* menu) 73 { 74 BMessage* message = new BMessage(MSG_LANGUAGE_SELECTED); 75 message->AddString(kLanguageIdKey, id); 76 BMenuItem* item = new BMenuItem(name, message); 77 menu->AddItem(item); 78 } 79 80 81 /* static */ void 82 LanguageMenuUtils::_AddLanguageToMenu( 83 const LanguageRef& language, BMenu* menu) 84 { 85 BString name; 86 if (language->GetName(name) != B_OK || name.IsEmpty()) 87 name.SetTo("???"); 88 LanguageMenuUtils::_AddLanguageToMenu(language->ID(), name, menu); 89 } 90 91 92 /* static */ int32 93 LanguageMenuUtils::_AddLanguagesToMenu(const std::vector<LanguageRef>& languages, 94 BMenu* menu, bool isPopular) 95 { 96 int32 count = 0; 97 98 for (uint32 i = 0; i < languages.size(); i++) { 99 const LanguageRef language = languages[i]; 100 101 if (languages[i]->IsPopular() == isPopular) { 102 LanguageMenuUtils::_AddLanguageToMenu(languages[i], menu); 103 count++; 104 } 105 } 106 107 return count; 108 } 109 110 111 /*static*/ int 112 LanguageMenuUtils::_LanguagesPresentationCompareFn(const LanguageRef& l1, const LanguageRef& l2) 113 { 114 BCollator* collator = LocaleUtils::GetSharedCollator(); 115 BString name1; 116 BString name2; 117 int32 result = 0; 118 119 if (l1->GetName(name1) == B_OK && l2->GetName(name2) == B_OK) 120 result = collator->Compare(name1.String(), name2.String()); 121 if (0 == result) 122 result = strcmp(l1->ID(), l2->ID()); 123 124 return result; 125 } 126 127 128 /*static*/ bool 129 LanguageMenuUtils::_IsLanguagePresentationBefore(const LanguageRef& l1, const LanguageRef& l2) 130 { 131 return _LanguagesPresentationCompareFn(l1, l2) < 0; 132 }