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 22static 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 31LanguageMenuUtils::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 64LanguageMenuUtils::MarkLanguageInMenu( 65 const BString& languageId, BMenu* menu) { 66 AppUtils::MarkItemWithKeyValueInMenuOrFirst(menu, kLanguageIdKey, languageId); 67} 68 69 70/* static */ void 71LanguageMenuUtils::_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 82LanguageMenuUtils::_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 93LanguageMenuUtils::_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 112LanguageMenuUtils::_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 129LanguageMenuUtils::_IsLanguagePresentationBefore(const LanguageRef& l1, const LanguageRef& l2) 130{ 131 return _LanguagesPresentationCompareFn(l1, l2) < 0; 132}