diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ui/lookupwidget.c | 5 | ||||
-rw-r--r-- | src/ui/root.c | 130 | ||||
-rw-r--r-- | src/ui/util.c | 4 | ||||
-rw-r--r-- | src/ui/widget.c | 161 | ||||
-rw-r--r-- | src/ui/widget.h | 4 | ||||
-rw-r--r-- | src/ui/window.c | 5 |
6 files changed, 182 insertions, 127 deletions
diff --git a/src/ui/lookupwidget.c b/src/ui/lookupwidget.c index 7a0fe237..b06523f9 100644 --- a/src/ui/lookupwidget.c +++ b/src/ui/lookupwidget.c | |||
@@ -655,11 +655,10 @@ static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { | |||
655 | equal_Rangecc(range_Command(cmd, "id"), "navbar"))) { | 655 | equal_Rangecc(range_Command(cmd, "id"), "navbar"))) { |
656 | /* Position the lookup popup under the URL bar. */ { | 656 | /* Position the lookup popup under the URL bar. */ { |
657 | iRoot *root = w->root; | 657 | iRoot *root = w->root; |
658 | const iInt2 rootSize = size_Root(root); | ||
659 | const iRect navBarBounds = bounds_Widget(findChild_Widget(root->widget, "navbar")); | 658 | const iRect navBarBounds = bounds_Widget(findChild_Widget(root->widget, "navbar")); |
660 | iWidget *url = findChild_Widget(root->widget, "url"); | 659 | iWidget *url = findChild_Widget(root->widget, "url"); |
661 | setFixedSize_Widget(w, init_I2(width_Widget(url), | 660 | setFixedSize_Widget(w, init_I2(width_Widget(url), |
662 | (rootSize.y - bottom_Rect(navBarBounds)) / 2)); | 661 | (bottom_Rect(rect_Root(root)) - bottom_Rect(navBarBounds)) / 2)); |
663 | setPos_Widget(w, windowToLocal_Widget(w, bottomLeft_Rect(bounds_Widget(url)))); | 662 | setPos_Widget(w, windowToLocal_Widget(w, bottomLeft_Rect(bounds_Widget(url)))); |
664 | #if defined (iPlatformAppleMobile) | 663 | #if defined (iPlatformAppleMobile) |
665 | /* Adjust height based on keyboard size. */ { | 664 | /* Adjust height based on keyboard size. */ { |
@@ -667,7 +666,7 @@ static iBool processEvent_LookupWidget_(iLookupWidget *d, const SDL_Event *ev) { | |||
667 | if (deviceType_App() == phone_AppDeviceType) { | 666 | if (deviceType_App() == phone_AppDeviceType) { |
668 | float l, r; | 667 | float l, r; |
669 | safeAreaInsets_iOS(&l, NULL, &r, NULL); | 668 | safeAreaInsets_iOS(&l, NULL, &r, NULL); |
670 | w->rect.size.x = rootSize.x - l - r; | 669 | w->rect.size.x = size_Root(root).x - l - r; |
671 | w->rect.pos.x = l; | 670 | w->rect.pos.x = l; |
672 | /* TODO: Need to use windowToLocal_Widget? */ | 671 | /* TODO: Need to use windowToLocal_Widget? */ |
673 | } | 672 | } |
diff --git a/src/ui/root.c b/src/ui/root.c index a97c8d49..287b641e 100644 --- a/src/ui/root.c +++ b/src/ui/root.c | |||
@@ -541,59 +541,63 @@ iBool isNarrow_Root(const iRoot *d) { | |||
541 | return width_Rect(safeRect_Root(d)) / gap_UI < 140; | 541 | return width_Rect(safeRect_Root(d)) / gap_UI < 140; |
542 | } | 542 | } |
543 | 543 | ||
544 | static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { | 544 | static void updateNavBarSize_(iWidget *navBar) { |
545 | if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "metrics.changed")) { | 545 | const iBool isPhone = deviceType_App() == phone_AppDeviceType; |
546 | const iBool isPhone = deviceType_App() == phone_AppDeviceType; | 546 | const iBool isNarrow = !isPhone && isNarrow_Root(navBar->root); |
547 | const iBool isNarrow = !isPhone && isNarrow_Root(navBar->root); | 547 | /* Adjust navbar padding. */ { |
548 | /* Adjust navbar padding. */ { | 548 | int hPad = isPhone && isPortrait_App() ? 0 : (isPhone || isNarrow) ? gap_UI / 2 |
549 | int hPad = isPhone && isPortrait_App() ? 0 : (isPhone || isNarrow) ? gap_UI / 2 | 549 | : gap_UI * 3 / 2; |
550 | : gap_UI * 3 / 2; | 550 | int vPad = gap_UI * 3 / 2; |
551 | int vPad = gap_UI * 3 / 2; | 551 | int topPad = !findWidget_Root("winbar") ? gap_UI / 2 : 0; |
552 | int topPad = !findWidget_App("winbar") ? gap_UI / 2 : 0; | 552 | setPadding_Widget(navBar, hPad, vPad / 3 + topPad, hPad, vPad / 2); |
553 | setPadding_Widget(navBar, hPad, vPad / 3 + topPad, hPad, vPad / 2); | 553 | } |
554 | } | 554 | /* Button sizing. */ |
555 | /* Button sizing. */ | 555 | if (isNarrow ^ ((flags_Widget(navBar) & tight_WidgetFlag) != 0)) { |
556 | if (isNarrow ^ ((flags_Widget(navBar) & tight_WidgetFlag) != 0)) { | 556 | setFlags_Widget(navBar, tight_WidgetFlag, isNarrow); |
557 | setFlags_Widget(navBar, tight_WidgetFlag, isNarrow); | 557 | iForEach(ObjectList, i, navBar->children) { |
558 | iForEach(ObjectList, i, navBar->children) { | 558 | iWidget *child = as_Widget(i.object); |
559 | iWidget *child = as_Widget(i.object); | 559 | setFlags_Widget(child, tight_WidgetFlag, isNarrow); |
560 | setFlags_Widget(child, tight_WidgetFlag, isNarrow); | 560 | if (isInstance_Object(i.object, &Class_LabelWidget)) { |
561 | if (isInstance_Object(i.object, &Class_LabelWidget)) { | 561 | iLabelWidget *label = i.object; |
562 | iLabelWidget *label = i.object; | 562 | updateSize_LabelWidget(label); |
563 | updateSize_LabelWidget(label); | ||
564 | } | ||
565 | } | 563 | } |
566 | /* Note that InputWidget uses the `tight` flag to adjust its inner padding. */ | ||
567 | /* TODO: Is this redundant? See `updateMetrics_Window_()`. */ | ||
568 | const int embedButtonWidth = width_Widget(findChild_Widget(navBar, "navbar.lock")); | ||
569 | setContentPadding_InputWidget(findChild_Widget(navBar, "url"), | ||
570 | embedButtonWidth * 0.75f, | ||
571 | embedButtonWidth * 0.75f); | ||
572 | } | 564 | } |
573 | if (isPhone) { | 565 | /* Note that InputWidget uses the `tight` flag to adjust its inner padding. */ |
574 | static const char *buttons[] = { "navbar.back", "navbar.forward", "navbar.sidebar", | 566 | /* TODO: Is this redundant? See `updateMetrics_Window_()`. */ |
575 | "navbar.ident", "navbar.home", "navbar.menu" }; | 567 | const int embedButtonWidth = width_Widget(findChild_Widget(navBar, "navbar.lock")); |
576 | iWidget *toolBar = findWidget_App("toolbar"); | 568 | setContentPadding_InputWidget(findChild_Widget(navBar, "url"), |
577 | setVisualOffset_Widget(toolBar, 0, 0, 0); | 569 | embedButtonWidth * 0.75f, |
578 | setFlags_Widget(toolBar, hidden_WidgetFlag, isLandscape_App()); | 570 | embedButtonWidth * 0.75f); |
579 | iForIndices(i, buttons) { | 571 | } |
580 | iLabelWidget *btn = findChild_Widget(navBar, buttons[i]); | 572 | if (isPhone) { |
581 | setFlags_Widget(as_Widget(btn), hidden_WidgetFlag, isPortrait_App()); | 573 | static const char *buttons[] = { "navbar.back", "navbar.forward", "navbar.sidebar", |
582 | if (isLandscape_App()) { | 574 | "navbar.ident", "navbar.home", "navbar.menu" }; |
583 | /* Collapsing sets size to zero and the label doesn't know when to update | 575 | iWidget *toolBar = findWidget_App("toolbar"); |
584 | its own size automatically. */ | 576 | setVisualOffset_Widget(toolBar, 0, 0, 0); |
585 | updateSize_LabelWidget(btn); | 577 | setFlags_Widget(toolBar, hidden_WidgetFlag, isLandscape_App()); |
586 | } | 578 | iForIndices(i, buttons) { |
579 | iLabelWidget *btn = findChild_Widget(navBar, buttons[i]); | ||
580 | setFlags_Widget(as_Widget(btn), hidden_WidgetFlag, isPortrait_App()); | ||
581 | if (isLandscape_App()) { | ||
582 | /* Collapsing sets size to zero and the label doesn't know when to update | ||
583 | its own size automatically. */ | ||
584 | updateSize_LabelWidget(btn); | ||
587 | } | 585 | } |
588 | arrange_Widget(navBar->root->widget); | ||
589 | } | 586 | } |
590 | /* Resize the URL input field. */ { | 587 | arrange_Widget(navBar->root->widget); |
591 | iWidget *urlBar = findChild_Widget(navBar, "url"); | 588 | } |
592 | urlBar->rect.size.x = iMini(navBarAvailableSpace_(navBar), 167 * gap_UI); | 589 | /* Resize the URL input field. */ { |
593 | arrange_Widget(navBar); | 590 | iWidget *urlBar = findChild_Widget(navBar, "url"); |
594 | } | 591 | urlBar->rect.size.x = iMini(navBarAvailableSpace_(navBar), 167 * gap_UI); |
595 | refresh_Widget(navBar); | 592 | arrange_Widget(navBar); |
596 | postCommand_Widget(navBar, "layout.changed id:navbar"); | 593 | } |
594 | refresh_Widget(navBar); | ||
595 | postCommand_Widget(navBar, "layout.changed id:navbar"); | ||
596 | } | ||
597 | |||
598 | static iBool handleNavBarCommands_(iWidget *navBar, const char *cmd) { | ||
599 | if (equal_Command(cmd, "window.resized") || equal_Command(cmd, "metrics.changed")) { | ||
600 | updateNavBarSize_(navBar); | ||
597 | return iFalse; | 601 | return iFalse; |
598 | } | 602 | } |
599 | else if (equal_Command(cmd, "window.reload.update")) { | 603 | else if (equal_Command(cmd, "window.reload.update")) { |
@@ -740,16 +744,18 @@ static iBool handleSearchBarCommands_(iWidget *searchBar, const char *cmd) { | |||
740 | else if (equal_Command(cmd, "focus.gained")) { | 744 | else if (equal_Command(cmd, "focus.gained")) { |
741 | if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { | 745 | if (pointer_Command(cmd) == findChild_Widget(searchBar, "find.input")) { |
742 | if (!isVisible_Widget(searchBar)) { | 746 | if (!isVisible_Widget(searchBar)) { |
743 | setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); | 747 | // setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iFalse); |
744 | arrange_Widget(root_Widget(searchBar)); | 748 | // arrange_Widget(root_Widget(searchBar)); |
745 | postRefresh_App(); | 749 | // postRefresh_App(); |
750 | showCollapsed_Widget(searchBar, iTrue); | ||
746 | } | 751 | } |
747 | } | 752 | } |
748 | } | 753 | } |
749 | else if (equal_Command(cmd, "find.close")) { | 754 | else if (equal_Command(cmd, "find.close")) { |
750 | if (isVisible_Widget(searchBar)) { | 755 | if (isVisible_Widget(searchBar)) { |
751 | setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iTrue); | 756 | //setFlags_Widget(searchBar, hidden_WidgetFlag | disabled_WidgetFlag, iTrue); |
752 | arrange_Widget(searchBar->parent); | 757 | //arrange_Widget(searchBar->parent); |
758 | showCollapsed_Widget(searchBar, iFalse); | ||
753 | if (isFocused_Widget(findChild_Widget(searchBar, "find.input"))) { | 759 | if (isFocused_Widget(findChild_Widget(searchBar, "find.input"))) { |
754 | setFocus_Widget(NULL); | 760 | setFocus_Widget(NULL); |
755 | } | 761 | } |
@@ -886,6 +892,7 @@ void updateMetrics_Root(iRoot *d) { | |||
886 | 892 | ||
887 | void createUserInterface_Root(iRoot *d) { | 893 | void createUserInterface_Root(iRoot *d) { |
888 | iWidget *root = d->widget = new_Widget(); | 894 | iWidget *root = d->widget = new_Widget(); |
895 | root->rect.size = get_Window()->size; | ||
889 | iAssert(root->root == d); | 896 | iAssert(root->root == d); |
890 | setId_Widget(root, "root"); | 897 | setId_Widget(root, "root"); |
891 | /* Children of root cover the entire window. */ | 898 | /* Children of root cover the entire window. */ |
@@ -944,13 +951,14 @@ void createUserInterface_Root(iRoot *d) { | |||
944 | setBackgroundColor_Widget(winBar, uiBackground_ColorId); | 951 | setBackgroundColor_Widget(winBar, uiBackground_ColorId); |
945 | } | 952 | } |
946 | #endif | 953 | #endif |
954 | iWidget *navBar; | ||
947 | /* Navigation bar. */ { | 955 | /* Navigation bar. */ { |
948 | iWidget *navBar = new_Widget(); | 956 | navBar = new_Widget(); |
949 | setId_Widget(navBar, "navbar"); | 957 | setId_Widget(navBar, "navbar"); |
950 | setFlags_Widget(navBar, | 958 | setFlags_Widget(navBar, |
951 | hittable_WidgetFlag | /* context menu */ | 959 | hittable_WidgetFlag | /* context menu */ |
952 | arrangeHeight_WidgetFlag | | 960 | arrangeHeight_WidgetFlag | |
953 | resizeChildren_WidgetFlag | | 961 | resizeWidthOfChildren_WidgetFlag | |
954 | arrangeHorizontal_WidgetFlag | | 962 | arrangeHorizontal_WidgetFlag | |
955 | drawBackgroundToHorizontalSafeArea_WidgetFlag | | 963 | drawBackgroundToHorizontalSafeArea_WidgetFlag | |
956 | drawBackgroundToVerticalSafeArea_WidgetFlag, | 964 | drawBackgroundToVerticalSafeArea_WidgetFlag, |
@@ -958,7 +966,8 @@ void createUserInterface_Root(iRoot *d) { | |||
958 | addChild_Widget(div, iClob(navBar)); | 966 | addChild_Widget(div, iClob(navBar)); |
959 | setBackgroundColor_Widget(navBar, uiBackground_ColorId); | 967 | setBackgroundColor_Widget(navBar, uiBackground_ColorId); |
960 | setCommandHandler_Widget(navBar, handleNavBarCommands_); | 968 | setCommandHandler_Widget(navBar, handleNavBarCommands_); |
961 | setId_Widget(addChildFlags_Widget(navBar, iClob(newIcon_LabelWidget(backArrow_Icon, 0, 0, "navigate.back")), collapse_WidgetFlag), "navbar.back"); | 969 | iWidget *navBack; |
970 | setId_Widget(navBack = addChildFlags_Widget(navBar, iClob(newIcon_LabelWidget(backArrow_Icon, 0, 0, "navigate.back")), collapse_WidgetFlag), "navbar.back"); | ||
962 | setId_Widget(addChildFlags_Widget(navBar, iClob(newIcon_LabelWidget(forwardArrow_Icon, 0, 0, "navigate.forward")), collapse_WidgetFlag), "navbar.forward"); | 971 | setId_Widget(addChildFlags_Widget(navBar, iClob(newIcon_LabelWidget(forwardArrow_Icon, 0, 0, "navigate.forward")), collapse_WidgetFlag), "navbar.forward"); |
963 | /* Mobile devices have a button for easier access to the left sidebar. */ | 972 | /* Mobile devices have a button for easier access to the left sidebar. */ |
964 | if (deviceType_App() != desktop_AppDeviceType) { | 973 | if (deviceType_App() != desktop_AppDeviceType) { |
@@ -999,7 +1008,7 @@ void createUserInterface_Root(iRoot *d) { | |||
999 | setId_Widget(rightEmbed, "url.rightembed"); | 1008 | setId_Widget(rightEmbed, "url.rightembed"); |
1000 | addChildFlags_Widget(as_Widget(url), | 1009 | addChildFlags_Widget(as_Widget(url), |
1001 | iClob(rightEmbed), | 1010 | iClob(rightEmbed), |
1002 | arrangeHorizontal_WidgetFlag | arrangeSize_WidgetFlag | | 1011 | arrangeHorizontal_WidgetFlag | arrangeWidth_WidgetFlag | |
1003 | resizeHeightOfChildren_WidgetFlag | | 1012 | resizeHeightOfChildren_WidgetFlag | |
1004 | moveToParentRightEdge_WidgetFlag); | 1013 | moveToParentRightEdge_WidgetFlag); |
1005 | /* Feeds refresh indicator is inside the input field. */ { | 1014 | /* Feeds refresh indicator is inside the input field. */ { |
@@ -1132,8 +1141,8 @@ void createUserInterface_Root(iRoot *d) { | |||
1132 | iWidget *searchBar = new_Widget(); | 1141 | iWidget *searchBar = new_Widget(); |
1133 | setId_Widget(searchBar, "search"); | 1142 | setId_Widget(searchBar, "search"); |
1134 | setFlags_Widget(searchBar, | 1143 | setFlags_Widget(searchBar, |
1135 | hidden_WidgetFlag | disabled_WidgetFlag | collapse_WidgetFlag | | 1144 | hidden_WidgetFlag | disabledWhenHidden_WidgetFlag | collapse_WidgetFlag | |
1136 | arrangeHeight_WidgetFlag | resizeChildren_WidgetFlag | | 1145 | arrangeHeight_WidgetFlag | resizeWidthOfChildren_WidgetFlag | |
1137 | arrangeHorizontal_WidgetFlag, | 1146 | arrangeHorizontal_WidgetFlag, |
1138 | iTrue); | 1147 | iTrue); |
1139 | if (deviceType_App() == desktop_AppDeviceType) { | 1148 | if (deviceType_App() == desktop_AppDeviceType) { |
@@ -1270,6 +1279,7 @@ void createUserInterface_Root(iRoot *d) { | |||
1270 | addAction_Widget(root, SDLK_j, KMOD_PRIMARY, "splitmenu.open"); | 1279 | addAction_Widget(root, SDLK_j, KMOD_PRIMARY, "splitmenu.open"); |
1271 | } | 1280 | } |
1272 | updateMetrics_Root(d); | 1281 | updateMetrics_Root(d); |
1282 | updateNavBarSize_(navBar); | ||
1273 | } | 1283 | } |
1274 | 1284 | ||
1275 | void showToolbars_Root(iRoot *d, iBool show) { | 1285 | void showToolbars_Root(iRoot *d, iBool show) { |
diff --git a/src/ui/util.c b/src/ui/util.c index 0a0c37a9..7bc611e0 100644 --- a/src/ui/util.c +++ b/src/ui/util.c | |||
@@ -2061,8 +2061,8 @@ static iWidget *appendTwoColumnPage_(iWidget *tabs, const char *title, int short | |||
2061 | iWidget **values) { | 2061 | iWidget **values) { |
2062 | /* TODO: Use `makeTwoColumnWidget_()`, see above. */ | 2062 | /* TODO: Use `makeTwoColumnWidget_()`, see above. */ |
2063 | iWidget *page = new_Widget(); | 2063 | iWidget *page = new_Widget(); |
2064 | setFlags_Widget(page, arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag | | 2064 | setBackgroundColor_Widget(page, red_ColorId); |
2065 | resizeHeightOfChildren_WidgetFlag, iTrue); | 2065 | setFlags_Widget(page, arrangeVertical_WidgetFlag | arrangeSize_WidgetFlag, iTrue); |
2066 | addChildFlags_Widget(page, iClob(new_Widget()), expand_WidgetFlag); | 2066 | addChildFlags_Widget(page, iClob(new_Widget()), expand_WidgetFlag); |
2067 | setPadding_Widget(page, 0, gap_UI, 0, gap_UI); | 2067 | setPadding_Widget(page, 0, gap_UI, 0, gap_UI); |
2068 | iWidget *columns = new_Widget(); | 2068 | iWidget *columns = new_Widget(); |
diff --git a/src/ui/widget.c b/src/ui/widget.c index e4d92b35..62112e86 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -232,11 +232,29 @@ void setRoot_Widget(iWidget *d, iRoot *root) { | |||
232 | } | 232 | } |
233 | } | 233 | } |
234 | 234 | ||
235 | iLocalDef iBool isCollapsed_Widget_(const iWidget *d) { | ||
236 | return (d->flags & (hidden_WidgetFlag | collapse_WidgetFlag)) == | ||
237 | (hidden_WidgetFlag | collapse_WidgetFlag); | ||
238 | } | ||
239 | |||
240 | iLocalDef iBool isArrangedPos_Widget_(const iWidget *d) { | ||
241 | return (d->flags & fixedPosition_WidgetFlag) == 0; | ||
242 | } | ||
243 | |||
244 | iLocalDef iBool isArrangedSize_Widget_(const iWidget *d) { | ||
245 | return !isCollapsed_Widget_(d) && isArrangedPos_Widget_(d) && | ||
246 | !(d->flags & parentCannotResize_WidgetFlag); | ||
247 | } | ||
248 | |||
249 | iLocalDef iBool doesAffectSizing_Widget_(const iWidget *d) { | ||
250 | return !isCollapsed_Widget_(d) && isArrangedPos_Widget_(d); | ||
251 | } | ||
252 | |||
235 | static int numExpandingChildren_Widget_(const iWidget *d) { | 253 | static int numExpandingChildren_Widget_(const iWidget *d) { |
236 | int count = 0; | 254 | int count = 0; |
237 | iConstForEach(ObjectList, i, d->children) { | 255 | iConstForEach(ObjectList, i, d->children) { |
238 | const iWidget *child = constAs_Widget(i.object); | 256 | const iWidget *child = constAs_Widget(i.object); |
239 | if (flags_Widget(child) & expand_WidgetFlag) { | 257 | if (flags_Widget(child) & expand_WidgetFlag && doesAffectSizing_Widget_(child)) { |
240 | count++; | 258 | count++; |
241 | } | 259 | } |
242 | } | 260 | } |
@@ -253,7 +271,7 @@ static int widestChild_Widget_(const iWidget *d) { | |||
253 | } | 271 | } |
254 | 272 | ||
255 | static void arrange_Widget_(iWidget *); | 273 | static void arrange_Widget_(iWidget *); |
256 | static const iBool tracing_ = iFalse; | 274 | static const iBool tracing_ = 0; |
257 | 275 | ||
258 | #define TRACE(d, ...) if (tracing_) { printf_Widget_(d, __VA_ARGS__); } | 276 | #define TRACE(d, ...) if (tracing_) { printf_Widget_(d, __VA_ARGS__); } |
259 | 277 | ||
@@ -288,7 +306,7 @@ static void setWidth_Widget_(iWidget *d, int width) { | |||
288 | iAssert(width >= 0); | 306 | iAssert(width >= 0); |
289 | TRACE(d, "attempt to set width to %d (current: %d, min width: %d)", width, d->rect.size.x, d->minSize.x); | 307 | TRACE(d, "attempt to set width to %d (current: %d, min width: %d)", width, d->rect.size.x, d->minSize.x); |
290 | width = iMax(width, d->minSize.x); | 308 | width = iMax(width, d->minSize.x); |
291 | if (~d->flags & fixedWidth_WidgetFlag || d->flags & collapse_WidgetFlag) { | 309 | if (~d->flags & fixedWidth_WidgetFlag) { //} || d->flags & collapse_WidgetFlag) { |
292 | if (d->rect.size.x != width) { | 310 | if (d->rect.size.x != width) { |
293 | d->rect.size.x = width; | 311 | d->rect.size.x = width; |
294 | TRACE(d, "width has changed to %d", width); | 312 | TRACE(d, "width has changed to %d", width); |
@@ -313,7 +331,7 @@ static void setHeight_Widget_(iWidget *d, int height) { | |||
313 | iAssert(height >= 0); | 331 | iAssert(height >= 0); |
314 | TRACE(d, "attempt to set height to %d (current: %d, min height: %d)", height, d->rect.size.y, d->minSize.y); | 332 | TRACE(d, "attempt to set height to %d (current: %d, min height: %d)", height, d->rect.size.y, d->minSize.y); |
315 | height = iMax(height, d->minSize.y); | 333 | height = iMax(height, d->minSize.y); |
316 | if (~d->flags & fixedHeight_WidgetFlag || d->flags & collapse_WidgetFlag) { | 334 | if (~d->flags & fixedHeight_WidgetFlag) { //} || d->flags & collapse_WidgetFlag) { |
317 | if (d->rect.size.y != height) { | 335 | if (d->rect.size.y != height) { |
318 | d->rect.size.y = height; | 336 | d->rect.size.y = height; |
319 | TRACE(d, "height has changed to %d", height); | 337 | TRACE(d, "height has changed to %d", height); |
@@ -327,11 +345,6 @@ static void setHeight_Widget_(iWidget *d, int height) { | |||
327 | } | 345 | } |
328 | } | 346 | } |
329 | 347 | ||
330 | iLocalDef iBool isCollapsed_Widget_(const iWidget *d) { | ||
331 | return (d->flags & (hidden_WidgetFlag | collapse_WidgetFlag)) == | ||
332 | (hidden_WidgetFlag | collapse_WidgetFlag); | ||
333 | } | ||
334 | |||
335 | iLocalDef iRect innerRect_Widget_(const iWidget *d) { | 348 | iLocalDef iRect innerRect_Widget_(const iWidget *d) { |
336 | return init_Rect(d->padding[0], | 349 | return init_Rect(d->padding[0], |
337 | d->padding[1], | 350 | d->padding[1], |
@@ -347,14 +360,15 @@ iRect innerBounds_Widget(const iWidget *d) { | |||
347 | return ib; | 360 | return ib; |
348 | } | 361 | } |
349 | 362 | ||
350 | iLocalDef iBool isArranged_Widget_(const iWidget *d) { | 363 | //iLocalDef iBool isArranged_Widget_(const iWidget *d) { |
351 | return !isCollapsed_Widget_(d) && ~d->flags & fixedPosition_WidgetFlag; | 364 | // return !isCollapsed_Widget_(d) && ~d->flags & fixedPosition_WidgetFlag; |
352 | } | 365 | //} |
366 | |||
353 | 367 | ||
354 | static size_t numArrangedChildren_Widget_(const iWidget *d) { | 368 | static size_t numArrangedChildren_Widget_(const iWidget *d) { |
355 | size_t count = 0; | 369 | size_t count = 0; |
356 | iConstForEach(ObjectList, i, d->children) { | 370 | iConstForEach(ObjectList, i, d->children) { |
357 | if (isArranged_Widget_(i.object)) { | 371 | if (isArrangedPos_Widget_(i.object)) { |
358 | count++; | 372 | count++; |
359 | } | 373 | } |
360 | } | 374 | } |
@@ -387,15 +401,20 @@ static void boundsOfChildren_Widget_(const iWidget *d, iRect *bounds_out) { | |||
387 | *bounds_out = union_Rect(*bounds_out, childRect); | 401 | *bounds_out = union_Rect(*bounds_out, childRect); |
388 | } | 402 | } |
389 | } | 403 | } |
404 | #if !defined (NDEBUG) | ||
405 | if (tracing_) { | ||
406 | if (bounds_out->size.x && bounds_out->size.y == 0) { | ||
407 | printf("SUSPECT CHILD BOUNDS?\n"); | ||
408 | puts ("---------------------"); | ||
409 | printTree_Widget(d); | ||
410 | puts ("---------------------"); | ||
411 | } | ||
412 | } | ||
413 | #endif | ||
390 | } | 414 | } |
391 | 415 | ||
392 | static void arrange_Widget_(iWidget *d) { | 416 | static void arrange_Widget_(iWidget *d) { |
393 | TRACE(d, "arranging..."); | 417 | TRACE(d, "arranging..."); |
394 | if (isCollapsed_Widget_(d)) { | ||
395 | TRACE(d, "collapsed => END"); | ||
396 | setFlags_Widget(d, wasCollapsed_WidgetFlag, iTrue); | ||
397 | return; | ||
398 | } | ||
399 | if (d->flags & moveToParentLeftEdge_WidgetFlag) { | 418 | if (d->flags & moveToParentLeftEdge_WidgetFlag) { |
400 | d->rect.pos.x = d->padding[0]; /* FIXME: Shouldn't this be d->parent->padding[0]? */ | 419 | d->rect.pos.x = d->padding[0]; /* FIXME: Shouldn't this be d->parent->padding[0]? */ |
401 | TRACE(d, "move to parent left edge: %d", d->rect.pos.x); | 420 | TRACE(d, "move to parent left edge: %d", d->rect.pos.x); |
@@ -439,57 +458,42 @@ static void arrange_Widget_(iWidget *d) { | |||
439 | } | 458 | } |
440 | const size_t childCount = numArrangedChildren_Widget_(d); | 459 | const size_t childCount = numArrangedChildren_Widget_(d); |
441 | TRACE(d, "%d arranged children", childCount); | 460 | TRACE(d, "%d arranged children", childCount); |
461 | const int expCount = numExpandingChildren_Widget_(d); | ||
462 | TRACE(d, "%d expanding children", expCount); | ||
442 | /* Resize children to fill the parent widget. */ | 463 | /* Resize children to fill the parent widget. */ |
443 | if (d->flags & resizeChildren_WidgetFlag) { | 464 | if (d->flags & resizeChildren_WidgetFlag) { |
444 | const iInt2 dirs = init_I2((d->flags & resizeWidthOfChildren_WidgetFlag) != 0, | 465 | const iInt2 dirs = init_I2((d->flags & resizeWidthOfChildren_WidgetFlag) != 0, |
445 | (d->flags & resizeHeightOfChildren_WidgetFlag) != 0); | 466 | (d->flags & resizeHeightOfChildren_WidgetFlag) != 0); |
446 | TRACE(d, "resize children, x:%d y:%d", dirs.x, dirs.y); | 467 | #if !defined (NDEBUG) |
447 | /* Collapse hidden children. */ | 468 | /* Check for conflicting flags. */ |
448 | iBool collapseChanged = iFalse; | 469 | if (dirs.x) iAssert(~d->flags & arrangeWidth_WidgetFlag); |
449 | iForEach(ObjectList, c, d->children) { | 470 | if (dirs.y) iAssert(~d->flags & arrangeHeight_WidgetFlag); |
450 | iWidget *child = as_Widget(c.object); | 471 | #endif |
451 | if (!isCollapsed_Widget_(child) && child->flags & wasCollapsed_WidgetFlag) { | 472 | TRACE(d, "resize children, x:%d y:%d (own size: %dx%d)", dirs.x, dirs.y, |
452 | setFlags_Widget(child, wasCollapsed_WidgetFlag, iFalse); | 473 | d->rect.size.x, d->rect.size.y); |
453 | TRACE(d, "child %p is uncollapsed", child); | ||
454 | /* Undo collapse and determine the normal size again. */ | ||
455 | arrange_Widget_(d); | ||
456 | collapseChanged = iTrue; | ||
457 | } | ||
458 | else if (isCollapsed_Widget_(child) && ~child->flags & wasCollapsed_WidgetFlag) { | ||
459 | setFlags_Widget(child, wasCollapsed_WidgetFlag, iTrue); | ||
460 | collapseChanged = iTrue; | ||
461 | TRACE(d, "child %p flagged as collapsed", child); | ||
462 | } | ||
463 | } | ||
464 | if (collapseChanged) { | ||
465 | TRACE(d, "redoing arrangement due to changes in child collapse state"); | ||
466 | arrange_Widget_(d); /* Redo with the new child sizes. */ | ||
467 | return; | ||
468 | } | ||
469 | const int expCount = numExpandingChildren_Widget_(d); | ||
470 | TRACE(d, "%d expanding children", expCount); | ||
471 | /* Only resize the expanding children, not touching the others. */ | ||
472 | if (expCount > 0) { | 474 | if (expCount > 0) { |
475 | /* There are expanding children, so all non-expanding children will retain their | ||
476 | current size. */ | ||
473 | iInt2 avail = innerRect_Widget_(d).size; | 477 | iInt2 avail = innerRect_Widget_(d).size; |
474 | TRACE(d, "inner size: %dx%d", avail.x, avail.y); | 478 | TRACE(d, "inner size: %dx%d", avail.x, avail.y); |
475 | iConstForEach(ObjectList, i, d->children) { | 479 | iConstForEach(ObjectList, i, d->children) { |
476 | const iWidget *child = constAs_Widget(i.object); | 480 | const iWidget *child = constAs_Widget(i.object); |
477 | if (!isArranged_Widget_(child)) { | 481 | if (doesAffectSizing_Widget_(child)) { |
478 | continue; | 482 | if (~child->flags & expand_WidgetFlag) { |
479 | } | 483 | subv_I2(&avail, child->rect.size); |
480 | if (~child->flags & expand_WidgetFlag) { | 484 | } |
481 | subv_I2(&avail, child->rect.size); | ||
482 | } | 485 | } |
483 | } | 486 | } |
484 | avail = divi_I2(max_I2(zero_I2(), avail), expCount); | 487 | avail = divi_I2(max_I2(zero_I2(), avail), expCount); |
485 | TRACE(d, "changing child sizes (expand mode)..."); | 488 | TRACE(d, "changing child sizes..."); |
486 | iForEach(ObjectList, j, d->children) { | 489 | iForEach(ObjectList, j, d->children) { |
487 | iWidget *child = as_Widget(j.object); | 490 | iWidget *child = as_Widget(j.object); |
488 | if (!isArranged_Widget_(child)) { | 491 | if (!isArrangedSize_Widget_(child)) { |
489 | TRACE(d, "child %p is not arranged", child); | 492 | TRACE(d, "child %p size is not arranged", child); |
490 | continue; | 493 | continue; |
491 | } | 494 | } |
492 | if (child->flags & expand_WidgetFlag) { | 495 | if (~child->flags & expand_WidgetFlag) { |
496 | #if 0 | ||
493 | if (d->flags & arrangeHorizontal_WidgetFlag) { | 497 | if (d->flags & arrangeHorizontal_WidgetFlag) { |
494 | if (dirs.x) setWidth_Widget_(child, avail.x); | 498 | if (dirs.x) setWidth_Widget_(child, avail.x); |
495 | if (dirs.y) setHeight_Widget_(child, height_Rect(innerRect_Widget_(d))); | 499 | if (dirs.y) setHeight_Widget_(child, height_Rect(innerRect_Widget_(d))); |
@@ -500,6 +504,7 @@ static void arrange_Widget_(iWidget *d) { | |||
500 | } | 504 | } |
501 | } | 505 | } |
502 | else { | 506 | else { |
507 | #endif | ||
503 | /* Fill the off axis, though. */ | 508 | /* Fill the off axis, though. */ |
504 | if (d->flags & arrangeHorizontal_WidgetFlag) { | 509 | if (d->flags & arrangeHorizontal_WidgetFlag) { |
505 | if (dirs.y) setHeight_Widget_(child, height_Rect(innerRect_Widget_(d))); | 510 | if (dirs.y) setHeight_Widget_(child, height_Rect(innerRect_Widget_(d))); |
@@ -509,7 +514,7 @@ static void arrange_Widget_(iWidget *d) { | |||
509 | } | 514 | } |
510 | } | 515 | } |
511 | } | 516 | } |
512 | TRACE(d, "...done changing child sizes (expand mode)"); | 517 | TRACE(d, "...done changing child sizes"); |
513 | } | 518 | } |
514 | else { | 519 | else { |
515 | /* Evenly size all children. */ | 520 | /* Evenly size all children. */ |
@@ -526,7 +531,7 @@ static void arrange_Widget_(iWidget *d) { | |||
526 | TRACE(d, "begin changing child sizes (EVEN mode)..."); | 531 | TRACE(d, "begin changing child sizes (EVEN mode)..."); |
527 | iForEach(ObjectList, i, d->children) { | 532 | iForEach(ObjectList, i, d->children) { |
528 | iWidget *child = as_Widget(i.object); | 533 | iWidget *child = as_Widget(i.object); |
529 | if (isArranged_Widget_(child) && ~child->flags & parentCannotResize_WidgetFlag) { | 534 | if (isArrangedSize_Widget_(child)) { |
530 | if (dirs.x) { | 535 | if (dirs.x) { |
531 | setWidth_Widget_(child, child->flags & unpadded_WidgetFlag ? unpaddedChildSize.x : childSize.x); | 536 | setWidth_Widget_(child, child->flags & unpadded_WidgetFlag ? unpaddedChildSize.x : childSize.x); |
532 | } | 537 | } |
@@ -535,19 +540,55 @@ static void arrange_Widget_(iWidget *d) { | |||
535 | } | 540 | } |
536 | } | 541 | } |
537 | else { | 542 | else { |
538 | TRACE(d, "child %p cannot be resized (parentCannotResize: %d)", child, | 543 | TRACE(d, "child %p cannot be resized (collapsed: %d, arrangedPos: %d, parentCannotResize: %d)", child, |
544 | isCollapsed_Widget_(child), | ||
545 | isArrangedPos_Widget_(child), | ||
539 | (child->flags & parentCannotResize_WidgetFlag) != 0); | 546 | (child->flags & parentCannotResize_WidgetFlag) != 0); |
540 | } | 547 | } |
541 | } | 548 | } |
542 | TRACE(d, "...done changing child sizes (EVEN mode)"); | 549 | TRACE(d, "...done changing child sizes (EVEN mode)"); |
543 | } | 550 | } |
544 | } | 551 | } |
552 | /* Resize the expanding children to fill the remaining available space. */ | ||
553 | if (expCount > 0 && (d->flags & (arrangeHorizontal_WidgetFlag | arrangeVertical_WidgetFlag))) { | ||
554 | TRACE(d, "%d expanding children, resizing them %s...", expCount, | ||
555 | d->flags & arrangeHorizontal_WidgetFlag ? "horizontally" : "vertically"); | ||
556 | const iRect innerRect = innerRect_Widget_(d); | ||
557 | iInt2 avail = innerRect.size; | ||
558 | iConstForEach(ObjectList, i, d->children) { | ||
559 | const iWidget *child = constAs_Widget(i.object); | ||
560 | if (doesAffectSizing_Widget_(child)) { | ||
561 | if (~child->flags & expand_WidgetFlag) { | ||
562 | subv_I2(&avail, child->rect.size); | ||
563 | } | ||
564 | } | ||
565 | } | ||
566 | avail = divi_I2(max_I2(zero_I2(), avail), expCount); | ||
567 | TRACE(d, "available for expansion (per child): %d\n", d->flags & arrangeHorizontal_WidgetFlag ? avail.x : avail.y); | ||
568 | iForEach(ObjectList, j, d->children) { | ||
569 | iWidget *child = as_Widget(j.object); | ||
570 | if (!isArrangedSize_Widget_(child)) { | ||
571 | TRACE(d, "child %p size is not arranged", child); | ||
572 | continue; | ||
573 | } | ||
574 | if (child->flags & expand_WidgetFlag) { | ||
575 | if (d->flags & arrangeHorizontal_WidgetFlag) { | ||
576 | setWidth_Widget_(child, avail.x); | ||
577 | setHeight_Widget_(child, height_Rect(innerRect)); | ||
578 | } | ||
579 | else if (d->flags & arrangeVertical_WidgetFlag) { | ||
580 | setWidth_Widget_(child, width_Rect(innerRect)); | ||
581 | setHeight_Widget_(child, avail.y); | ||
582 | } | ||
583 | } | ||
584 | } | ||
585 | } | ||
545 | if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { | 586 | if (d->flags & resizeChildrenToWidestChild_WidgetFlag) { |
546 | const int widest = widestChild_Widget_(d); | 587 | const int widest = widestChild_Widget_(d); |
547 | TRACE(d, "resizing children to widest child (%d)...", widest); | 588 | TRACE(d, "resizing children to widest child (%d)...", widest); |
548 | iForEach(ObjectList, i, d->children) { | 589 | iForEach(ObjectList, i, d->children) { |
549 | iWidget *child = as_Widget(i.object); | 590 | iWidget *child = as_Widget(i.object); |
550 | if (isArranged_Widget_(child) && ~child->flags & parentCannotResize_WidgetFlag) { | 591 | if (isArrangedSize_Widget_(child)) { |
551 | setWidth_Widget_(child, widest); | 592 | setWidth_Widget_(child, widest); |
552 | } | 593 | } |
553 | else { | 594 | else { |
@@ -564,7 +605,7 @@ static void arrange_Widget_(iWidget *d) { | |||
564 | iForEach(ObjectList, i, d->children) { | 605 | iForEach(ObjectList, i, d->children) { |
565 | iWidget *child = as_Widget(i.object); | 606 | iWidget *child = as_Widget(i.object); |
566 | arrange_Widget_(child); | 607 | arrange_Widget_(child); |
567 | if (!isArranged_Widget_(child)) { | 608 | if (isCollapsed_Widget_(child) || !isArrangedPos_Widget_(child)) { |
568 | TRACE(d, "child %p arranging prohibited", child); | 609 | TRACE(d, "child %p arranging prohibited", child); |
569 | continue; | 610 | continue; |
570 | } | 611 | } |
@@ -648,6 +689,7 @@ static void arrange_Widget_(iWidget *d) { | |||
648 | TRACE(d, "END"); | 689 | TRACE(d, "END"); |
649 | } | 690 | } |
650 | 691 | ||
692 | #if 0 | ||
651 | void resetSize_Widget(iWidget *d) { | 693 | void resetSize_Widget(iWidget *d) { |
652 | if (~d->flags & fixedWidth_WidgetFlag) { | 694 | if (~d->flags & fixedWidth_WidgetFlag) { |
653 | d->rect.size.x = d->minSize.x; | 695 | d->rect.size.x = d->minSize.x; |
@@ -657,11 +699,12 @@ void resetSize_Widget(iWidget *d) { | |||
657 | } | 699 | } |
658 | iForEach(ObjectList, i, children_Widget(d)) { | 700 | iForEach(ObjectList, i, children_Widget(d)) { |
659 | iWidget *child = as_Widget(i.object); | 701 | iWidget *child = as_Widget(i.object); |
660 | if (isArranged_Widget_(child)) { | 702 | if (isArrangedSize_Widget_(child)) { |
661 | resetSize_Widget(child); | 703 | resetSize_Widget(child); |
662 | } | 704 | } |
663 | } | 705 | } |
664 | } | 706 | } |
707 | #endif | ||
665 | 708 | ||
666 | void arrange_Widget(iWidget *d) { | 709 | void arrange_Widget(iWidget *d) { |
667 | //resetSize_Widget_(d); /* back to initial default sizes */ | 710 | //resetSize_Widget_(d); /* back to initial default sizes */ |
diff --git a/src/ui/widget.h b/src/ui/widget.h index c3c9609e..36797210 100644 --- a/src/ui/widget.h +++ b/src/ui/widget.h | |||
@@ -87,7 +87,8 @@ enum iWidgetFlag { | |||
87 | }; | 87 | }; |
88 | 88 | ||
89 | /* 64-bit extended flags */ | 89 | /* 64-bit extended flags */ |
90 | #define wasCollapsed_WidgetFlag iBit64(32) | 90 | //#define wasCollapsed_WidgetFlag iBit64(32) |
91 | #define disabledWhenHidden_WidgetFlag iBit64(32) | ||
91 | #define centerHorizontal_WidgetFlag iBit64(33) | 92 | #define centerHorizontal_WidgetFlag iBit64(33) |
92 | #define moveToParentLeftEdge_WidgetFlag iBit64(34) | 93 | #define moveToParentLeftEdge_WidgetFlag iBit64(34) |
93 | #define moveToParentRightEdge_WidgetFlag iBit64(35) | 94 | #define moveToParentRightEdge_WidgetFlag iBit64(35) |
@@ -116,7 +117,6 @@ enum iWidgetFlag { | |||
116 | #define parentCannotResizeHeight_WidgetFlag iBit64(58) | 117 | #define parentCannotResizeHeight_WidgetFlag iBit64(58) |
117 | #define ignoreForParentWidth_WidgetFlag iBit64(59) | 118 | #define ignoreForParentWidth_WidgetFlag iBit64(59) |
118 | #define noFadeBackground_WidgetFlag iBit64(60) | 119 | #define noFadeBackground_WidgetFlag iBit64(60) |
119 | #define disabledWhenHidden_WidgetFlag iBit64(61) | ||
120 | 120 | ||
121 | enum iWidgetAddPos { | 121 | enum iWidgetAddPos { |
122 | back_WidgetAddPos, | 122 | back_WidgetAddPos, |
diff --git a/src/ui/window.c b/src/ui/window.c index 9ac9b918..704e6f2a 100644 --- a/src/ui/window.c +++ b/src/ui/window.c | |||
@@ -471,6 +471,7 @@ void init_Window(iWindow *d, iRect rect) { | |||
471 | d->frameTime = SDL_GetTicks(); | 471 | d->frameTime = SDL_GetTicks(); |
472 | d->loadAnimTimer = 0; | 472 | d->loadAnimTimer = 0; |
473 | init_Text(d->render); | 473 | init_Text(d->render); |
474 | SDL_GetRendererOutputSize(d->render, &d->size.x, &d->size.y); | ||
474 | setupUserInterface_Window(d); | 475 | setupUserInterface_Window(d); |
475 | postCommand_App("~bindings.changed"); /* update from bindings */ | 476 | postCommand_App("~bindings.changed"); /* update from bindings */ |
476 | updateSize_Window_(d, iFalse); | 477 | updateSize_Window_(d, iFalse); |
@@ -1175,6 +1176,7 @@ void setSplitMode_Window(iWindow *d, int splitMode) { | |||
1175 | iAssert(d->roots[1] == NULL); | 1176 | iAssert(d->roots[1] == NULL); |
1176 | d->roots[1] = new_Root(); | 1177 | d->roots[1] = new_Root(); |
1177 | setCurrent_Root(d->roots[1]); | 1178 | setCurrent_Root(d->roots[1]); |
1179 | d->keyRoot = d->roots[1]; | ||
1178 | createUserInterface_Root(d->roots[1]); | 1180 | createUserInterface_Root(d->roots[1]); |
1179 | /* If the old root has multiple tabs, move the current one to the new split. */ { | 1181 | /* If the old root has multiple tabs, move the current one to the new split. */ { |
1180 | iWidget *docTabs0 = findChild_Widget(d->roots[0]->widget, "doctabs"); | 1182 | iWidget *docTabs0 = findChild_Widget(d->roots[0]->widget, "doctabs"); |
@@ -1186,7 +1188,8 @@ void setSplitMode_Window(iWindow *d, int splitMode) { | |||
1186 | iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ | 1188 | iRelease(removeTabPage_Widget(docTabs1, 0)); /* delete the default tab */ |
1187 | setRoot_Widget(as_Widget(moved), d->roots[1]); | 1189 | setRoot_Widget(as_Widget(moved), d->roots[1]); |
1188 | prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); | 1190 | prependTabPage_Widget(docTabs1, iClob(moved), "", 0, 0); |
1189 | showTabPage_Widget(docTabs1, as_Widget(moved)); | 1191 | //showTabPage_Widget(docTabs1, as_Widget(moved)); |
1192 | postCommandf_App("tabs.switch page:%p", moved); | ||
1190 | } | 1193 | } |
1191 | else { | 1194 | else { |
1192 | postCommand_Root(d->roots[1], "navigate.home"); | 1195 | postCommand_Root(d->roots[1], "navigate.home"); |