summaryrefslogtreecommitdiff
path: root/src/ui/widget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-16 09:33:49 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-16 09:33:49 +0200
commit49bc5bba5df94f2bcbe12b513255b92599c052c2 (patch)
tree80faf1f591fb7498dc512d5826457b52c56fc5f3 /src/ui/widget.c
parent63d1b8562c655d5f482846c99ec95ba666587e81 (diff)
Mobile: Dialog layout fixes
Orientation and safe inset changes are now applied to phone dialogs. There is still the occasional unscrollable dialog, but it seems random?
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r--src/ui/widget.c80
1 files changed, 74 insertions, 6 deletions
diff --git a/src/ui/widget.c b/src/ui/widget.c
index 8641dd61..385eb7e0 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -102,7 +102,7 @@ static void visualOffsetAnimation_Widget_(void *ptr) {
102 addTicker_App(visualOffsetAnimation_Widget_, ptr); 102 addTicker_App(visualOffsetAnimation_Widget_, ptr);
103 } 103 }
104 else { 104 else {
105 setFlags_Widget(d, visualOffset_WidgetFlag, iFalse); 105 d->flags &= ~visualOffset_WidgetFlag;
106 } 106 }
107} 107}
108 108
@@ -341,7 +341,7 @@ void arrange_Widget(iWidget *d) {
341 return; 341 return;
342 } 342 }
343 if (d->flags & moveToParentLeftEdge_WidgetFlag) { 343 if (d->flags & moveToParentLeftEdge_WidgetFlag) {
344 d->rect.pos.x = d->padding[0]; 344 d->rect.pos.x = d->padding[0]; /* FIXME: Shouldn't this be d->parent->padding[0]? */
345 } 345 }
346 else if (d->flags & moveToParentRightEdge_WidgetFlag) { 346 else if (d->flags & moveToParentRightEdge_WidgetFlag) {
347 d->rect.pos.x = width_Rect(innerRect_Widget_(d->parent)) - width_Rect(d->rect); 347 d->rect.pos.x = width_Rect(innerRect_Widget_(d->parent)) - width_Rect(d->rect);
@@ -355,6 +355,13 @@ void arrange_Widget(iWidget *d) {
355 if (d->flags & resizeToParentHeight_WidgetFlag) { 355 if (d->flags & resizeToParentHeight_WidgetFlag) {
356 setHeight_Widget_(d, height_Rect(innerRect_Widget_(d->parent))); 356 setHeight_Widget_(d, height_Rect(innerRect_Widget_(d->parent)));
357 } 357 }
358 if (d->flags & safePadding_WidgetFlag) {
359#if defined (iPlatformAppleMobile)
360 float left, top, right, bottom;
361 safeAreaInsets_iOS(&left, &top, &right, &bottom);
362 setPadding_Widget(d, left, top, right, bottom);
363#endif
364 }
358 /* The rest of the arrangement depends on child widgets. */ 365 /* The rest of the arrangement depends on child widgets. */
359 if (!d->children) { 366 if (!d->children) {
360 return; 367 return;
@@ -489,6 +496,9 @@ void arrange_Widget(iWidget *d) {
489 else if ((d->flags & resizeChildren_WidgetFlag) == resizeChildren_WidgetFlag) { 496 else if ((d->flags & resizeChildren_WidgetFlag) == resizeChildren_WidgetFlag) {
490 child->rect.pos = pos; 497 child->rect.pos = pos;
491 } 498 }
499 else if (d->flags & resizeWidthOfChildren_WidgetFlag) {
500 child->rect.pos.x = pos.x;
501 }
492 } 502 }
493 /* Update the size of the widget according to the arrangement. */ 503 /* Update the size of the widget according to the arrangement. */
494 if (d->flags & arrangeSize_WidgetFlag) { 504 if (d->flags & arrangeSize_WidgetFlag) {
@@ -667,10 +677,10 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
667 } 677 }
668#endif 678#endif
669#if 0 679#if 0
670 if (ev->type == SDL_MOUSEBUTTONDOWN) { 680 if (ev->type == SDL_MOUSEWHEEL) {
671 printf("[%p] %s:'%s' ate the button %d\n", 681 printf("[%p] %s:'%s' ate the wheel\n",
672 child, class_Widget(child)->name, 682 child, class_Widget(child)->name,
673 cstr_String(id_Widget(child)), ev->button.button); 683 cstr_String(id_Widget(child)));
674 fflush(stdout); 684 fflush(stdout);
675 } 685 }
676#endif 686#endif
@@ -692,6 +702,36 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
692 return iFalse; 702 return iFalse;
693} 703}
694 704
705static iBool scrollOverflow_Widget_(iWidget *d, int delta) {
706 iRect bounds = bounds_Widget(d);
707 const iInt2 rootSize = rootSize_Window(get_Window());
708 const iRect winRect = safeRootRect_Window(get_Window());
709 const int yTop = top_Rect(winRect);
710 const int yBottom = bottom_Rect(winRect);
711 //const int safeBottom = rootSize.y - yBottom;
712 bounds.pos.y += delta;
713 const iRangei range = { bottom_Rect(winRect) - height_Rect(bounds), yTop };
714// printf("range: %d ... %d\n", range.start, range.end);
715 if (range.start >= range.end) {
716 bounds.pos.y = range.end;
717 }
718 else {
719 bounds.pos.y = iClamp(bounds.pos.y, range.start, range.end);
720 }
721// if (delta >= 0) {
722// bounds.pos.y = iMin(bounds.pos.y, yTop);
723// }
724// else {
725// bounds.pos.y = iMax(bounds.pos.y, );
726// }
727 const iInt2 newPos = localCoord_Widget(d->parent, bounds.pos);
728 if (!isEqual_I2(newPos, d->rect.pos)) {
729 d->rect.pos = newPos;
730 refresh_Widget(d);
731 }
732 return height_Rect(bounds) > height_Rect(winRect);
733}
734
695iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) { 735iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) {
696 if (ev->type == SDL_KEYDOWN) { 736 if (ev->type == SDL_KEYDOWN) {
697 if (ev->key.keysym.sym == SDLK_TAB) { 737 if (ev->key.keysym.sym == SDLK_TAB) {
@@ -720,6 +760,14 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) {
720 } 760 }
721 else if (d->flags & overflowScrollable_WidgetFlag && ev->type == SDL_MOUSEWHEEL && 761 else if (d->flags & overflowScrollable_WidgetFlag && ev->type == SDL_MOUSEWHEEL &&
722 ~d->flags & visualOffset_WidgetFlag) { 762 ~d->flags & visualOffset_WidgetFlag) {
763 int step = ev->wheel.y;
764 if (!isPerPixel_MouseWheelEvent(&ev->wheel)) {
765 step *= lineHeight_Text(uiLabel_FontId);
766 }
767 if (scrollOverflow_Widget_(d, step)) {
768 return iTrue;
769 }
770#if 0
723 iRect bounds = bounds_Widget(d); 771 iRect bounds = bounds_Widget(d);
724 const iInt2 rootSize = rootSize_Window(get_Window()); 772 const iInt2 rootSize = rootSize_Window(get_Window());
725 const iRect winRect = safeRootRect_Window(get_Window()); 773 const iRect winRect = safeRootRect_Window(get_Window());
@@ -736,15 +784,20 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) {
736 bounds.pos.y = iMin(bounds.pos.y, yTop); 784 bounds.pos.y = iMin(bounds.pos.y, yTop);
737 } 785 }
738 else { 786 else {
739 bounds.pos.y = iMax(bounds.pos.y, rootSize.y + safeBottom - height_Rect(bounds)); 787 bounds.pos.y = iMax(bounds.pos.y, rootSize.y /*+ safeBottom*/ - height_Rect(bounds));
740 } 788 }
741 d->rect.pos = localCoord_Widget(d->parent, bounds.pos); 789 d->rect.pos = localCoord_Widget(d->parent, bounds.pos);
742 refresh_Widget(d); 790 refresh_Widget(d);
743 return iTrue; 791 return iTrue;
744 } 792 }
793#endif
745 } 794 }
746 switch (ev->type) { 795 switch (ev->type) {
747 case SDL_USEREVENT: { 796 case SDL_USEREVENT: {
797 if (d->flags & overflowScrollable_WidgetFlag &&
798 isCommand_UserEvent(ev, "widget.overflow")) {
799 scrollOverflow_Widget_(d, 0); /* check bounds */
800 }
748 if (ev->user.code == command_UserEventCode && d->commandHandler && 801 if (ev->user.code == command_UserEventCode && d->commandHandler &&
749 d->commandHandler(d, ev->user.data1)) { 802 d->commandHandler(d, ev->user.data1)) {
750 return iTrue; 803 return iTrue;
@@ -1041,6 +1094,21 @@ iAny *findChild_Widget(const iWidget *d, const char *id) {
1041 return NULL; 1094 return NULL;
1042} 1095}
1043 1096
1097static void addMatchingToArray_Widget_(const iWidget *d, const char *id, iPtrArray *found) {
1098 if (cmp_String(id_Widget(d), id) == 0) {
1099 pushBack_PtrArray(found, d);
1100 }
1101 iForEach(ObjectList, i, d->children) {
1102 addMatchingToArray_Widget_(i.object, id, found);
1103 }
1104}
1105
1106const iPtrArray *findChildren_Widget(const iWidget *d, const char *id) {
1107 iPtrArray *found = new_PtrArray();
1108 addMatchingToArray_Widget_(d, id, found);
1109 return collect_PtrArray(found);
1110}
1111
1044iAny *findParentClass_Widget(const iWidget *d, const iAnyClass *class) { 1112iAny *findParentClass_Widget(const iWidget *d, const iAnyClass *class) {
1045 if (!d) return NULL; 1113 if (!d) return NULL;
1046 iWidget *i = d->parent; 1114 iWidget *i = d->parent;