diff options
Diffstat (limited to 'src/ui')
-rw-r--r-- | src/ui/bindingswidget.c | 1 | ||||
-rw-r--r-- | src/ui/certimportwidget.c | 4 | ||||
-rw-r--r-- | src/ui/documentwidget.c | 9 | ||||
-rw-r--r-- | src/ui/inputwidget.c | 2 | ||||
-rw-r--r-- | src/ui/listwidget.c | 13 | ||||
-rw-r--r-- | src/ui/lookupwidget.c | 4 | ||||
-rw-r--r-- | src/ui/paint.c | 5 | ||||
-rw-r--r-- | src/ui/translation.c | 5 | ||||
-rw-r--r-- | src/ui/util.c | 85 | ||||
-rw-r--r-- | src/ui/util.h | 4 | ||||
-rw-r--r-- | src/ui/visbuf.c | 64 | ||||
-rw-r--r-- | src/ui/visbuf.h | 2 | ||||
-rw-r--r-- | src/ui/widget.c | 218 | ||||
-rw-r--r-- | src/ui/widget.h | 6 | ||||
-rw-r--r-- | src/ui/window.c | 15 |
15 files changed, 323 insertions, 114 deletions
diff --git a/src/ui/bindingswidget.c b/src/ui/bindingswidget.c index c73982b3..dc23dd6e 100644 --- a/src/ui/bindingswidget.c +++ b/src/ui/bindingswidget.c | |||
@@ -110,6 +110,7 @@ static void updateItems_BindingsWidget_(iBindingsWidget *d) { | |||
110 | void init_BindingsWidget(iBindingsWidget *d) { | 110 | void init_BindingsWidget(iBindingsWidget *d) { |
111 | iWidget *w = as_Widget(d); | 111 | iWidget *w = as_Widget(d); |
112 | init_Widget(w); | 112 | init_Widget(w); |
113 | setId_Widget(w, "bindings"); | ||
113 | setFlags_Widget(w, resizeChildren_WidgetFlag, iTrue); | 114 | setFlags_Widget(w, resizeChildren_WidgetFlag, iTrue); |
114 | d->activePos = iInvalidPos; | 115 | d->activePos = iInvalidPos; |
115 | d->contextPos = iInvalidPos; | 116 | d->contextPos = iInvalidPos; |
diff --git a/src/ui/certimportwidget.c b/src/ui/certimportwidget.c index 43e8ff97..a4245603 100644 --- a/src/ui/certimportwidget.c +++ b/src/ui/certimportwidget.c | |||
@@ -148,8 +148,8 @@ void init_CertImportWidget(iCertImportWidget *d) { | |||
148 | } | 148 | } |
149 | addChild_Widget(w, iClob(page)); | 149 | addChild_Widget(w, iClob(page)); |
150 | arrange_Widget(w); | 150 | arrange_Widget(w); |
151 | setSize_Widget(as_Widget(d->crtLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12)); | 151 | setFixedSize_Widget(as_Widget(d->crtLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12)); |
152 | setSize_Widget(as_Widget(d->keyLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12)); | 152 | setFixedSize_Widget(as_Widget(d->keyLabel), init_I2(width_Widget(w) - 6.5 * gap_UI, gap_UI * 12)); |
153 | /* Buttons. */ | 153 | /* Buttons. */ |
154 | addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); | 154 | addChild_Widget(w, iClob(makePadding_Widget(gap_UI))); |
155 | iWidget *buttons = makeDialogButtons_Widget( | 155 | iWidget *buttons = makeDialogButtons_Widget( |
diff --git a/src/ui/documentwidget.c b/src/ui/documentwidget.c index 3b5ddb7c..9a50b611 100644 --- a/src/ui/documentwidget.c +++ b/src/ui/documentwidget.c | |||
@@ -1752,7 +1752,7 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
1752 | delete_Array(items); | 1752 | delete_Array(items); |
1753 | /* Enforce a minimum size. */ | 1753 | /* Enforce a minimum size. */ |
1754 | iWidget *sizer = new_Widget(); | 1754 | iWidget *sizer = new_Widget(); |
1755 | setSize_Widget(sizer, init_I2(gap_UI * 65, 1)); | 1755 | setFixedSize_Widget(sizer, init_I2(gap_UI * 65, 1)); |
1756 | addChildFlags_Widget(dlg, iClob(sizer), frameless_WidgetFlag); | 1756 | addChildFlags_Widget(dlg, iClob(sizer), frameless_WidgetFlag); |
1757 | setFlags_Widget(dlg, centerHorizontal_WidgetFlag, iFalse); | 1757 | setFlags_Widget(dlg, centerHorizontal_WidgetFlag, iFalse); |
1758 | if (deviceType_App() != phone_AppDeviceType) { | 1758 | if (deviceType_App() != phone_AppDeviceType) { |
@@ -2040,10 +2040,9 @@ static iBool handleCommand_DocumentWidget_(iDocumentWidget *d, const char *cmd) | |||
2040 | fetchNextUnfetchedImage_DocumentWidget_(d)) { | 2040 | fetchNextUnfetchedImage_DocumentWidget_(d)) { |
2041 | return iTrue; | 2041 | return iTrue; |
2042 | } | 2042 | } |
2043 | const float amount = argLabel_Command(cmd, "full") ? 1.0f : 0.5f; | 2043 | const float amount = argLabel_Command(cmd, "full") != 0 ? 1.0f : 0.5f; |
2044 | smoothScroll_DocumentWidget_(d, | 2044 | smoothScroll_DocumentWidget_(d, |
2045 | dir * (amount * height_Rect(documentBounds_DocumentWidget_(d)) - | 2045 | dir * amount * height_Rect(documentBounds_DocumentWidget_(d)), |
2046 | 0 * lineHeight_Text(paragraph_FontId)), | ||
2047 | smoothDuration_DocumentWidget_); | 2046 | smoothDuration_DocumentWidget_); |
2048 | return iTrue; | 2047 | return iTrue; |
2049 | } | 2048 | } |
@@ -3391,7 +3390,7 @@ static void draw_DocumentWidget_(const iDocumentWidget *d) { | |||
3391 | const iRangei vis = visibleRange_DocumentWidget_(d); | 3390 | const iRangei vis = visibleRange_DocumentWidget_(d); |
3392 | const iRangei full = { 0, size_GmDocument(d->doc).y }; | 3391 | const iRangei full = { 0, size_GmDocument(d->doc).y }; |
3393 | reposition_VisBuf(visBuf, vis); | 3392 | reposition_VisBuf(visBuf, vis); |
3394 | iRangei invalidRange[3]; | 3393 | iRangei invalidRange[iElemCount(d->visBuf->buffers)]; |
3395 | invalidRanges_VisBuf(visBuf, full, invalidRange); | 3394 | invalidRanges_VisBuf(visBuf, full, invalidRange); |
3396 | /* Redraw the invalid ranges. */ { | 3395 | /* Redraw the invalid ranges. */ { |
3397 | iPaint *p = &ctx.paint; | 3396 | iPaint *p = &ctx.paint; |
diff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c index 5593b5b9..0856db93 100644 --- a/src/ui/inputwidget.c +++ b/src/ui/inputwidget.c | |||
@@ -248,7 +248,7 @@ void setMaxLen_InputWidget(iInputWidget *d, size_t maxLen) { | |||
248 | /* Set a fixed size. */ | 248 | /* Set a fixed size. */ |
249 | iBlock *content = new_Block(maxLen); | 249 | iBlock *content = new_Block(maxLen); |
250 | fill_Block(content, 'M'); | 250 | fill_Block(content, 'M'); |
251 | setSize_Widget( | 251 | setFixedSize_Widget( |
252 | as_Widget(d), | 252 | as_Widget(d), |
253 | add_I2(measure_Text(d->font, cstr_Block(content)), init_I2(6 * gap_UI, 2 * gap_UI))); | 253 | add_I2(measure_Text(d->font, cstr_Block(content)), init_I2(6 * gap_UI, 2 * gap_UI))); |
254 | delete_Block(content); | 254 | delete_Block(content); |
diff --git a/src/ui/listwidget.c b/src/ui/listwidget.c index 942c46dd..95a59090 100644 --- a/src/ui/listwidget.c +++ b/src/ui/listwidget.c | |||
@@ -361,17 +361,18 @@ static void draw_ListWidget_(const iListWidget *d) { | |||
361 | /* TODO: This seems to draw two items per each shift of the visible region, even though | 361 | /* TODO: This seems to draw two items per each shift of the visible region, even though |
362 | one should be enough. Probably an off-by-one error in the calculation of the | 362 | one should be enough. Probably an off-by-one error in the calculation of the |
363 | invalid range. */ | 363 | invalid range. */ |
364 | iAssert(d->visBuf->buffers[0].texture); | 364 | iForIndices(i, d->visBuf->buffers) { |
365 | iAssert(d->visBuf->buffers[1].texture); | 365 | iAssert(d->visBuf->buffers[i].texture); |
366 | iAssert(d->visBuf->buffers[2].texture); | 366 | } |
367 | const int bg[3] = { w->bgColor, w->bgColor, w->bgColor }; | 367 | const int bg[iElemCount(d->visBuf->buffers)] = { |
368 | // const int bg[3] = { red_ColorId, magenta_ColorId, blue_ColorId }; | 368 | w->bgColor, w->bgColor, w->bgColor, w->bgColor |
369 | }; | ||
369 | const int bottom = numItems_ListWidget(d) * d->itemHeight; | 370 | const int bottom = numItems_ListWidget(d) * d->itemHeight; |
370 | const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight, | 371 | const iRangei vis = { d->scrollY / d->itemHeight * d->itemHeight, |
371 | ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight }; | 372 | ((d->scrollY + bounds.size.y) / d->itemHeight + 1) * d->itemHeight }; |
372 | reposition_VisBuf(d->visBuf, vis); | 373 | reposition_VisBuf(d->visBuf, vis); |
373 | /* Check which parts are invalid. */ | 374 | /* Check which parts are invalid. */ |
374 | iRangei invalidRange[3]; | 375 | iRangei invalidRange[iElemCount(d->visBuf->buffers)]; |
375 | invalidRanges_VisBuf(d->visBuf, (iRangei){ 0, bottom }, invalidRange); | 376 | invalidRanges_VisBuf(d->visBuf, (iRangei){ 0, bottom }, invalidRange); |
376 | iForIndices(i, d->visBuf->buffers) { | 377 | iForIndices(i, d->visBuf->buffers) { |
377 | iVisBufTexture *buf = &d->visBuf->buffers[i]; | 378 | iVisBufTexture *buf = &d->visBuf->buffers[i]; |
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c index c711d61f..f3fd54d2 100644 --- a/src/ui/lookupwidget.c +++ b/src/ui/lookupwidget.c | |||
@@ -657,8 +657,8 @@ static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { | |||
657 | const iWindow *window = get_Window(); | 657 | const iWindow *window = get_Window(); |
658 | const iInt2 rootSize = rootSize_Window(window); | 658 | const iInt2 rootSize = rootSize_Window(window); |
659 | const iRect navBarBounds = bounds_Widget(findWidget_App("navbar")); | 659 | const iRect navBarBounds = bounds_Widget(findWidget_App("navbar")); |
660 | setSize_Widget(w, init_I2(width_Widget(findWidget_App("url")), | 660 | setFixedSize_Widget(w, init_I2(width_Widget(findWidget_App("url")), |
661 | (rootSize.y - bottom_Rect(navBarBounds)) / 2)); | 661 | (rootSize.y - bottom_Rect(navBarBounds)) / 2)); |
662 | setPos_Widget(w, bottomLeft_Rect(bounds_Widget(findWidget_App("url")))); | 662 | setPos_Widget(w, bottomLeft_Rect(bounds_Widget(findWidget_App("url")))); |
663 | #if defined (iPlatformAppleMobile) | 663 | #if defined (iPlatformAppleMobile) |
664 | /* Adjust height based on keyboard size. */ { | 664 | /* Adjust height based on keyboard size. */ { |
diff --git a/src/ui/paint.c b/src/ui/paint.c index 36e3f703..857bf20c 100644 --- a/src/ui/paint.c +++ b/src/ui/paint.c | |||
@@ -67,6 +67,11 @@ void setClip_Paint(iPaint *d, iRect rect) { | |||
67 | rect.pos.y -= off; | 67 | rect.pos.y -= off; |
68 | rect.size.y = iMax(0, rect.size.y + off); | 68 | rect.size.y = iMax(0, rect.size.y + off); |
69 | } | 69 | } |
70 | if (rect.pos.x < 0) { | ||
71 | const int off = rect.pos.x; | ||
72 | rect.pos.x -= off; | ||
73 | rect.size.x = iMax(0, rect.size.x + off); | ||
74 | } | ||
70 | SDL_RenderSetClipRect(renderer_Paint_(d), (const SDL_Rect *) &rect); | 75 | SDL_RenderSetClipRect(renderer_Paint_(d), (const SDL_Rect *) &rect); |
71 | } | 76 | } |
72 | 77 | ||
diff --git a/src/ui/translation.c b/src/ui/translation.c index 86607fc6..4102fcb9 100644 --- a/src/ui/translation.c +++ b/src/ui/translation.c | |||
@@ -442,8 +442,9 @@ iBool handleCommand_Translation(iTranslation *d, const char *cmd) { | |||
442 | setFlags_Widget(as_Widget(acceptButton), disabled_WidgetFlag, iTrue); | 442 | setFlags_Widget(as_Widget(acceptButton), disabled_WidgetFlag, iTrue); |
443 | iTranslationProgressWidget *prog = new_TranslationProgressWidget(); | 443 | iTranslationProgressWidget *prog = new_TranslationProgressWidget(); |
444 | setPos_Widget(as_Widget(prog), langs->rect.pos); | 444 | setPos_Widget(as_Widget(prog), langs->rect.pos); |
445 | setSize_Widget(as_Widget(prog), langs->rect.size); | 445 | setFixedSize_Widget(as_Widget(prog), init_I2(width_Rect(innerBounds_Widget(d->dlg)), |
446 | addChild_Widget(d->dlg, iClob(prog)); | 446 | langs->rect.size.y)); |
447 | addChildFlags_Widget(d->dlg, iClob(prog), 0); | ||
447 | submit_Translation(d); | 448 | submit_Translation(d); |
448 | } | 449 | } |
449 | return iTrue; | 450 | return iTrue; |
diff --git a/src/ui/util.c b/src/ui/util.c index 60618181..564cf785 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -438,7 +438,7 @@ iInt2 delta_Click(const iClick *d) { | |||
438 | iWidget *makePadding_Widget(int size) { | 438 | iWidget *makePadding_Widget(int size) { |
439 | iWidget *pad = new_Widget(); | 439 | iWidget *pad = new_Widget(); |
440 | setId_Widget(pad, "padding"); | 440 | setId_Widget(pad, "padding"); |
441 | setSize_Widget(pad, init1_I2(size)); | 441 | setFixedSize_Widget(pad, init1_I2(size)); |
442 | return pad; | 442 | return pad; |
443 | } | 443 | } |
444 | 444 | ||
@@ -463,7 +463,7 @@ iWidget *makeHDiv_Widget(void) { | |||
463 | 463 | ||
464 | iWidget *addAction_Widget(iWidget *parent, int key, int kmods, const char *command) { | 464 | iWidget *addAction_Widget(iWidget *parent, int key, int kmods, const char *command) { |
465 | iLabelWidget *action = newKeyMods_LabelWidget("", key, kmods, command); | 465 | iLabelWidget *action = newKeyMods_LabelWidget("", key, kmods, command); |
466 | setSize_Widget(as_Widget(action), zero_I2()); | 466 | setFixedSize_Widget(as_Widget(action), zero_I2()); |
467 | addChildFlags_Widget(parent, iClob(action), hidden_WidgetFlag); | 467 | addChildFlags_Widget(parent, iClob(action), hidden_WidgetFlag); |
468 | return as_Widget(action); | 468 | return as_Widget(action); |
469 | } | 469 | } |
@@ -856,16 +856,23 @@ iWidget *removeTabPage_Widget(iWidget *tabs, size_t index) { | |||
856 | } | 856 | } |
857 | 857 | ||
858 | void resizeToLargestPage_Widget(iWidget *tabs) { | 858 | void resizeToLargestPage_Widget(iWidget *tabs) { |
859 | // puts("RESIZE TO LARGEST PAGE ..."); | ||
860 | iWidget *pages = findChild_Widget(tabs, "tabs.pages"); | ||
861 | iForEach(ObjectList, i, children_Widget(pages)) { | ||
862 | setMinSize_Widget(i.object, zero_I2()); | ||
863 | // resetSize_Widget(i.object); | ||
864 | } | ||
859 | arrange_Widget(tabs); | 865 | arrange_Widget(tabs); |
860 | iInt2 largest = zero_I2(); | 866 | iInt2 largest = zero_I2(); |
861 | iWidget *pages = findChild_Widget(tabs, "tabs.pages"); | 867 | iConstForEach(ObjectList, j, children_Widget(pages)) { |
862 | iConstForEach(ObjectList, i, children_Widget(pages)) { | 868 | const iWidget *page = constAs_Widget(j.object); |
863 | largest = max_I2(largest, ((const iWidget *) i.object)->rect.size); | 869 | largest = max_I2(largest, page->rect.size); |
864 | } | 870 | } |
865 | iForEach(ObjectList, j, children_Widget(pages)) { | 871 | iForEach(ObjectList, k, children_Widget(pages)) { |
866 | setSize_Widget(j.object, largest); | 872 | setMinSize_Widget(k.object, largest); |
867 | } | 873 | } |
868 | setSize_Widget(tabs, addY_I2(largest, height_Widget(findChild_Widget(tabs, "tabs.buttons")))); | 874 | setFixedSize_Widget(tabs, addY_I2(largest, height_Widget(findChild_Widget(tabs, "tabs.buttons")))); |
875 | // puts("... DONE WITH RESIZE TO LARGEST PAGE"); | ||
869 | } | 876 | } |
870 | 877 | ||
871 | iLabelWidget *tabButtonForPage_Widget_(iWidget *tabs, const iWidget *page) { | 878 | iLabelWidget *tabButtonForPage_Widget_(iWidget *tabs, const iWidget *page) { |
@@ -1012,7 +1019,7 @@ static void updateSheetPanelMetrics_(iWidget *sheet) { | |||
1012 | setSize_Widget(pad, init1_I2(naviHeight)); | 1019 | setSize_Widget(pad, init1_I2(naviHeight)); |
1013 | } | 1020 | } |
1014 | #endif | 1021 | #endif |
1015 | setSize_Widget(navi, init_I2(-1, naviHeight)); | 1022 | setFixedSize_Widget(navi, init_I2(-1, naviHeight)); |
1016 | } | 1023 | } |
1017 | 1024 | ||
1018 | static iBool slidePanelHandler_(iWidget *d, const char *cmd) { | 1025 | static iBool slidePanelHandler_(iWidget *d, const char *cmd) { |
@@ -1786,12 +1793,16 @@ static iBool toggleHandler_(iWidget *d, const char *cmd) { | |||
1786 | isSelected_Widget(d) ? 1 : 0)); | 1793 | isSelected_Widget(d) ? 1 : 0)); |
1787 | return iTrue; | 1794 | return iTrue; |
1788 | } | 1795 | } |
1796 | else if (equal_Command(cmd, "lang.changed")) { | ||
1797 | /* TODO: Measure labels again. */ | ||
1798 | } | ||
1789 | return iFalse; | 1799 | return iFalse; |
1790 | } | 1800 | } |
1791 | 1801 | ||
1792 | iWidget *makeToggle_Widget(const char *id) { | 1802 | iWidget *makeToggle_Widget(const char *id) { |
1793 | iWidget *toggle = as_Widget(new_LabelWidget("${toggle.yes}", "toggle")); /* "YES" for sizing */ | 1803 | iWidget *toggle = as_Widget(new_LabelWidget("${toggle.yes}", "toggle")); /* "YES" for sizing */ |
1794 | setId_Widget(toggle, id); | 1804 | setId_Widget(toggle, id); |
1805 | /* TODO: Measure both labels and use the larger of the two. */ | ||
1795 | updateTextCStr_LabelWidget((iLabelWidget *) toggle, "${toggle.no}"); /* actual initial value */ | 1806 | updateTextCStr_LabelWidget((iLabelWidget *) toggle, "${toggle.no}"); /* actual initial value */ |
1796 | setFlags_Widget(toggle, fixedWidth_WidgetFlag, iTrue); | 1807 | setFlags_Widget(toggle, fixedWidth_WidgetFlag, iTrue); |
1797 | setCommandHandler_Widget(toggle, toggleHandler_); | 1808 | setCommandHandler_Widget(toggle, toggleHandler_); |
@@ -1837,8 +1848,9 @@ static iWidget *appendTwoColumnPage_(iWidget *tabs, const char *title, int short | |||
1837 | } | 1848 | } |
1838 | 1849 | ||
1839 | static void makeTwoColumnHeading_(const char *title, iWidget *headings, iWidget *values) { | 1850 | static void makeTwoColumnHeading_(const char *title, iWidget *headings, iWidget *values) { |
1840 | addChild_Widget(headings, | 1851 | addChildFlags_Widget(headings, |
1841 | iClob(makeHeading_Widget(format_CStr(uiHeading_ColorEscape "%s", title)))); | 1852 | iClob(makeHeading_Widget(format_CStr(uiHeading_ColorEscape "%s", title))), |
1853 | ignoreForParentWidth_WidgetFlag); | ||
1842 | addChild_Widget(values, iClob(makeHeading_Widget(""))); | 1854 | addChild_Widget(values, iClob(makeHeading_Widget(""))); |
1843 | } | 1855 | } |
1844 | 1856 | ||
@@ -1878,6 +1890,36 @@ static int cmp_MenuItem_(const void *e1, const void *e2) { | |||
1878 | } | 1890 | } |
1879 | #endif | 1891 | #endif |
1880 | 1892 | ||
1893 | void updatePreferencesLayout_Widget(iWidget *prefs) { | ||
1894 | if (!prefs) return; | ||
1895 | /* Doing manual layout here because the widget arranging logic isn't sophisticated enough. */ | ||
1896 | /* TODO: Make the arranging more sophisticated to automate this. */ | ||
1897 | static const char *inputIds[] = { | ||
1898 | "prefs.searchurl", | ||
1899 | "prefs.downloads", | ||
1900 | "prefs.ca.file", | ||
1901 | "prefs.ca.path", | ||
1902 | "prefs.proxy.gemini", | ||
1903 | "prefs.proxy.gopher", | ||
1904 | "prefs.proxy.http" | ||
1905 | }; | ||
1906 | iWidget *tabs = findChild_Widget(prefs, "prefs.tabs"); | ||
1907 | /* Input fields expand to the right edge. */ | ||
1908 | /* TODO: Add an arrangement flag for this. */ | ||
1909 | iForIndices(i, inputIds) { | ||
1910 | iInputWidget *input = findChild_Widget(tabs, inputIds[i]); | ||
1911 | if (input) { | ||
1912 | as_Widget(input)->rect.size.x = 0; | ||
1913 | } | ||
1914 | } | ||
1915 | as_Widget(findChild_Widget(prefs, "bindings"))->rect.size.x = 0; | ||
1916 | resizeToLargestPage_Widget(tabs); | ||
1917 | arrange_Widget(prefs); | ||
1918 | iForIndices(i, inputIds) { | ||
1919 | expandInputFieldWidth_(findChild_Widget(tabs, inputIds[i])); | ||
1920 | } | ||
1921 | } | ||
1922 | |||
1881 | iWidget *makePreferences_Widget(void) { | 1923 | iWidget *makePreferences_Widget(void) { |
1882 | iWidget *dlg = makeSheet_Widget("prefs"); | 1924 | iWidget *dlg = makeSheet_Widget("prefs"); |
1883 | addChildFlags_Widget(dlg, | 1925 | addChildFlags_Widget(dlg, |
@@ -1984,9 +2026,6 @@ iWidget *makePreferences_Widget(void) { | |||
1984 | setId_Widget(addChild_Widget(values, iClob(new_InputWidget(8))), "prefs.uiscale"); | 2026 | setId_Widget(addChild_Widget(values, iClob(new_InputWidget(8))), "prefs.uiscale"); |
1985 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.retainwindow}"))); | 2027 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.retainwindow}"))); |
1986 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.retainwindow"))); | 2028 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.retainwindow"))); |
1987 | makeTwoColumnHeading_("${heading.prefs.widelayout}", headings, values); | ||
1988 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.sideicon}"))); | ||
1989 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.sideicon"))); | ||
1990 | } | 2029 | } |
1991 | /* Colors. */ { | 2030 | /* Colors. */ { |
1992 | appendTwoColumnPage_(tabs, "${heading.prefs.colors}", '3', &headings, &values); | 2031 | appendTwoColumnPage_(tabs, "${heading.prefs.colors}", '3', &headings, &values); |
@@ -2023,7 +2062,7 @@ iWidget *makePreferences_Widget(void) { | |||
2023 | addChildFlags_Widget(values, iClob(sats), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 2062 | addChildFlags_Widget(values, iClob(sats), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
2024 | } | 2063 | } |
2025 | /* Layout. */ { | 2064 | /* Layout. */ { |
2026 | appendTwoColumnPage_(tabs, "${heading.prefs.style}", '4', &headings, &values); | 2065 | setId_Widget(appendTwoColumnPage_(tabs, "${heading.prefs.style}", '4', &headings, &values), "prefs.page.style"); |
2027 | makeTwoColumnHeading_("${heading.prefs.fonts}", headings, values); | 2066 | makeTwoColumnHeading_("${heading.prefs.fonts}", headings, values); |
2028 | /* Fonts. */ { | 2067 | /* Fonts. */ { |
2029 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.headingfont}"))); | 2068 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.headingfont}"))); |
@@ -2063,6 +2102,9 @@ iWidget *makePreferences_Widget(void) { | |||
2063 | addChildFlags_Widget(values, iClob(quote), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); | 2102 | addChildFlags_Widget(values, iClob(quote), arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag); |
2064 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.biglede}"))); | 2103 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.biglede}"))); |
2065 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.biglede"))); | 2104 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.biglede"))); |
2105 | makeTwoColumnHeading_("${heading.prefs.widelayout}", headings, values); | ||
2106 | addChild_Widget(headings, iClob(makeHeading_Widget("${prefs.sideicon}"))); | ||
2107 | addChild_Widget(values, iClob(makeToggle_Widget("prefs.sideicon"))); | ||
2066 | } | 2108 | } |
2067 | /* Network. */ { | 2109 | /* Network. */ { |
2068 | appendTwoColumnPage_(tabs, "${heading.prefs.network}", '5', &headings, &values); | 2110 | appendTwoColumnPage_(tabs, "${heading.prefs.network}", '5', &headings, &values); |
@@ -2095,22 +2137,13 @@ iWidget *makePreferences_Widget(void) { | |||
2095 | appendFramelessTabPage_(tabs, iClob(bind), "${heading.prefs.keys}", '6', KMOD_PRIMARY); | 2137 | appendFramelessTabPage_(tabs, iClob(bind), "${heading.prefs.keys}", '6', KMOD_PRIMARY); |
2096 | } | 2138 | } |
2097 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); | 2139 | addChild_Widget(dlg, iClob(makePadding_Widget(gap_UI))); |
2098 | resizeToLargestPage_Widget(tabs); | 2140 | updatePreferencesLayout_Widget(dlg); |
2099 | arrange_Widget(dlg); | ||
2100 | /* Set input field sizes. */ { | ||
2101 | expandInputFieldWidth_(findChild_Widget(tabs, "prefs.searchurl")); | ||
2102 | expandInputFieldWidth_(findChild_Widget(tabs, "prefs.downloads")); | ||
2103 | expandInputFieldWidth_(findChild_Widget(tabs, "prefs.ca.file")); | ||
2104 | expandInputFieldWidth_(findChild_Widget(tabs, "prefs.ca.path")); | ||
2105 | expandInputFieldWidth_(findChild_Widget(tabs, "prefs.proxy.gemini")); | ||
2106 | expandInputFieldWidth_(findChild_Widget(tabs, "prefs.proxy.gopher")); | ||
2107 | expandInputFieldWidth_(findChild_Widget(tabs, "prefs.proxy.http")); | ||
2108 | } | ||
2109 | addChild_Widget(dlg, | 2141 | addChild_Widget(dlg, |
2110 | iClob(makeDialogButtons_Widget( | 2142 | iClob(makeDialogButtons_Widget( |
2111 | (iMenuItem[]){ { "${dismiss}", SDLK_ESCAPE, 0, "prefs.dismiss" } }, 1))); | 2143 | (iMenuItem[]){ { "${dismiss}", SDLK_ESCAPE, 0, "prefs.dismiss" } }, 1))); |
2112 | addChild_Widget(get_Window()->root, iClob(dlg)); | 2144 | addChild_Widget(get_Window()->root, iClob(dlg)); |
2113 | finalizeSheet_Widget(dlg); | 2145 | finalizeSheet_Widget(dlg); |
2146 | //printTree_Widget(dlg); | ||
2114 | return dlg; | 2147 | return dlg; |
2115 | } | 2148 | } |
2116 | 2149 | ||
diff --git a/src/ui/util.h b/src/ui/util.h index c6320e29..02b0df38 100644 --- a/src/ui/util.h +++ b/src/ui/util.h | |||
@@ -228,7 +228,9 @@ iWidget * makeMessage_Widget (const char *title, const char *msg); | |||
228 | iWidget * makeQuestion_Widget (const char *title, const char *msg, | 228 | iWidget * makeQuestion_Widget (const char *title, const char *msg, |
229 | const iMenuItem *items, size_t numItems); | 229 | const iMenuItem *items, size_t numItems); |
230 | 230 | ||
231 | iWidget * makePreferences_Widget (void); | 231 | iWidget * makePreferences_Widget (void); |
232 | void updatePreferencesLayout_Widget (iWidget *prefs); | ||
233 | |||
232 | iWidget * makeBookmarkEditor_Widget (void); | 234 | iWidget * makeBookmarkEditor_Widget (void); |
233 | iWidget * makeBookmarkCreation_Widget (const iString *url, const iString *title, iChar icon); | 235 | iWidget * makeBookmarkCreation_Widget (const iString *url, const iString *title, iChar icon); |
234 | iWidget * makeIdentityCreation_Widget (void); | 236 | iWidget * makeIdentityCreation_Widget (void); |
diff --git a/src/ui/visbuf.c b/src/ui/visbuf.c index 0f9e1092..198ad574 100644 --- a/src/ui/visbuf.c +++ b/src/ui/visbuf.c | |||
@@ -75,12 +75,13 @@ void dealloc_VisBuf(iVisBuf *d) { | |||
75 | void reposition_VisBuf(iVisBuf *d, const iRangei vis) { | 75 | void reposition_VisBuf(iVisBuf *d, const iRangei vis) { |
76 | d->vis = vis; | 76 | d->vis = vis; |
77 | iRangei good = { 0, 0 }; | 77 | iRangei good = { 0, 0 }; |
78 | size_t avail[3], numAvail = 0; | 78 | size_t avail[iElemCount(d->buffers)], numAvail = 0; |
79 | /* Check which buffers are available for reuse. */ { | 79 | /* Check which buffers are available for reuse. */ { |
80 | iForIndices(i, d->buffers) { | 80 | iForIndices(i, d->buffers) { |
81 | iVisBufTexture *buf = d->buffers + i; | 81 | iVisBufTexture *buf = d->buffers + i; |
82 | const iRangei region = { buf->origin, buf->origin + d->texSize.y }; | 82 | const iRangei region = { buf->origin, buf->origin + d->texSize.y }; |
83 | if (region.start >= vis.end || region.end <= vis.start) { | 83 | if (isEmpty_Rangei(buf->validRange) || |
84 | buf->validRange.start >= vis.end || buf->validRange.end <= vis.start) { | ||
84 | avail[numAvail++] = i; | 85 | avail[numAvail++] = i; |
85 | iZap(buf->validRange); | 86 | iZap(buf->validRange); |
86 | } | 87 | } |
@@ -89,25 +90,50 @@ void reposition_VisBuf(iVisBuf *d, const iRangei vis) { | |||
89 | } | 90 | } |
90 | } | 91 | } |
91 | } | 92 | } |
92 | if (numAvail == iElemCount(d->buffers)) { | 93 | iBool wasChanged = iFalse; |
93 | /* All buffers are outside the visible range, do a reset. */ | 94 | iBool doReset = (numAvail == iElemCount(d->buffers)); |
94 | d->buffers[0].origin = vis.start; | 95 | /* Try to extend to cover the visible range. */ |
95 | d->buffers[1].origin = vis.start + d->texSize.y; | 96 | while (!doReset && vis.start < good.start) { |
96 | d->buffers[2].origin = vis.start + 2 * d->texSize.y; | 97 | if (numAvail == 0) { |
98 | doReset = iTrue; | ||
99 | break; | ||
100 | } | ||
101 | good.start -= d->texSize.y; | ||
102 | d->buffers[avail[--numAvail]].origin = good.start; | ||
103 | wasChanged = iTrue; | ||
97 | } | 104 | } |
98 | else { | 105 | while (!doReset && vis.end > good.end) { |
99 | /* Extend to cover the visible range. */ | 106 | if (numAvail == 0) { |
100 | while (vis.start < good.start) { | 107 | doReset = iTrue; |
101 | iAssert(numAvail > 0); | 108 | break; |
102 | d->buffers[avail[--numAvail]].origin = good.start - d->texSize.y; | ||
103 | good.start -= d->texSize.y; | ||
104 | } | 109 | } |
105 | while (vis.end > good.end) { | 110 | d->buffers[avail[--numAvail]].origin = good.end; |
106 | iAssert(numAvail > 0); | 111 | good.end += d->texSize.y; |
107 | d->buffers[avail[--numAvail]].origin = good.end; | 112 | wasChanged = iTrue; |
108 | good.end += d->texSize.y; | 113 | } |
114 | if (doReset) { | ||
115 | // puts("VisBuf reset!"); | ||
116 | // fflush(stdout); | ||
117 | wasChanged = iTrue; | ||
118 | int pos = -1; | ||
119 | iForIndices(i, d->buffers) { | ||
120 | iZap(d->buffers[i].validRange); | ||
121 | d->buffers[i].origin = vis.start + pos++ * d->texSize.y; | ||
109 | } | 122 | } |
110 | } | 123 | } |
124 | #if 0 | ||
125 | if (wasChanged) { | ||
126 | printf("\nVISIBLE RANGE: %d ... %d\n", vis.start, vis.end); | ||
127 | iForIndices(i, d->buffers) { | ||
128 | const iVisBufTexture *bt = &d->buffers[i]; | ||
129 | printf(" %zu: buf %5d ... %5d valid %5d ... %5d\n", i, bt->origin, | ||
130 | bt->origin + d->texSize.y, | ||
131 | bt->validRange.start, | ||
132 | bt->validRange.end); | ||
133 | } | ||
134 | fflush(stdout); | ||
135 | } | ||
136 | #endif | ||
111 | } | 137 | } |
112 | 138 | ||
113 | void invalidRanges_VisBuf(const iVisBuf *d, const iRangei full, iRangei *out_invalidRanges) { | 139 | void invalidRanges_VisBuf(const iVisBuf *d, const iRangei full, iRangei *out_invalidRanges) { |
diff --git a/src/ui/visbuf.h b/src/ui/visbuf.h index 4b0908f9..b285e90b 100644 --- a/src/ui/visbuf.h +++ b/src/ui/visbuf.h | |||
@@ -38,7 +38,7 @@ struct Impl_VisBufTexture { | |||
38 | struct Impl_VisBuf { | 38 | struct Impl_VisBuf { |
39 | iInt2 texSize; | 39 | iInt2 texSize; |
40 | iRangei vis; | 40 | iRangei vis; |
41 | iVisBufTexture buffers[3]; | 41 | iVisBufTexture buffers[4]; |
42 | }; | 42 | }; |
43 | 43 | ||
44 | iDeclareTypeConstruction(VisBuf) | 44 | iDeclareTypeConstruction(VisBuf) |
diff --git a/src/ui/widget.c b/src/ui/widget.c index e19a9482..baabf673 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -86,6 +86,7 @@ void init_Widget(iWidget *d) { | |||
86 | init_String(&d->id); | 86 | init_String(&d->id); |
87 | d->flags = 0; | 87 | d->flags = 0; |
88 | d->rect = zero_Rect(); | 88 | d->rect = zero_Rect(); |
89 | d->minSize = zero_I2(); | ||
89 | d->bgColor = none_ColorId; | 90 | d->bgColor = none_ColorId; |
90 | d->frameColor = none_ColorId; | 91 | d->frameColor = none_ColorId; |
91 | init_Anim(&d->visualOffset, 0.0f); | 92 | init_Anim(&d->visualOffset, 0.0f); |
@@ -188,20 +189,25 @@ void setPos_Widget(iWidget *d, iInt2 pos) { | |||
188 | setFlags_Widget(d, fixedPosition_WidgetFlag, iTrue); | 189 | setFlags_Widget(d, fixedPosition_WidgetFlag, iTrue); |
189 | } | 190 | } |
190 | 191 | ||
191 | void setSize_Widget(iWidget *d, iInt2 size) { | 192 | void setFixedSize_Widget(iWidget *d, iInt2 fixedSize) { |
192 | int flags = fixedSize_WidgetFlag; | 193 | int flags = fixedSize_WidgetFlag; |
193 | if (size.x < 0) { | 194 | if (fixedSize.x < 0) { |
194 | size.x = d->rect.size.x; | 195 | fixedSize.x = d->rect.size.x; |
195 | flags &= ~fixedWidth_WidgetFlag; | 196 | flags &= ~fixedWidth_WidgetFlag; |
196 | } | 197 | } |
197 | if (size.y < 0) { | 198 | if (fixedSize.y < 0) { |
198 | size.y = d->rect.size.y; | 199 | fixedSize.y = d->rect.size.y; |
199 | flags &= ~fixedHeight_WidgetFlag; | 200 | flags &= ~fixedHeight_WidgetFlag; |
200 | } | 201 | } |
201 | d->rect.size = size; | 202 | d->rect.size = fixedSize; |
202 | setFlags_Widget(d, flags, iTrue); | 203 | setFlags_Widget(d, flags, iTrue); |
203 | } | 204 | } |
204 | 205 | ||
206 | void setMinSize_Widget(iWidget *d, iInt2 minSize) { | ||
207 | d->minSize = minSize; | ||
208 | /* rearranging needed to apply this */ | ||
209 | } | ||
210 | |||
205 | void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) { | 211 | void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) { |
206 | d->padding[0] = left; | 212 | d->padding[0] = left; |
207 | d->padding[1] = top; | 213 | d->padding[1] = top; |
@@ -268,33 +274,79 @@ static int widestChild_Widget_(const iWidget *d) { | |||
268 | return width; | 274 | return width; |
269 | } | 275 | } |
270 | 276 | ||
277 | static void arrange_Widget_(iWidget *); | ||
278 | static const iBool tracing_ = iFalse; | ||
279 | |||
280 | #define TRACE(d, ...) if (tracing_) { printf_Widget_(d, __VA_ARGS__); } | ||
281 | |||
282 | static int depth_Widget_(const iWidget *d) { | ||
283 | int depth = 0; | ||
284 | for (const iWidget *w = d->parent; w; w = w->parent) { | ||
285 | depth++; | ||
286 | } | ||
287 | return depth; | ||
288 | } | ||
289 | |||
290 | static void printf_Widget_(const iWidget *d, const char *format, ...) { | ||
291 | va_list args; | ||
292 | va_start(args, format); | ||
293 | iString *msg = new_String(); | ||
294 | for (size_t i = 0; i < depth_Widget_(d); ++i) { | ||
295 | appendCStr_String(msg, "| "); | ||
296 | } | ||
297 | appendFormat_String(msg, "[%p] %s(%s) ", d, class_Widget(d)->name, cstr_String(id_Widget(d))); | ||
298 | while (size_String(msg) < 44 + depth_Widget_(d) * 4) { | ||
299 | appendCStr_String(msg, " "); | ||
300 | } | ||
301 | iBlock *msg2 = new_Block(0); | ||
302 | vprintf_Block(msg2, format, args); | ||
303 | va_end(args); | ||
304 | printf("%s%s\n", cstr_String(msg), cstr_Block(msg2)); | ||
305 | delete_Block(msg2); | ||
306 | delete_String(msg); | ||
307 | } | ||
308 | |||
271 | static void setWidth_Widget_(iWidget *d, int width) { | 309 | static void setWidth_Widget_(iWidget *d, int width) { |
272 | iAssert(width >= 0); | 310 | iAssert(width >= 0); |
311 | TRACE(d, "attempt to set width to %d (current: %d, min width: %d)", width, d->rect.size.x, d->minSize.x); | ||
312 | width = iMax(width, d->minSize.x); | ||
273 | if (~d->flags & fixedWidth_WidgetFlag || d->flags & collapse_WidgetFlag) { | 313 | if (~d->flags & fixedWidth_WidgetFlag || d->flags & collapse_WidgetFlag) { |
274 | if (d->rect.size.x != width) { | 314 | if (d->rect.size.x != width) { |
275 | d->rect.size.x = width; | 315 | d->rect.size.x = width; |
316 | TRACE(d, "width has changed to %d", width); | ||
276 | if (class_Widget(d)->sizeChanged) { | 317 | if (class_Widget(d)->sizeChanged) { |
277 | const int oldHeight = d->rect.size.y; | 318 | const int oldHeight = d->rect.size.y; |
278 | class_Widget(d)->sizeChanged(d); | 319 | class_Widget(d)->sizeChanged(d); |
279 | if (d->rect.size.y != oldHeight) { | 320 | if (d->rect.size.y != oldHeight) { |
321 | TRACE(d, "sizeChanged() cuased height change to %d; redoing parent", d->rect.size.y); | ||
280 | /* Widget updated its height. */ | 322 | /* Widget updated its height. */ |
281 | arrange_Widget(d->parent); | 323 | arrange_Widget_(d->parent); |
324 | TRACE(d, "parent layout redone"); | ||
282 | } | 325 | } |
283 | } | 326 | } |
284 | } | 327 | } |
285 | } | 328 | } |
329 | else { | ||
330 | TRACE(d, "changing width not allowed; flags: %x", d->flags); | ||
331 | } | ||
286 | } | 332 | } |
287 | 333 | ||
288 | static void setHeight_Widget_(iWidget *d, int height) { | 334 | static void setHeight_Widget_(iWidget *d, int height) { |
289 | iAssert(height >= 0); | 335 | iAssert(height >= 0); |
336 | TRACE(d, "attempt to set height to %d (current: %d, min height: %d)", height, d->rect.size.y, d->minSize.y); | ||
337 | height = iMax(height, d->minSize.y); | ||
290 | if (~d->flags & fixedHeight_WidgetFlag || d->flags & collapse_WidgetFlag) { | 338 | if (~d->flags & fixedHeight_WidgetFlag || d->flags & collapse_WidgetFlag) { |
291 | if (d->rect.size.y != height) { | 339 | if (d->rect.size.y != height) { |
292 | d->rect.size.y = height; | 340 | d->rect.size.y = height; |
341 | TRACE(d, "height has changed to %d", height); | ||
293 | if (class_Widget(d)->sizeChanged) { | 342 | if (class_Widget(d)->sizeChanged) { |
294 | class_Widget(d)->sizeChanged(d); | 343 | class_Widget(d)->sizeChanged(d); |
295 | } | 344 | } |
296 | } | 345 | } |
297 | } | 346 | } |
347 | else { | ||
348 | TRACE(d, "changing height not allowed; flags: %x", d->flags); | ||
349 | } | ||
298 | } | 350 | } |
299 | 351 | ||
300 | iLocalDef iBool isCollapsed_Widget_(const iWidget *d) { | 352 | iLocalDef iBool isCollapsed_Widget_(const iWidget *d) { |
@@ -336,29 +388,63 @@ static void centerHorizontal_Widget_(iWidget *d) { | |||
336 | : rootSize_Window(get_Window()).x) - | 388 | : rootSize_Window(get_Window()).x) - |
337 | width_Rect(d->rect)) / | 389 | width_Rect(d->rect)) / |
338 | 2; | 390 | 2; |
391 | TRACE(d, "center horizontally: %d", d->rect.pos.x); | ||
339 | } | 392 | } |
340 | 393 | ||
341 | void arrange_Widget(iWidget *d) { | 394 | static void boundsOfChildren_Widget_(const iWidget *d, iRect *bounds_out) { |
395 | *bounds_out = zero_Rect(); | ||
396 | iConstForEach(ObjectList, i, d->children) { | ||
397 | const iWidget *child = constAs_Widget(i.object); | ||
398 | if (isCollapsed_Widget_(child)) { | ||
399 | continue; | ||
400 | } | ||
401 | iRect childRect = child->rect; | ||
402 | if (child->flags & ignoreForParentWidth_WidgetFlag) { | ||
403 | childRect.size.x = 0; | ||
404 | } | ||
405 | if (isEmpty_Rect(*bounds_out)) { | ||
406 | *bounds_out = childRect; | ||
407 | } | ||
408 | else { | ||
409 | *bounds_out = union_Rect(*bounds_out, childRect); | ||
410 | } | ||
411 | } | ||
412 | } | ||
413 | |||
414 | static void arrange_Widget_(iWidget *d) { | ||
415 | TRACE(d, "arranging..."); | ||
342 | if (isCollapsed_Widget_(d)) { | 416 | if (isCollapsed_Widget_(d)) { |
417 | TRACE(d, "collapsed => END"); | ||
343 | setFlags_Widget(d, wasCollapsed_WidgetFlag, iTrue); | 418 | setFlags_Widget(d, wasCollapsed_WidgetFlag, iTrue); |
344 | return; | 419 | return; |
345 | } | 420 | } |
346 | if (d->flags & moveToParentLeftEdge_WidgetFlag) { | 421 | if (d->flags & moveToParentLeftEdge_WidgetFlag) { |
347 | d->rect.pos.x = d->padding[0]; /* FIXME: Shouldn't this be d->parent->padding[0]? */ | 422 | d->rect.pos.x = d->padding[0]; /* FIXME: Shouldn't this be d->parent->padding[0]? */ |
423 | TRACE(d, "move to parent left edge: %d", d->rect.pos.x); | ||
348 | } | 424 | } |
349 | else if (d->flags & moveToParentRightEdge_WidgetFlag) { | 425 | else if (d->flags & moveToParentRightEdge_WidgetFlag) { |
350 | d->rect.pos.x = width_Rect(innerRect_Widget_(d->parent)) - width_Rect(d->rect); | 426 | d->rect.pos.x = width_Rect(innerRect_Widget_(d->parent)) - width_Rect(d->rect); |
427 | TRACE(d, "move to parent right edge: %d", d->rect.pos.x); | ||
351 | } | 428 | } |
352 | else if (d->flags & moveToParentBottomEdge_WidgetFlag) { | 429 | else if (d->flags & moveToParentBottomEdge_WidgetFlag) { |
353 | d->rect.pos.y = height_Rect(innerRect_Widget_(d->parent)) - height_Rect(d->rect); | 430 | d->rect.pos.y = height_Rect(innerRect_Widget_(d->parent)) - height_Rect(d->rect); |
431 | TRACE(d, "move to parent bottom edge: %d", d->rect.pos.y); | ||
354 | } | 432 | } |
355 | else if (d->flags & centerHorizontal_WidgetFlag) { | 433 | else if (d->flags & centerHorizontal_WidgetFlag) { |
356 | centerHorizontal_Widget_(d); | 434 | centerHorizontal_Widget_(d); |
357 | } | 435 | } |
358 | if (d->flags & resizeToParentWidth_WidgetFlag) { | 436 | if (d->flags & resizeToParentWidth_WidgetFlag) { |
359 | setWidth_Widget_(d, width_Rect(innerRect_Widget_(d->parent))); | 437 | iRect childBounds = zero_Rect(); |
438 | if (flags_Widget(d->parent) & arrangeWidth_WidgetFlag) { | ||
439 | /* Can't go narrower than what the children require, though. */ | ||
440 | boundsOfChildren_Widget_(d, &childBounds); | ||
441 | } | ||
442 | TRACE(d, "resize to parent width; child bounds width %d", childBounds.size.x, childBounds.size.y); | ||
443 | setWidth_Widget_(d, iMaxi(width_Rect(innerRect_Widget_(d->parent)), | ||
444 | width_Rect(childBounds))); | ||
360 | } | 445 | } |
361 | if (d->flags & resizeToParentHeight_WidgetFlag) { | 446 | if (d->flags & resizeToParentHeight_WidgetFlag) { |
447 | TRACE(d, "resize to parent height"); | ||
362 | setHeight_Widget_(d, height_Rect(innerRect_Widget_(d->parent))); | 448 | setHeight_Widget_(d, height_Rect(innerRect_Widget_(d->parent))); |
363 | } | 449 | } |
364 | if (d->flags & safePadding_WidgetFlag) { | 450 | if (d->flags & safePadding_WidgetFlag) { |
@@ -370,46 +456,44 @@ void arrange_Widget(iWidget *d) { | |||
370 | } | 456 | } |
371 | /* The rest of the arrangement depends on child widgets. */ | 457 | /* The rest of the arrangement depends on child widgets. */ |
372 | if (!d->children) { | 458 | if (!d->children) { |
459 | TRACE(d, "no children => END"); | ||
373 | return; | 460 | return; |
374 | } | 461 | } |
375 | const size_t childCount = numArrangedChildren_Widget_(d); | 462 | const size_t childCount = numArrangedChildren_Widget_(d); |
376 | /* There may still be unarranged children that need arranging internally. */ | 463 | TRACE(d, "%d arranged children", childCount); |
377 | if (childCount == 0) { | ||
378 | iForEach(ObjectList, i, d->children) { | ||
379 | iWidget *child = as_Widget(i.object); | ||
380 | if (isArranged_Widget_(child)) { | ||
381 | arrange_Widget(child); | ||
382 | } | ||
383 | } | ||
384 | return; | ||
385 | } | ||
386 | /* Resize children to fill the parent widget. */ | 464 | /* Resize children to fill the parent widget. */ |
387 | if (d->flags & resizeChildren_WidgetFlag) { | 465 | if (d->flags & resizeChildren_WidgetFlag) { |
388 | const iInt2 dirs = init_I2((d->flags & resizeWidthOfChildren_WidgetFlag) != 0, | 466 | const iInt2 dirs = init_I2((d->flags & resizeWidthOfChildren_WidgetFlag) != 0, |
389 | (d->flags & resizeHeightOfChildren_WidgetFlag) != 0); | 467 | (d->flags & resizeHeightOfChildren_WidgetFlag) != 0); |
468 | TRACE(d, "resize children, x:%d y:%d", dirs.x, dirs.y); | ||
390 | /* Collapse hidden children. */ | 469 | /* Collapse hidden children. */ |
391 | iBool collapseChanged = iFalse; | 470 | iBool collapseChanged = iFalse; |
392 | iForEach(ObjectList, c, d->children) { | 471 | iForEach(ObjectList, c, d->children) { |
393 | iWidget *child = as_Widget(c.object); | 472 | iWidget *child = as_Widget(c.object); |
394 | if (!isCollapsed_Widget_(child) && child->flags & wasCollapsed_WidgetFlag) { | 473 | if (!isCollapsed_Widget_(child) && child->flags & wasCollapsed_WidgetFlag) { |
395 | setFlags_Widget(child, wasCollapsed_WidgetFlag, iFalse); | 474 | setFlags_Widget(child, wasCollapsed_WidgetFlag, iFalse); |
475 | TRACE(d, "child %p is uncollapsed", child); | ||
396 | /* Undo collapse and determine the normal size again. */ | 476 | /* Undo collapse and determine the normal size again. */ |
397 | arrange_Widget(d); | 477 | arrange_Widget_(d); |
398 | collapseChanged = iTrue; | 478 | collapseChanged = iTrue; |
399 | } | 479 | } |
400 | else if (isCollapsed_Widget_(child) && ~child->flags & wasCollapsed_WidgetFlag) { | 480 | else if (isCollapsed_Widget_(child) && ~child->flags & wasCollapsed_WidgetFlag) { |
401 | setFlags_Widget(child, wasCollapsed_WidgetFlag, iTrue); | 481 | setFlags_Widget(child, wasCollapsed_WidgetFlag, iTrue); |
402 | collapseChanged = iTrue; | 482 | collapseChanged = iTrue; |
483 | TRACE(d, "child %p flagged as collapsed", child); | ||
403 | } | 484 | } |
404 | } | 485 | } |
405 | if (collapseChanged) { | 486 | if (collapseChanged) { |
406 | arrange_Widget(d); /* Redo with the new child sizes. */ | 487 | TRACE(d, "redoing arrangement due to changes in child collapse state"); |
488 | arrange_Widget_(d); /* Redo with the new child sizes. */ | ||
407 | return; | 489 | return; |
408 | } | 490 | } |
409 | const int expCount = numExpandingChildren_Widget_(d); | 491 | const int expCount = numExpandingChildren_Widget_(d); |
492 | TRACE(d, "%d expanding children", expCount); | ||
410 | /* Only resize the expanding children, not touching the others. */ | 493 | /* Only resize the expanding children, not touching the others. */ |
411 | if (expCount > 0) { | 494 | if (expCount > 0) { |
412 | iInt2 avail = innerRect_Widget_(d).size; | 495 | iInt2 avail = innerRect_Widget_(d).size; |
496 | TRACE(d, "inner size: %dx%d", avail.x, avail.y); | ||
413 | iConstForEach(ObjectList, i, d->children) { | 497 | iConstForEach(ObjectList, i, d->children) { |
414 | const iWidget *child = constAs_Widget(i.object); | 498 | const iWidget *child = constAs_Widget(i.object); |
415 | if (!isArranged_Widget_(child)) { | 499 | if (!isArranged_Widget_(child)) { |
@@ -420,9 +504,11 @@ void arrange_Widget(iWidget *d) { | |||
420 | } | 504 | } |
421 | } | 505 | } |
422 | avail = divi_I2(max_I2(zero_I2(), avail), expCount); | 506 | avail = divi_I2(max_I2(zero_I2(), avail), expCount); |
507 | TRACE(d, "changing child sizes (expand mode)..."); | ||
423 | iForEach(ObjectList, j, d->children) { | 508 | iForEach(ObjectList, j, d->children) { |
424 | iWidget *child = as_Widget(j.object); | 509 | iWidget *child = as_Widget(j.object); |
425 | if (!isArranged_Widget_(child)) { | 510 | if (!isArranged_Widget_(child)) { |
511 | TRACE(d, "child %p is not arranged", child); | ||
426 | continue; | 512 | continue; |
427 | } | 513 | } |
428 | if (child->flags & expand_WidgetFlag) { | 514 | if (child->flags & expand_WidgetFlag) { |
@@ -445,6 +531,7 @@ void arrange_Widget(iWidget *d) { | |||
445 | } | 531 | } |
446 | } | 532 | } |
447 | } | 533 | } |
534 | TRACE(d, "...done changing child sizes (expand mode)"); | ||
448 | } | 535 | } |
449 | else { | 536 | else { |
450 | /* Evenly size all children. */ | 537 | /* Evenly size all children. */ |
@@ -458,6 +545,7 @@ void arrange_Widget(iWidget *d) { | |||
458 | childSize.y /= childCount; | 545 | childSize.y /= childCount; |
459 | unpaddedChildSize.y /= childCount; | 546 | unpaddedChildSize.y /= childCount; |
460 | } | 547 | } |
548 | TRACE(d, "begin changing child sizes (EVEN mode)..."); | ||
461 | iForEach(ObjectList, i, d->children) { | 549 | iForEach(ObjectList, i, d->children) { |
462 | iWidget *child = as_Widget(i.object); | 550 | iWidget *child = as_Widget(i.object); |
463 | if (isArranged_Widget_(child) && ~child->flags & parentCannotResize_WidgetFlag) { | 551 | if (isArranged_Widget_(child) && ~child->flags & parentCannotResize_WidgetFlag) { |
@@ -468,34 +556,52 @@ void arrange_Widget(iWidget *d) { | |||
468 | setHeight_Widget_(child, child->flags & unpadded_WidgetFlag ? unpaddedChildSize.y : childSize.y); | 556 | setHeight_Widget_(child, child->flags & unpadded_WidgetFlag ? unpaddedChildSize.y : childSize.y); |
469 | } | 557 | } |
470 | } | 558 | } |
559 | else { | ||
560 | TRACE(d, "child %p cannot be resized (parentCannotResize: %d)", child, | ||
561 | (child->flags & parentCannotResize_WidgetFlag) != 0); | ||
562 | } | ||
471 | } | 563 | } |
564 | TRACE(d, "...done changing child sizes (EVEN mode)"); | ||
472 | } | 565 | } |
473 | } | 566 | } |
474 | if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { | 567 | if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { |
475 | const int widest = widestChild_Widget_(d); | 568 | const int widest = widestChild_Widget_(d); |
569 | TRACE(d, "resizing children to widest child (%d)...", widest); | ||
476 | iForEach(ObjectList, i, d->children) { | 570 | iForEach(ObjectList, i, d->children) { |
477 | iWidget *child = as_Widget(i.object); | 571 | iWidget *child = as_Widget(i.object); |
478 | if (isArranged_Widget_(child) && ~child->flags & parentCannotResize_WidgetFlag) { | 572 | if (isArranged_Widget_(child) && ~child->flags & parentCannotResize_WidgetFlag) { |
479 | setWidth_Widget_(child, widest); | 573 | setWidth_Widget_(child, widest); |
480 | } | 574 | } |
575 | else { | ||
576 | TRACE(d, "child %p cannot be resized (parentCannotResize: %d)", child, | ||
577 | (child->flags & parentCannotResize_WidgetFlag) != 0); | ||
578 | } | ||
481 | } | 579 | } |
580 | TRACE(d, "...done resizing children to widest child"); | ||
482 | } | 581 | } |
483 | iInt2 pos = initv_I2(d->padding); | 582 | iInt2 pos = initv_I2(d->padding); |
583 | TRACE(d, "begin positioning children from %d,%d (flags:%s%s)...", pos.x, pos.y, | ||
584 | d->flags & arrangeHorizontal_WidgetFlag ? " horiz" : "", | ||
585 | d->flags & arrangeVertical_WidgetFlag ? " vert" : ""); | ||
484 | iForEach(ObjectList, i, d->children) { | 586 | iForEach(ObjectList, i, d->children) { |
485 | iWidget *child = as_Widget(i.object); | 587 | iWidget *child = as_Widget(i.object); |
486 | arrange_Widget(child); | 588 | arrange_Widget_(child); |
487 | if (!isArranged_Widget_(child)) { | 589 | if (!isArranged_Widget_(child)) { |
590 | TRACE(d, "child %p arranging prohibited", child); | ||
488 | continue; | 591 | continue; |
489 | } | 592 | } |
490 | if (child->flags & centerHorizontal_WidgetFlag) { | 593 | if (child->flags & centerHorizontal_WidgetFlag) { |
594 | TRACE(d, "child %p is centered, skipping", child); | ||
491 | continue; | 595 | continue; |
492 | } | 596 | } |
493 | if (d->flags & (arrangeHorizontal_WidgetFlag | arrangeVertical_WidgetFlag)) { | 597 | if (d->flags & (arrangeHorizontal_WidgetFlag | arrangeVertical_WidgetFlag)) { |
494 | if (child->flags & | 598 | if (child->flags & |
495 | (moveToParentLeftEdge_WidgetFlag | moveToParentRightEdge_WidgetFlag)) { | 599 | (moveToParentLeftEdge_WidgetFlag | moveToParentRightEdge_WidgetFlag)) { |
600 | TRACE(d, "child %p is attached an edge, skipping", child); | ||
496 | continue; /* Not part of the sequential arrangement .*/ | 601 | continue; /* Not part of the sequential arrangement .*/ |
497 | } | 602 | } |
498 | child->rect.pos = pos; | 603 | child->rect.pos = pos; |
604 | TRACE(d, "child %p set position to %d,%d", child, pos.x, pos.y); | ||
499 | if (d->flags & arrangeHorizontal_WidgetFlag) { | 605 | if (d->flags & arrangeHorizontal_WidgetFlag) { |
500 | pos.x += child->rect.size.x; | 606 | pos.x += child->rect.size.x; |
501 | } | 607 | } |
@@ -506,26 +612,20 @@ void arrange_Widget(iWidget *d) { | |||
506 | else if ((d->flags & resizeChildren_WidgetFlag) == resizeChildren_WidgetFlag && | 612 | else if ((d->flags & resizeChildren_WidgetFlag) == resizeChildren_WidgetFlag && |
507 | ~child->flags & moveToParentBottomEdge_WidgetFlag) { | 613 | ~child->flags & moveToParentBottomEdge_WidgetFlag) { |
508 | child->rect.pos = pos; | 614 | child->rect.pos = pos; |
615 | TRACE(d, "child %p set position to %d,%d (not sequential, children being resized)", child, pos.x, pos.y); | ||
509 | } | 616 | } |
510 | else if (d->flags & resizeWidthOfChildren_WidgetFlag) { | 617 | else if (d->flags & resizeWidthOfChildren_WidgetFlag) { |
511 | child->rect.pos.x = pos.x; | 618 | child->rect.pos.x = pos.x; |
619 | TRACE(d, "child %p set X to %d (not sequential, children being resized)", child, pos.x); | ||
512 | } | 620 | } |
513 | } | 621 | } |
622 | TRACE(d, "...done positioning children"); | ||
514 | /* Update the size of the widget according to the arrangement. */ | 623 | /* Update the size of the widget according to the arrangement. */ |
515 | if (d->flags & arrangeSize_WidgetFlag) { | 624 | if (d->flags & arrangeSize_WidgetFlag) { |
516 | iRect bounds = zero_Rect(); | 625 | iRect bounds; |
517 | iConstForEach(ObjectList, i, d->children) { | 626 | boundsOfChildren_Widget_(d, &bounds); |
518 | const iWidget *child = constAs_Widget(i.object); | 627 | TRACE(d, "begin arranging own size; bounds of children: %d,%d %dx%d", |
519 | if (isCollapsed_Widget_(child)) { | 628 | bounds.pos.x, bounds.pos.y, bounds.size.x, bounds.size.y); |
520 | continue; | ||
521 | } | ||
522 | if (isEmpty_Rect(bounds)) { | ||
523 | bounds = child->rect; | ||
524 | } | ||
525 | else { | ||
526 | bounds = union_Rect(bounds, child->rect); | ||
527 | } | ||
528 | } | ||
529 | adjustEdges_Rect(&bounds, -d->padding[1], d->padding[2], d->padding[3], -d->padding[0]); | 629 | adjustEdges_Rect(&bounds, -d->padding[1], d->padding[2], d->padding[3], -d->padding[0]); |
530 | if (d->flags & arrangeWidth_WidgetFlag) { | 630 | if (d->flags & arrangeWidth_WidgetFlag) { |
531 | setWidth_Widget_(d, bounds.size.x); | 631 | setWidth_Widget_(d, bounds.size.x); |
@@ -535,14 +635,15 @@ void arrange_Widget(iWidget *d) { | |||
535 | if (child->flags & | 635 | if (child->flags & |
536 | (resizeToParentWidth_WidgetFlag | | 636 | (resizeToParentWidth_WidgetFlag | |
537 | moveToParentLeftEdge_WidgetFlag | | 637 | moveToParentLeftEdge_WidgetFlag | |
538 | moveToParentBottomEdge_WidgetFlag | | ||
539 | moveToParentRightEdge_WidgetFlag)) { | 638 | moveToParentRightEdge_WidgetFlag)) { |
540 | arrange_Widget(child); | 639 | TRACE(d, "rearranging child %p because its size or position depends on parent width", child); |
640 | arrange_Widget_(child); | ||
541 | } | 641 | } |
542 | } | 642 | } |
543 | if (d->flags & moveToParentRightEdge_WidgetFlag) { | 643 | if (d->flags & moveToParentRightEdge_WidgetFlag) { |
544 | /* TODO: Fix this: not DRY. See beginning of method. */ | 644 | /* TODO: Fix this: not DRY. See beginning of method. */ |
545 | d->rect.pos.x = width_Rect(innerRect_Widget_(d->parent)) - width_Rect(d->rect); | 645 | d->rect.pos.x = width_Rect(innerRect_Widget_(d->parent)) - width_Rect(d->rect); |
646 | TRACE(d, "after width change moving to right edge of parent, set X to %d", d, d->rect.pos.x); | ||
546 | } | 647 | } |
547 | } | 648 | } |
548 | if (d->flags & arrangeHeight_WidgetFlag) { | 649 | if (d->flags & arrangeHeight_WidgetFlag) { |
@@ -550,8 +651,10 @@ void arrange_Widget(iWidget *d) { | |||
550 | /* Parent size changed, must update the children.*/ | 651 | /* Parent size changed, must update the children.*/ |
551 | iForEach(ObjectList, j, d->children) { | 652 | iForEach(ObjectList, j, d->children) { |
552 | iWidget *child = as_Widget(j.object); | 653 | iWidget *child = as_Widget(j.object); |
553 | if (child->flags & resizeToParentHeight_WidgetFlag) { | 654 | if (child->flags & (resizeToParentHeight_WidgetFlag | |
554 | arrange_Widget(child); | 655 | moveToParentBottomEdge_WidgetFlag)) { |
656 | TRACE(d, "rearranging child %p because its size or position depends on parent height", child); | ||
657 | arrange_Widget_(child); | ||
555 | } | 658 | } |
556 | } | 659 | } |
557 | } | 660 | } |
@@ -562,9 +665,31 @@ void arrange_Widget(iWidget *d) { | |||
562 | if (d->flags & centerHorizontal_WidgetFlag) { | 665 | if (d->flags & centerHorizontal_WidgetFlag) { |
563 | centerHorizontal_Widget_(d); | 666 | centerHorizontal_Widget_(d); |
564 | } | 667 | } |
668 | TRACE(d, "...done arranging own size"); | ||
669 | } | ||
670 | TRACE(d, "END"); | ||
671 | } | ||
672 | |||
673 | void resetSize_Widget(iWidget *d) { | ||
674 | if (~d->flags & fixedWidth_WidgetFlag) { | ||
675 | d->rect.size.x = d->minSize.x; | ||
676 | } | ||
677 | if (~d->flags & fixedHeight_WidgetFlag) { | ||
678 | d->rect.size.y = d->minSize.y; | ||
679 | } | ||
680 | iForEach(ObjectList, i, children_Widget(d)) { | ||
681 | iWidget *child = as_Widget(i.object); | ||
682 | if (isArranged_Widget_(child)) { | ||
683 | resetSize_Widget(child); | ||
684 | } | ||
565 | } | 685 | } |
566 | } | 686 | } |
567 | 687 | ||
688 | void arrange_Widget(iWidget *d) { | ||
689 | //resetSize_Widget_(d); /* back to initial default sizes */ | ||
690 | arrange_Widget_(d); | ||
691 | } | ||
692 | |||
568 | static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { | 693 | static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) { |
569 | if (d->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { | 694 | if (d->flags & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { |
570 | const int off = iRound(value_Anim(&d->visualOffset)); | 695 | const int off = iRound(value_Anim(&d->visualOffset)); |
@@ -1350,6 +1475,7 @@ void refresh_Widget(const iAnyObject *d) { | |||
1350 | postRefresh_App(); | 1475 | postRefresh_App(); |
1351 | } | 1476 | } |
1352 | 1477 | ||
1478 | /* Debug utility for inspecting widget trees. */ | ||
1353 | #include "labelwidget.h" | 1479 | #include "labelwidget.h" |
1354 | static void printTree_Widget_(const iWidget *d, int indent) { | 1480 | static void printTree_Widget_(const iWidget *d, int indent) { |
1355 | for (int i = 0; i < indent; ++i) { | 1481 | for (int i = 0; i < indent; ++i) { |
@@ -1361,9 +1487,17 @@ static void printTree_Widget_(const iWidget *d, int indent) { | |||
1361 | cstr_String(text_LabelWidget((const iLabelWidget *) d)), | 1487 | cstr_String(text_LabelWidget((const iLabelWidget *) d)), |
1362 | cstr_String(command_LabelWidget((const iLabelWidget *) d))); | 1488 | cstr_String(command_LabelWidget((const iLabelWidget *) d))); |
1363 | } | 1489 | } |
1364 | printf("size:%dx%d [%d..%d %d:%d] flags:%08llx%s\n", d->rect.size.x, d->rect.size.y, | 1490 | printf("size:%dx%d {min:%dx%d} [%d..%d %d:%d] flags:%08llx%s%s%s%s%s\n", |
1365 | d->padding[0], d->padding[2], d->padding[1], d->padding[3], | 1491 | d->rect.size.x, d->rect.size.y, |
1366 | (long long unsigned int) d->flags, d->flags & tight_WidgetFlag ? " tight" : ""); | 1492 | d->minSize.x, d->minSize.y, |
1493 | d->padding[0], d->padding[2], | ||
1494 | d->padding[1], d->padding[3], | ||
1495 | (long long unsigned int) d->flags, | ||
1496 | d->flags & expand_WidgetFlag ? " exp" : "", | ||
1497 | d->flags & tight_WidgetFlag ? " tight" : "", | ||
1498 | d->flags & fixedWidth_WidgetFlag ? " fixW" : "", | ||
1499 | d->flags & fixedHeight_WidgetFlag ? " fixH" : "", | ||
1500 | d->flags & resizeToParentWidth_WidgetFlag ? " rsPrnW" : ""); | ||
1367 | iConstForEach(ObjectList, i, d->children) { | 1501 | iConstForEach(ObjectList, i, d->children) { |
1368 | printTree_Widget_(i.object, indent + 1); | 1502 | printTree_Widget_(i.object, indent + 1); |
1369 | } | 1503 | } |
diff --git a/src/ui/widget.h b/src/ui/widget.h index ad7ce168..4c5b7d85 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -112,6 +112,7 @@ enum iWidgetFlag { | |||
112 | #define safePadding_WidgetFlag iBit64(56) /* padded using safe area insets */ | 112 | #define safePadding_WidgetFlag iBit64(56) /* padded using safe area insets */ |
113 | #define moveToParentBottomEdge_WidgetFlag iBit64(57) | 113 | #define moveToParentBottomEdge_WidgetFlag iBit64(57) |
114 | #define parentCannotResizeHeight_WidgetFlag iBit64(58) | 114 | #define parentCannotResizeHeight_WidgetFlag iBit64(58) |
115 | #define ignoreForParentWidth_WidgetFlag iBit64(59) | ||
115 | 116 | ||
116 | enum iWidgetAddPos { | 117 | enum iWidgetAddPos { |
117 | back_WidgetAddPos, | 118 | back_WidgetAddPos, |
@@ -128,6 +129,7 @@ struct Impl_Widget { | |||
128 | iString id; | 129 | iString id; |
129 | int64_t flags; | 130 | int64_t flags; |
130 | iRect rect; | 131 | iRect rect; |
132 | iInt2 minSize; | ||
131 | int padding[4]; /* left, top, right, bottom */ | 133 | int padding[4]; /* left, top, right, bottom */ |
132 | iAnim visualOffset; | 134 | iAnim visualOffset; |
133 | int bgColor; | 135 | int bgColor; |
@@ -220,7 +222,8 @@ iBool hasParent_Widget (const iWidget *d, const iWidget *someParent | |||
220 | void setId_Widget (iWidget *, const char *id); | 222 | void setId_Widget (iWidget *, const char *id); |
221 | void setFlags_Widget (iWidget *, int64_t flags, iBool set); | 223 | void setFlags_Widget (iWidget *, int64_t flags, iBool set); |
222 | void setPos_Widget (iWidget *, iInt2 pos); | 224 | void setPos_Widget (iWidget *, iInt2 pos); |
223 | void setSize_Widget (iWidget *, iInt2 size); | 225 | void setFixedSize_Widget (iWidget *, iInt2 fixedSize); |
226 | void setMinSize_Widget (iWidget *, iInt2 minSize); | ||
224 | void setPadding_Widget (iWidget *, int left, int top, int right, int bottom); | 227 | void setPadding_Widget (iWidget *, int left, int top, int right, int bottom); |
225 | iLocalDef void setPadding1_Widget (iWidget *d, int padding) { setPadding_Widget(d, padding, padding, padding, padding); } | 228 | iLocalDef void setPadding1_Widget (iWidget *d, int padding) { setPadding_Widget(d, padding, padding, padding, padding); } |
226 | void setVisualOffset_Widget (iWidget *, int value, uint32_t span, int animFlags); | 229 | void setVisualOffset_Widget (iWidget *, int value, uint32_t span, int animFlags); |
@@ -237,6 +240,7 @@ iAny * removeChild_Widget (iWidget *, iAnyObject *child); /* returns a | |||
237 | iAny * child_Widget (iWidget *, size_t index); /* O(n) */ | 240 | iAny * child_Widget (iWidget *, size_t index); /* O(n) */ |
238 | size_t childIndex_Widget (const iWidget *, const iAnyObject *child); /* O(n) */ | 241 | size_t childIndex_Widget (const iWidget *, const iAnyObject *child); /* O(n) */ |
239 | void arrange_Widget (iWidget *); | 242 | void arrange_Widget (iWidget *); |
243 | void resetSize_Widget (iWidget *); | ||
240 | iBool dispatchEvent_Widget (iWidget *, const SDL_Event *); | 244 | iBool dispatchEvent_Widget (iWidget *, const SDL_Event *); |
241 | iBool processEvent_Widget (iWidget *, const SDL_Event *); | 245 | iBool processEvent_Widget (iWidget *, const SDL_Event *); |
242 | void postCommand_Widget (const iAnyObject *, const char *cmd, ...); | 246 | void postCommand_Widget (const iAnyObject *, const char *cmd, ...); |
diff --git a/src/ui/window.c b/src/ui/window.c index a3675ae5..1b6c5e89 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -875,10 +875,10 @@ static void updateMetrics_Window_(iWindow *d) { | |||
875 | iWidget *appMax = findChild_Widget(winBar, "winbar.max"); | 875 | iWidget *appMax = findChild_Widget(winBar, "winbar.max"); |
876 | iWidget *appClose = findChild_Widget(winBar, "winbar.close"); | 876 | iWidget *appClose = findChild_Widget(winBar, "winbar.close"); |
877 | setPadding_Widget(winBar, 0, gap_UI / 3, 0, 0); | 877 | setPadding_Widget(winBar, 0, gap_UI / 3, 0, 0); |
878 | setSize_Widget(appMin, init_I2(gap_UI * 11.5f, height_Widget(appTitle))); | 878 | setFixedSize_Widget(appMin, init_I2(gap_UI * 11.5f, height_Widget(appTitle))); |
879 | setSize_Widget(appMax, appMin->rect.size); | 879 | setFixedSize_Widget(appMax, appMin->rect.size); |
880 | setSize_Widget(appClose, appMin->rect.size); | 880 | setFixedSize_Widget(appClose, appMin->rect.size); |
881 | setSize_Widget(appIcon, init_I2(appIconSize_(), appMin->rect.size.y)); | 881 | setFixedSize_Widget(appIcon, init_I2(appIconSize_(), appMin->rect.size.y)); |
882 | } | 882 | } |
883 | iWidget *navBar = findChild_Widget(d->root, "navbar"); | 883 | iWidget *navBar = findChild_Widget(d->root, "navbar"); |
884 | iWidget *lock = findChild_Widget(navBar, "navbar.lock"); | 884 | iWidget *lock = findChild_Widget(navBar, "navbar.lock"); |
@@ -888,7 +888,7 @@ static void updateMetrics_Window_(iWindow *d) { | |||
888 | setPadding_Widget(as_Widget(url), 0, gap_UI, 0, gap_UI); | 888 | setPadding_Widget(as_Widget(url), 0, gap_UI, 0, gap_UI); |
889 | navBar->rect.size.y = 0; /* recalculate height based on children (FIXME: shouldn't be needed) */ | 889 | navBar->rect.size.y = 0; /* recalculate height based on children (FIXME: shouldn't be needed) */ |
890 | updateSize_LabelWidget((iLabelWidget *) lock); | 890 | updateSize_LabelWidget((iLabelWidget *) lock); |
891 | setSize_Widget(embedPad, init_I2(width_Widget(lock) + gap_UI / 2, 1)); | 891 | setFixedSize_Widget(embedPad, init_I2(width_Widget(lock) + gap_UI / 2, 1)); |
892 | setContentPadding_InputWidget((iInputWidget *) url, width_Widget(lock) * 0.75, | 892 | setContentPadding_InputWidget((iInputWidget *) url, width_Widget(lock) * 0.75, |
893 | width_Widget(lock) * 0.75); | 893 | width_Widget(lock) * 0.75); |
894 | rightEmbed->rect.pos.y = gap_UI; | 894 | rightEmbed->rect.pos.y = gap_UI; |
@@ -1251,6 +1251,7 @@ static void updateRootSize_Window_(iWindow *d, iBool notifyAlways) { | |||
1251 | const iInt2 oldSize = *size; | 1251 | const iInt2 oldSize = *size; |
1252 | SDL_GetRendererOutputSize(d->render, &size->x, &size->y); | 1252 | SDL_GetRendererOutputSize(d->render, &size->x, &size->y); |
1253 | size->y -= d->keyboardHeight; | 1253 | size->y -= d->keyboardHeight; |
1254 | d->root->minSize = *size; | ||
1254 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { | 1255 | if (notifyAlways || !isEqual_I2(oldSize, *size)) { |
1255 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); | 1256 | const iBool isHoriz = (d->place.lastNotifiedSize.x != size->x); |
1256 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); | 1257 | const iBool isVert = (d->place.lastNotifiedSize.y != size->y); |
@@ -1465,7 +1466,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
1465 | setupWindow_iOS(d); | 1466 | setupWindow_iOS(d); |
1466 | #endif | 1467 | #endif |
1467 | d->root = new_Widget(); | 1468 | d->root = new_Widget(); |
1468 | setFlags_Widget(d->root, focusRoot_WidgetFlag, iTrue); | 1469 | setFlags_Widget(d->root, fixedSize_WidgetFlag | focusRoot_WidgetFlag, iTrue); |
1469 | d->presentTime = 0.0; | 1470 | d->presentTime = 0.0; |
1470 | d->frameTime = SDL_GetTicks(); | 1471 | d->frameTime = SDL_GetTicks(); |
1471 | d->loadAnimTimer = 0; | 1472 | d->loadAnimTimer = 0; |
@@ -1840,7 +1841,9 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) { | |||
1840 | insertMacMenus_(); | 1841 | insertMacMenus_(); |
1841 | #endif | 1842 | #endif |
1842 | invalidate_Window_(d); | 1843 | invalidate_Window_(d); |
1844 | updatePreferencesLayout_Widget(findChild_Widget(d->root, "prefs")); | ||
1843 | arrange_Widget(d->root); | 1845 | arrange_Widget(d->root); |
1846 | printTree_Widget(findChild_Widget(d->root, "prefs")); | ||
1844 | } | 1847 | } |
1845 | if (oldHover != hover_Widget()) { | 1848 | if (oldHover != hover_Widget()) { |
1846 | postRefresh_App(); | 1849 | postRefresh_App(); |