2828 * SOFTWARE.
2929 */
3030
31+ #include < exception>
3132#include < imgui.h>
3233#include < texture.hh>
3334#include < dpi.h>
3435#include < components.h>
3536#include < animate.h>
37+ #include < i18n.h>
3638#include < math.h>
3739#include < worker.h>
40+ #include < renderer.h>
41+ #include < cstdlib>
42+ #include < format>
43+ #ifndef _WIN32
44+ #include < unistd.h>
45+ #endif
3846
3947using namespace ImGui ;
4048
@@ -44,8 +52,7 @@ using namespace ImGui;
4452 */
4553bool RenderTitleBarComponent (std::shared_ptr<RouterNav> router)
4654{
47- ImGuiIO& io = GetIO ();
48- const std::string strTitleText = std::format (" Steam Homebrew" , io.Framerate );
55+ const std::string strTitleText = Locale::Get (" titlebarTitle" );
4956
5057 ImGuiViewport* viewport = GetMainViewport ();
5158 PushStyleVar (ImGuiStyleVar_WindowPadding, ImVec2 (ScaleX (15 ), ScaleY (15 )));
@@ -88,13 +95,109 @@ bool RenderTitleBarComponent(std::shared_ptr<RouterNav> router)
8895 Text (" %s" , strTitleText.c_str ());
8996 SameLine ();
9097
98+ ImVec2 closeButtonDimensions = { ceil (ScaleX (70 )), ceil (ScaleY (43 )) };
99+
91100 static bool isCloseButtonHovered = false ;
92101
93102 if (isCloseButtonHovered) {
94103 PushStyleColor (ImGuiCol_ChildBg, ImVec4 (0 .769f , 0 .169f , 0 .11f , 1 .0f ));
95104 }
96105
97- ImVec2 closeButtonDimensions = { ceil (ScaleX (70 )), ceil (ScaleY (43 )) };
106+ static bool langPopupOpen = false ;
107+
108+ ImVec2 langButtonDimensions = { ceil (ScaleX (50 )), ceil (ScaleY (43 )) };
109+ SetCursorPos ({ viewport->Size .x - closeButtonDimensions.x - langButtonDimensions.x , 0 });
110+
111+ PushStyleVar (ImGuiStyleVar_ChildRounding, 0 );
112+ PushStyleColor (ImGuiCol_ChildBg, ImVec4 (0 .f , 0 .f , 0 .f , 0 .f ));
113+ static bool isLangButtonHovered = false ;
114+ if (isLangButtonHovered)
115+ PushStyleColor (ImGuiCol_ChildBg, ImVec4 (1 .f , 1 .f , 1 .f , 0 .06f ));
116+
117+ BeginChild (" ##LangButton" , { langButtonDimensions.x , langButtonDimensions.y }, false , ImGuiWindowFlags_NoScrollbar);
118+ {
119+ SetCursorPos ({ (langButtonDimensions.x - ScaleX (20 )) * 0 .5f , ScaleY (12 ) });
120+ Image ((ImTextureID)(intptr_t )languageIconTexture, { ScaleX (20 ), ScaleY (20 ) });
121+ }
122+ EndChild ();
123+
124+ ImVec2 langBtnMin = GetItemRectMin ();
125+ ImVec2 langBtnMax = GetItemRectMax ();
126+
127+ if (isLangButtonHovered)
128+ PopStyleColor ();
129+ PopStyleColor ();
130+ PopStyleVar ();
131+
132+ if (IsItemClicked (ImGuiMouseButton_Left))
133+ OpenPopup (" ##LangPopup" );
134+
135+ if (IsItemHovered ())
136+ SetMouseCursor (ImGuiMouseCursor_Hand);
137+
138+ isLangButtonHovered = IsItemHovered ();
139+
140+ ImGuiIO& io = GetIO ();
141+ ImFont* vietItemFont = (io.Fonts ->Fonts .Size > 2 ) ? io.Fonts ->Fonts [2 ] : nullptr ;
142+ ImFont* dropdownFont = (io.Fonts ->Fonts .Size > 3 ) ? io.Fonts ->Fonts [3 ] : nullptr ;
143+
144+ const auto & langs = Locale::GetAvailableLanguages ();
145+ const std::string& currentLangId = Locale::GetCurrentLanguageId ();
146+
147+ const float popupWidth = ScaleX (400 );
148+ float anim = EaseInOutFloat (" ##LangPopupAnim" , 0 .f , 1 .f , IsPopupOpen (" ##LangPopup" ), 0 .35f );
149+
150+ float popupY = langBtnMax.y - ScaleY (6 ) * (1 .f - anim);
151+ SetNextWindowPos ({ langBtnMax.x - popupWidth, popupY });
152+ SetNextWindowSize ({ popupWidth, ScaleY (500 ) });
153+ SetNextWindowBgAlpha (anim);
154+
155+ PushStyleColor (ImGuiCol_PopupBg, ImVec4 (0 .10f , 0 .10f , 0 .11f , 1 .0f ));
156+ PushStyleColor (ImGuiCol_Header, ImVec4 (0 .20f , 0 .21f , 0 .22f , 1 .0f ));
157+ PushStyleColor (ImGuiCol_HeaderHovered, ImVec4 (0 .26f , 0 .27f , 0 .28f , 1 .0f ));
158+ PushStyleColor (ImGuiCol_Border, ImVec4 (0 .22f , 0 .23f , 0 .25f , 1 .0f ));
159+ PushStyleVar (ImGuiStyleVar_WindowPadding, ImVec2 (ScaleX (6 ), ScaleY (6 )));
160+ PushStyleVar (ImGuiStyleVar_ItemSpacing, ImVec2 (ScaleX (8 ), ScaleY (6 )));
161+ PushStyleVar (ImGuiStyleVar_PopupRounding, ScaleX (4 ));
162+
163+ if (dropdownFont)
164+ PushFont (dropdownFont);
165+
166+ if (BeginPopup (" ##LangPopup" , ImGuiWindowFlags_NoMove)) {
167+ if (!::IsWindowFocused ())
168+ CloseCurrentPopup ();
169+ PushStyleVar (ImGuiStyleVar_Alpha, anim);
170+ for (const auto & lang : langs) {
171+ bool isSelected = (lang.id == currentLangId);
172+ bool useVietFont = (lang.id == " vietnamese" ) && (vietItemFont != nullptr );
173+ if (useVietFont) {
174+ if (dropdownFont)
175+ PopFont ();
176+ PushFont (vietItemFont);
177+ }
178+ if (Selectable (lang.displayName .c_str (), isSelected, 0 , ImVec2 (popupWidth, 0 ))) {
179+ Locale::SetLanguage (lang.id );
180+ RequestFontRebuild ();
181+ CloseCurrentPopup ();
182+ }
183+ if (isSelected)
184+ SetItemDefaultFocus ();
185+ if (useVietFont) {
186+ PopFont ();
187+ if (dropdownFont)
188+ PushFont (dropdownFont);
189+ }
190+ }
191+ PopStyleVar ();
192+ EndPopup ();
193+ }
194+
195+ if (dropdownFont)
196+ PopFont ();
197+
198+ PopStyleVar (3 );
199+ PopStyleColor (4 );
200+
98201 SetCursorPos ({ viewport->Size .x - closeButtonDimensions.x , 0 });
99202
100203 PushStyleVar (ImGuiStyleVar_ChildRounding, 0 );
@@ -108,7 +211,11 @@ bool RenderTitleBarComponent(std::shared_ptr<RouterNav> router)
108211
109212 if (IsItemClicked (ImGuiMouseButton_Left) && !IsWorkerBusy ()) {
110213 JoinWorker ();
111- ExitProcess (0 );
214+ #ifdef _WIN32
215+ std::exit (0 );
216+ #else
217+ _exit (0 );
218+ #endif
112219 }
113220
114221 if (isCloseButtonHovered) {
0 commit comments