xref: /haiku/src/apps/haikudepot/util/LanguageMenuUtils.cpp (revision dd2a1e350b303b855a50fd64e6cb55618be1ae6a)
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 }