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