diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-23 21:40:41 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-03-23 21:40:41 +0200 |
commit | bb9a22212f83e55ebaf601a65251ccb3caf86fab (patch) | |
tree | 166aa0e7a0351b7a68d40e65b2a61afa0da51d37 | |
parent | 35496f8a9c9cc0098210349d5c7fda3492ffd9c8 (diff) |
UI language preference; switching at runtime
IssueID #192
-rw-r--r-- | src/app.c | 28 | ||||
-rw-r--r-- | src/lang.c | 2 | ||||
-rw-r--r-- | src/prefs.c | 2 | ||||
-rw-r--r-- | src/prefs.h | 1 | ||||
-rw-r--r-- | src/ui/command.c | 2 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 14 | ||||
-rw-r--r-- | src/ui/labelwidget.c | 9 | ||||
-rw-r--r-- | src/ui/labelwidget.h | 1 | ||||
-rw-r--r-- | src/ui/util.c | 61 | ||||
-rw-r--r-- | src/ui/window.c | 4 |
10 files changed, 105 insertions, 19 deletions
@@ -208,6 +208,7 @@ static iString *serializePrefs_App_(const iApp *d) { | |||
208 | } | 208 | } |
209 | appendFormat_String(str, "sidebar2.mode arg:%d\n", mode_SidebarWidget(sidebar2)); | 209 | appendFormat_String(str, "sidebar2.mode arg:%d\n", mode_SidebarWidget(sidebar2)); |
210 | } | 210 | } |
211 | appendFormat_String(str, "uilang id:%s\n", cstr_String(&d->prefs.uiLanguage)); | ||
211 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); | 212 | appendFormat_String(str, "uiscale arg:%f\n", uiScale_Window(d->window)); |
212 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); | 213 | appendFormat_String(str, "prefs.dialogtab arg:%d\n", d->prefs.dialogTab); |
213 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); | 214 | appendFormat_String(str, "font.set arg:%d\n", d->prefs.font); |
@@ -308,6 +309,11 @@ static void loadPrefs_App_(iApp *d) { | |||
308 | if (equal_Command(cmd, "uiscale")) { | 309 | if (equal_Command(cmd, "uiscale")) { |
309 | setUiScale_Window(get_Window(), argf_Command(cmd)); | 310 | setUiScale_Window(get_Window(), argf_Command(cmd)); |
310 | } | 311 | } |
312 | else if (equal_Command(cmd, "uilang")) { | ||
313 | const char *id = cstr_Rangecc(range_Command(cmd, "id")); | ||
314 | setCStr_String(&d->prefs.uiLanguage, id); | ||
315 | setCurrent_Lang(id); | ||
316 | } | ||
311 | else if (equal_Command(cmd, "ca.file") || equal_Command(cmd, "ca.path")) { | 317 | else if (equal_Command(cmd, "ca.file") || equal_Command(cmd, "ca.path")) { |
312 | /* Background requests may be started before these commands would get | 318 | /* Background requests may be started before these commands would get |
313 | handled via the event loop. */ | 319 | handled via the event loop. */ |
@@ -1286,13 +1292,14 @@ static void updatePrefsThemeButtons_(iWidget *d) { | |||
1286 | } | 1292 | } |
1287 | 1293 | ||
1288 | static void updateDropdownSelection_(iLabelWidget *dropButton, const char *selectedCommand) { | 1294 | static void updateDropdownSelection_(iLabelWidget *dropButton, const char *selectedCommand) { |
1289 | iForEach(ObjectList, i, children_Widget(findChild_Widget(as_Widget(dropButton), "menu"))) { | 1295 | iWidget *menu = findChild_Widget(as_Widget(dropButton), "menu"); |
1296 | iForEach(ObjectList, i, children_Widget(menu)) { | ||
1290 | if (isInstance_Object(i.object, &Class_LabelWidget)) { | 1297 | if (isInstance_Object(i.object, &Class_LabelWidget)) { |
1291 | iLabelWidget *item = i.object; | 1298 | iLabelWidget *item = i.object; |
1292 | const iBool isSelected = endsWith_String(command_LabelWidget(item), selectedCommand); | 1299 | const iBool isSelected = endsWith_String(command_LabelWidget(item), selectedCommand); |
1293 | setFlags_Widget(as_Widget(item), selected_WidgetFlag, isSelected); | 1300 | setFlags_Widget(as_Widget(item), selected_WidgetFlag, isSelected); |
1294 | if (isSelected) { | 1301 | if (isSelected) { |
1295 | updateText_LabelWidget(dropButton, text_LabelWidget(item)); | 1302 | updateText_LabelWidget(dropButton, sourceText_LabelWidget(item)); |
1296 | } | 1303 | } |
1297 | } | 1304 | } |
1298 | } | 1305 | } |
@@ -1300,8 +1307,6 @@ static void updateDropdownSelection_(iLabelWidget *dropButton, const char *selec | |||
1300 | 1307 | ||
1301 | static void updateColorThemeButton_(iLabelWidget *button, int theme) { | 1308 | static void updateColorThemeButton_(iLabelWidget *button, int theme) { |
1302 | if (!button) return; | 1309 | if (!button) return; |
1303 | // const char *mode = strstr(cstr_String(id_Widget(as_Widget(button))), ".dark") | ||
1304 | // ? "dark" : "light"; | ||
1305 | updateDropdownSelection_(button, format_CStr(".set arg:%d", theme)); | 1310 | updateDropdownSelection_(button, format_CStr(".set arg:%d", theme)); |
1306 | } | 1311 | } |
1307 | 1312 | ||
@@ -1355,6 +1360,11 @@ static iBool handlePrefsCommands_(iWidget *d, const char *cmd) { | |||
1355 | postCommand_App("prefs.changed"); | 1360 | postCommand_App("prefs.changed"); |
1356 | return iTrue; | 1361 | return iTrue; |
1357 | } | 1362 | } |
1363 | else if (equal_Command(cmd, "uilang")) { | ||
1364 | updateDropdownSelection_(findChild_Widget(d, "prefs.uilang"), | ||
1365 | cstr_String(string_Command(cmd, "id"))); | ||
1366 | return iFalse; | ||
1367 | } | ||
1358 | else if (equal_Command(cmd, "quoteicon.set")) { | 1368 | else if (equal_Command(cmd, "quoteicon.set")) { |
1359 | const int arg = arg_Command(cmd); | 1369 | const int arg = arg_Command(cmd); |
1360 | setFlags_Widget(findChild_Widget(d, "prefs.quoteicon.0"), selected_WidgetFlag, arg == 0); | 1370 | setFlags_Widget(findChild_Widget(d, "prefs.quoteicon.0"), selected_WidgetFlag, arg == 0); |
@@ -1532,6 +1542,15 @@ iBool handleCommand_App(const char *cmd) { | |||
1532 | d->prefs.dialogTab = arg_Command(cmd); | 1542 | d->prefs.dialogTab = arg_Command(cmd); |
1533 | return iTrue; | 1543 | return iTrue; |
1534 | } | 1544 | } |
1545 | else if (equal_Command(cmd, "uilang")) { | ||
1546 | const iString *lang = string_Command(cmd, "id"); | ||
1547 | if (!equal_String(lang, &d->prefs.uiLanguage)) { | ||
1548 | set_String(&d->prefs.uiLanguage, lang); | ||
1549 | setCurrent_Lang(cstr_String(&d->prefs.uiLanguage)); | ||
1550 | postCommand_App("lang.changed"); | ||
1551 | } | ||
1552 | return iTrue; | ||
1553 | } | ||
1535 | else if (equal_Command(cmd, "translation.languages")) { | 1554 | else if (equal_Command(cmd, "translation.languages")) { |
1536 | d->prefs.langFrom = argLabel_Command(cmd, "from"); | 1555 | d->prefs.langFrom = argLabel_Command(cmd, "from"); |
1537 | d->prefs.langTo = argLabel_Command(cmd, "to"); | 1556 | d->prefs.langTo = argLabel_Command(cmd, "to"); |
@@ -1891,6 +1910,7 @@ iBool handleCommand_App(const char *cmd) { | |||
1891 | setToggle_Widget(findChild_Widget(dlg, "prefs.hidetoolbarscroll"), d->prefs.hideToolbarOnScroll); | 1910 | setToggle_Widget(findChild_Widget(dlg, "prefs.hidetoolbarscroll"), d->prefs.hideToolbarOnScroll); |
1892 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); | 1911 | setToggle_Widget(findChild_Widget(dlg, "prefs.ostheme"), d->prefs.useSystemTheme); |
1893 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); | 1912 | setToggle_Widget(findChild_Widget(dlg, "prefs.customframe"), d->prefs.customFrame); |
1913 | updateDropdownSelection_(findChild_Widget(dlg, "prefs.uilang"), cstr_String(&d->prefs.uiLanguage)); | ||
1894 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); | 1914 | setToggle_Widget(findChild_Widget(dlg, "prefs.retainwindow"), d->prefs.retainWindowSize); |
1895 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), | 1915 | setText_InputWidget(findChild_Widget(dlg, "prefs.uiscale"), |
1896 | collectNewFormat_String("%g", uiScale_Window(d->window))); | 1916 | collectNewFormat_String("%g", uiScale_Window(d->window))); |
@@ -72,7 +72,7 @@ iRangecc range_Lang(iRangecc msgId) { | |||
72 | return ((const iMsgStr *) at_SortedArray(d->messages, pos))->str; | 72 | return ((const iMsgStr *) at_SortedArray(d->messages, pos))->str; |
73 | } | 73 | } |
74 | fprintf(stderr, "[Lang] missing: %s\n", cstr_Rangecc(msgId)); fflush(stderr); | 74 | fprintf(stderr, "[Lang] missing: %s\n", cstr_Rangecc(msgId)); fflush(stderr); |
75 | iAssert(iFalse); | 75 | // iAssert(iFalse); |
76 | return msgId; | 76 | return msgId; |
77 | } | 77 | } |
78 | 78 | ||
diff --git a/src/prefs.c b/src/prefs.c index a4f12e20..119dfd56 100644 --- a/src/prefs.c +++ b/src/prefs.c | |||
@@ -54,6 +54,7 @@ void init_Prefs(iPrefs *d) { | |||
54 | d->docThemeDark = colorfulDark_GmDocumentTheme; | 54 | d->docThemeDark = colorfulDark_GmDocumentTheme; |
55 | d->docThemeLight = white_GmDocumentTheme; | 55 | d->docThemeLight = white_GmDocumentTheme; |
56 | d->saturation = 1.0f; | 56 | d->saturation = 1.0f; |
57 | initCStr_String(&d->uiLanguage, "en"); | ||
57 | init_String(&d->caFile); | 58 | init_String(&d->caFile); |
58 | init_String(&d->caPath); | 59 | init_String(&d->caPath); |
59 | init_String(&d->geminiProxy); | 60 | init_String(&d->geminiProxy); |
@@ -81,4 +82,5 @@ void deinit_Prefs(iPrefs *d) { | |||
81 | deinit_String(&d->downloadDir); | 82 | deinit_String(&d->downloadDir); |
82 | deinit_String(&d->caPath); | 83 | deinit_String(&d->caPath); |
83 | deinit_String(&d->caFile); | 84 | deinit_String(&d->caFile); |
85 | deinit_String(&d->uiLanguage); | ||
84 | } | 86 | } |
diff --git a/src/prefs.h b/src/prefs.h index 130f11e2..1bd434d0 100644 --- a/src/prefs.h +++ b/src/prefs.h | |||
@@ -38,6 +38,7 @@ struct Impl_Prefs { | |||
38 | int langFrom; | 38 | int langFrom; |
39 | int langTo; | 39 | int langTo; |
40 | /* Window */ | 40 | /* Window */ |
41 | iString uiLanguage; | ||
41 | iBool useSystemTheme; | 42 | iBool useSystemTheme; |
42 | enum iColorTheme theme; | 43 | enum iColorTheme theme; |
43 | enum iColorAccent accent; | 44 | enum iColorAccent accent; |
diff --git a/src/ui/command.c b/src/ui/command.c index 44e66121..c5ca164e 100644 --- a/src/ui/command.c +++ b/src/ui/command.c | |||
@@ -96,7 +96,7 @@ iString *suffix_Command(const char *cmd, const char *label) { | |||
96 | } | 96 | } |
97 | 97 | ||
98 | const iString *string_Command(const char *cmd, const char *label) { | 98 | const iString *string_Command(const char *cmd, const char *label) { |
99 | return collect_String(newRange_String(range_Command(cmd, label))); | 99 | return collectNewRange_String(range_Command(cmd, label)); |
100 | } | 100 | } |
101 | 101 | ||
102 | iRangecc range_Command(const char *cmd, const char *label) { | 102 | iRangecc range_Command(const char *cmd, const char *label) { |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 05b83b3d..52359732 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -83,6 +83,7 @@ struct Impl_InputWidget { | |||
83 | iArray text; /* iChar[] */ | 83 | iArray text; /* iChar[] */ |
84 | iArray oldText; /* iChar[] */ | 84 | iArray oldText; /* iChar[] */ |
85 | iString hint; | 85 | iString hint; |
86 | iString srcHint; | ||
86 | int leftPadding; | 87 | int leftPadding; |
87 | int rightPadding; | 88 | int rightPadding; |
88 | size_t cursor; | 89 | size_t cursor; |
@@ -136,6 +137,7 @@ void init_InputWidget(iInputWidget *d, size_t maxLen) { | |||
136 | init_Array(&d->text, sizeof(iChar)); | 137 | init_Array(&d->text, sizeof(iChar)); |
137 | init_Array(&d->oldText, sizeof(iChar)); | 138 | init_Array(&d->oldText, sizeof(iChar)); |
138 | init_String(&d->hint); | 139 | init_String(&d->hint); |
140 | init_String(&d->srcHint); | ||
139 | init_Array(&d->undoStack, sizeof(iInputUndo)); | 141 | init_Array(&d->undoStack, sizeof(iInputUndo)); |
140 | d->font = uiInput_FontId | alwaysVariableFlag_FontId; | 142 | d->font = uiInput_FontId | alwaysVariableFlag_FontId; |
141 | d->leftPadding = 0; | 143 | d->leftPadding = 0; |
@@ -164,6 +166,7 @@ void deinit_InputWidget(iInputWidget *d) { | |||
164 | if (d->timer) { | 166 | if (d->timer) { |
165 | SDL_RemoveTimer(d->timer); | 167 | SDL_RemoveTimer(d->timer); |
166 | } | 168 | } |
169 | deinit_String(&d->srcHint); | ||
167 | deinit_String(&d->hint); | 170 | deinit_String(&d->hint); |
168 | deinit_Array(&d->oldText); | 171 | deinit_Array(&d->oldText); |
169 | deinit_Array(&d->text); | 172 | deinit_Array(&d->text); |
@@ -251,8 +254,10 @@ void setMaxLen_InputWidget(iInputWidget *d, size_t maxLen) { | |||
251 | } | 254 | } |
252 | 255 | ||
253 | void setHint_InputWidget(iInputWidget *d, const char *hintText) { | 256 | void setHint_InputWidget(iInputWidget *d, const char *hintText) { |
254 | setCStr_String(&d->hint, hintText); | 257 | /* Keep original for retranslations. */ |
255 | translate_Lang(&d->hint); /* TODO: Keep original for retranslations. */ | 258 | setCStr_String(&d->srcHint, hintText); |
259 | set_String(&d->hint, &d->srcHint); | ||
260 | translate_Lang(&d->hint); | ||
256 | } | 261 | } |
257 | 262 | ||
258 | void setContentPadding_InputWidget(iInputWidget *d, int left, int right) { | 263 | void setContentPadding_InputWidget(iInputWidget *d, int left, int right) { |
@@ -665,6 +670,11 @@ static iBool processEvent_InputWidget_(iInputWidget *d, const SDL_Event *ev) { | |||
665 | begin_InputWidget(d); | 670 | begin_InputWidget(d); |
666 | return iFalse; | 671 | return iFalse; |
667 | } | 672 | } |
673 | else if (isCommand_UserEvent(ev, "lang.changed")) { | ||
674 | set_String(&d->hint, &d->srcHint); | ||
675 | translate_Lang(&d->hint); | ||
676 | return iFalse; | ||
677 | } | ||
668 | else if (isCommand_Widget(w, ev, "focus.lost")) { | 678 | else if (isCommand_Widget(w, ev, "focus.lost")) { |
669 | end_InputWidget(d, iTrue); | 679 | end_InputWidget(d, iTrue); |
670 | return iFalse; | 680 | return iFalse; |
diff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c index 2a1eb06a..8089445b 100644 --- a/src/ui/labelwidget.c +++ b/src/ui/labelwidget.c | |||
@@ -85,6 +85,10 @@ static iBool processEvent_LabelWidget_(iLabelWidget *d, const SDL_Event *ev) { | |||
85 | if (isMetricsChange_UserEvent(ev)) { | 85 | if (isMetricsChange_UserEvent(ev)) { |
86 | updateSize_LabelWidget(d); | 86 | updateSize_LabelWidget(d); |
87 | } | 87 | } |
88 | else if (isCommand_UserEvent(ev, "lang.changed")) { | ||
89 | setText_LabelWidget(d, &d->srcLabel); | ||
90 | return iFalse; | ||
91 | } | ||
88 | else if (isCommand_UserEvent(ev, "bindings.changed")) { | 92 | else if (isCommand_UserEvent(ev, "bindings.changed")) { |
89 | /* Update the key used to trigger this label. */ | 93 | /* Update the key used to trigger this label. */ |
90 | updateKey_LabelWidget_(d); | 94 | updateKey_LabelWidget_(d); |
@@ -474,6 +478,11 @@ const iString *text_LabelWidget(const iLabelWidget *d) { | |||
474 | return &d->label; | 478 | return &d->label; |
475 | } | 479 | } |
476 | 480 | ||
481 | const iString *sourceText_LabelWidget(const iLabelWidget *d) { | ||
482 | if (!d) return collectNew_String(); | ||
483 | return &d->srcLabel; | ||
484 | } | ||
485 | |||
477 | const iString *command_LabelWidget(const iLabelWidget *d) { | 486 | const iString *command_LabelWidget(const iLabelWidget *d) { |
478 | return &d->command; | 487 | return &d->command; |
479 | } | 488 | } |
diff --git a/src/ui/labelwidget.h b/src/ui/labelwidget.h index 3e3c76fb..f4c4658c 100644 --- a/src/ui/labelwidget.h +++ b/src/ui/labelwidget.h | |||
@@ -45,6 +45,7 @@ void updateTextCStr_LabelWidget (iLabelWidget *, const char *text); /* not r | |||
45 | iInt2 defaultSize_LabelWidget (const iLabelWidget *); | 45 | iInt2 defaultSize_LabelWidget (const iLabelWidget *); |
46 | int font_LabelWidget (const iLabelWidget *); | 46 | int font_LabelWidget (const iLabelWidget *); |
47 | const iString * text_LabelWidget (const iLabelWidget *); | 47 | const iString * text_LabelWidget (const iLabelWidget *); |
48 | const iString * sourceText_LabelWidget (const iLabelWidget *); /* untranslated */ | ||
48 | const iString * command_LabelWidget (const iLabelWidget *); | 49 | const iString * command_LabelWidget (const iLabelWidget *); |
49 | iChar icon_LabelWidget (const iLabelWidget *); | 50 | iChar icon_LabelWidget (const iLabelWidget *); |
50 | 51 | ||
diff --git a/src/ui/util.c b/src/ui/util.c index 94690bc6..8c0b0138 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -1679,14 +1679,13 @@ iWidget *makeQuestion_Widget(const char *title, const char *msg, | |||
1679 | 1679 | ||
1680 | void setToggle_Widget(iWidget *d, iBool active) { | 1680 | void setToggle_Widget(iWidget *d, iBool active) { |
1681 | if (d) { | 1681 | if (d) { |
1682 | const char *YES = cstr_Lang("toggle.yes"); | ||
1683 | const char *NO = cstr_Lang("toggle.no"); | ||
1684 | setFlags_Widget(d, selected_WidgetFlag, active); | 1682 | setFlags_Widget(d, selected_WidgetFlag, active); |
1685 | iLabelWidget *label = (iLabelWidget *) d; | 1683 | iLabelWidget *label = (iLabelWidget *) d; |
1686 | if (!cmp_String(text_LabelWidget(label), YES) || | 1684 | if (!cmp_String(text_LabelWidget(label), cstr_Lang("toggle.yes")) || |
1687 | !cmp_String(text_LabelWidget(label), NO)) { | 1685 | !cmp_String(text_LabelWidget(label), cstr_Lang("toggle.no"))) { |
1688 | updateText_LabelWidget((iLabelWidget *) d, | 1686 | updateText_LabelWidget( |
1689 | collectNewCStr_String(isSelected_Widget(d) ? YES : NO)); | 1687 | (iLabelWidget *) d, |
1688 | collectNewCStr_String(isSelected_Widget(d) ? "${toggle.yes}" : "${toggle.no}")); | ||
1690 | } | 1689 | } |
1691 | else { | 1690 | else { |
1692 | refresh_Widget(d); | 1691 | refresh_Widget(d); |
@@ -1707,9 +1706,10 @@ static iBool toggleHandler_(iWidget *d, const char *cmd) { | |||
1707 | } | 1706 | } |
1708 | 1707 | ||
1709 | iWidget *makeToggle_Widget(const char *id) { | 1708 | iWidget *makeToggle_Widget(const char *id) { |
1710 | iWidget *toggle = as_Widget(new_LabelWidget("YES", "toggle")); /* "YES" for sizing */ | 1709 | iWidget *toggle = as_Widget(new_LabelWidget("${toggle.yes}", "toggle")); /* "YES" for sizing */ |
1711 | setId_Widget(toggle, id); | 1710 | setId_Widget(toggle, id); |
1712 | updateTextCStr_LabelWidget((iLabelWidget *) toggle, "NO"); /* actual initial value */ | 1711 | updateTextCStr_LabelWidget((iLabelWidget *) toggle, "${toggle.no}"); /* actual initial value */ |
1712 | setFlags_Widget(toggle, fixedWidth_WidgetFlag, iTrue); | ||
1713 | setCommandHandler_Widget(toggle, toggleHandler_); | 1713 | setCommandHandler_Widget(toggle, toggleHandler_); |
1714 | return toggle; | 1714 | return toggle; |
1715 | } | 1715 | } |
@@ -1787,6 +1787,11 @@ static void addFontButtons_(iWidget *parent, const char *id) { | |||
1787 | delete_Array(items); | 1787 | delete_Array(items); |
1788 | } | 1788 | } |
1789 | 1789 | ||
1790 | static int cmp_MenuItem_(const void *e1, const void *e2) { | ||
1791 | const iMenuItem *a = e1, *b = e2; | ||
1792 | return iCmpStr(a->label, b->label); | ||
1793 | } | ||
1794 | |||
1790 | iWidget *makePreferences_Widget(void) { | 1795 | iWidget *makePreferences_Widget(void) { |
1791 | iWidget *dlg = makeSheet_Widget("prefs"); | 1796 | iWidget *dlg = makeSheet_Widget("prefs"); |
1792 | addChildFlags_Widget(dlg, | 1797 | addChildFlags_Widget(dlg, |
@@ -1820,6 +1825,36 @@ iWidget *makePreferences_Widget(void) { | |||
1820 | } | 1825 | } |
1821 | /* Window. */ { | 1826 | /* Window. */ { |
1822 | appendTwoColumnPage_(tabs, "${heading.prefs.interface}", '2', &headings, &values); | 1827 | appendTwoColumnPage_(tabs, "${heading.prefs.interface}", '2', &headings, &values); |
1828 | /* UI languages. */ { | ||
1829 | iArray *uiLangs = collectNew_Array(sizeof(iMenuItem)); | ||
1830 | const iMenuItem langItems[] = { | ||
1831 | { "${lang.en}", 0, 0, "uilang id:en" }, | ||
1832 | { "${lang.fi}", 0, 0, "uilang id:fi" }, | ||
1833 | }; | ||
1834 | pushBackN_Array(uiLangs, langItems, iElemCount(langItems)); | ||
1835 | sort_Array(uiLangs, cmp_MenuItem_); | ||
1836 | /* TODO: Add an arrange flag for resizing parent to widest child. */ | ||
1837 | int widest = 0; | ||
1838 | size_t widestPos = iInvalidPos; | ||
1839 | iConstForEach(Array, i, uiLangs) { | ||
1840 | const int width = | ||
1841 | advance_Text(uiLabel_FontId, | ||
1842 | translateCStr_Lang(((const iMenuItem *) i.value)->label)) | ||
1843 | .x; | ||
1844 | if (widestPos == iInvalidPos || width > widest) { | ||
1845 | widest = width; | ||
1846 | widestPos = index_ArrayConstIterator(&i); | ||
1847 | } | ||
1848 | } | ||
1849 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.uilang}"))); | ||
1850 | setId_Widget(addChildFlags_Widget(values, | ||
1851 | iClob(makeMenuButton_LabelWidget( | ||
1852 | value_Array(uiLangs, widestPos, iMenuItem).label, | ||
1853 | data_Array(uiLangs), | ||
1854 | size_Array(uiLangs))), | ||
1855 | 0), | ||
1856 | "prefs.uilang"); | ||
1857 | } | ||
1823 | #if defined (iPlatformApple) || defined (iPlatformMSys) | 1858 | #if defined (iPlatformApple) || defined (iPlatformMSys) |
1824 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.ostheme}"))); | 1859 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.ostheme}"))); |
1825 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.ostheme"))); | 1860 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.ostheme"))); |
@@ -1898,11 +1933,15 @@ iWidget *makePreferences_Widget(void) { | |||
1898 | addFontButtons_(values, "font"); | 1933 | addFontButtons_(values, "font"); |
1899 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.mono}"))); | 1934 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.mono}"))); |
1900 | iWidget *mono = new_Widget(); | 1935 | iWidget *mono = new_Widget(); |
1901 | /* TODO: Needs labels! */ | 1936 | iWidget *tog; |
1902 | setTextCStr_LabelWidget( | 1937 | setTextCStr_LabelWidget( |
1903 | addChild_Widget(mono, iClob(makeToggle_Widget("prefs.mono.gemini"))), "${prefs.mono.gemini}"); | 1938 | addChild_Widget(mono, tog = iClob(makeToggle_Widget("prefs.mono.gemini"))), "${prefs.mono.gemini}"); |
1939 | setFlags_Widget(tog, fixedWidth_WidgetFlag, iFalse); | ||
1940 | updateSize_LabelWidget((iLabelWidget *) tog); | ||
1904 | setTextCStr_LabelWidget( | 1941 | setTextCStr_LabelWidget( |
1905 | addChild_Widget(mono, iClob(makeToggle_Widget("prefs.mono.gopher"))), "${prefs.mono.gopher}"); | 1942 | addChild_Widget(mono, tog = iClob(makeToggle_Widget("prefs.mono.gopher"))), "${prefs.mono.gopher}"); |
1943 | setFlags_Widget(tog, fixedWidth_WidgetFlag, iFalse); | ||
1944 | updateSize_LabelWidget((iLabelWidget *) tog); | ||
1906 | addChildFlags_Widget(values, iClob(mono), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 1945 | addChildFlags_Widget(values, iClob(mono), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
1907 | } | 1946 | } |
1908 | makeTwoColumnHeading_("${heading.prefs.paragraph}", headings, values); | 1947 | makeTwoColumnHeading_("${heading.prefs.paragraph}", headings, values); |
diff --git a/src/ui/window.c b/src/ui/window.c index 6949e245..97500b22 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -1820,6 +1820,10 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
1820 | if (isMetricsChange_UserEvent(&event)) { | 1820 | if (isMetricsChange_UserEvent(&event)) { |
1821 | updateMetrics_Window_(d); | 1821 | updateMetrics_Window_(d); |
1822 | } | 1822 | } |
1823 | if (isCommand_UserEvent(&event, "lang.changed")) { | ||
1824 | invalidate_Window_(d); | ||
1825 | arrange_Widget(d->root); | ||
1826 | } | ||
1823 | if (oldHover != hover_Widget()) { | 1827 | if (oldHover != hover_Widget()) { |
1824 | postRefresh_App(); | 1828 | postRefresh_App(); |
1825 | } | 1829 | } |