summaryrefslogtreecommitdiff
path: root/src/ui/widget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-03-09 22:44:45 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-03-09 22:44:45 +0200
commit2002543dbedcc1666d02d11fbde55f794d692bb7 (patch)
tree853412e7593d4a1ca3f0ccdc5ca31466a3400463 /src/ui/widget.c
parent5ccb0e0096dff6c2bbdfa959610620a14fdc918d (diff)
Mobile: Revising phone-style dialogs
Sliding panels and left-edge swipes.
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r--src/ui/widget.c92
1 files changed, 68 insertions, 24 deletions
diff --git a/src/ui/widget.c b/src/ui/widget.c
index d7543615..ec229b86 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -153,11 +153,13 @@ void setFlags_Widget(iWidget *d, int64_t flags, iBool set) {
153 } 153 }
154 iChangeFlags(d->flags, flags, set); 154 iChangeFlags(d->flags, flags, set);
155 if (flags & keepOnTop_WidgetFlag) { 155 if (flags & keepOnTop_WidgetFlag) {
156 iPtrArray *onTop = onTop_RootData_();
156 if (set) { 157 if (set) {
157 pushBack_PtrArray(onTop_RootData_(), d); 158 iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos);
159 pushBack_PtrArray(onTop, d);
158 } 160 }
159 else { 161 else {
160 removeOne_PtrArray(onTop_RootData_(), d); 162 removeOne_PtrArray(onTop, d);
161 } 163 }
162 } 164 }
163 } 165 }
@@ -169,10 +171,17 @@ void setPos_Widget(iWidget *d, iInt2 pos) {
169} 171}
170 172
171void setSize_Widget(iWidget *d, iInt2 size) { 173void setSize_Widget(iWidget *d, iInt2 size) {
172 if (size.x < 0) size.x = d->rect.size.x; 174 int flags = fixedSize_WidgetFlag;
173 if (size.y < 0) size.y = d->rect.size.y; 175 if (size.x < 0) {
176 size.x = d->rect.size.x;
177 flags &= ~fixedWidth_WidgetFlag;
178 }
179 if (size.y < 0) {
180 size.y = d->rect.size.y;
181 flags &= ~fixedHeight_WidgetFlag;
182 }
174 d->rect.size = size; 183 d->rect.size = size;
175 setFlags_Widget(d, fixedSize_WidgetFlag, iTrue); 184 setFlags_Widget(d, flags, iTrue);
176} 185}
177 186
178void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) { 187void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) {
@@ -498,16 +507,24 @@ void arrange_Widget(iWidget *d) {
498 } 507 }
499} 508}
500 509
501iRect bounds_Widget(const iWidget *d) { 510static void applyVisualOffset_Widget_(const iWidget *d, iInt2 *pos) {
502 iRect bounds = d->rect;
503 if (d->flags & visualOffset_WidgetFlag) { 511 if (d->flags & visualOffset_WidgetFlag) {
504 bounds.pos.y += iRound(value_Anim(&d->visualOffset)); 512 const int off = iRound(value_Anim(&d->visualOffset));
513 if (d->flags & horizontalOffset_WidgetFlag) {
514 pos->x += off;
515 }
516 else {
517 pos->y += off;
518 }
505 } 519 }
520}
521
522iRect bounds_Widget(const iWidget *d) {
523 iRect bounds = d->rect;
524 applyVisualOffset_Widget_(d, &bounds.pos);
506 for (const iWidget *w = d->parent; w; w = w->parent) { 525 for (const iWidget *w = d->parent; w; w = w->parent) {
507 iInt2 pos = w->rect.pos; 526 iInt2 pos = w->rect.pos;
508 if (w->flags & visualOffset_WidgetFlag) { 527 applyVisualOffset_Widget_(w, &pos);
509 pos.y += iRound(value_Anim(&w->visualOffset));
510 }
511 addv_I2(&bounds.pos, pos); 528 addv_I2(&bounds.pos, pos);
512 } 529 }
513#if defined (iPlatformMobile) 530#if defined (iPlatformMobile)
@@ -595,6 +612,14 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) {
595 if (dispatchEvent_Widget(child, ev)) { 612 if (dispatchEvent_Widget(child, ev)) {
596#if 0 613#if 0
597 if (ev->type == SDL_MOUSEBUTTONDOWN) { 614 if (ev->type == SDL_MOUSEBUTTONDOWN) {
615 printf("[%p] %s:'%s' ate the button %d\n",
616 child, class_Widget(child)->name,
617 cstr_String(id_Widget(child)), ev->button.button);
618 fflush(stdout);
619 }
620#endif
621#if 0
622 if (ev->type == SDL_MOUSEBUTTONDOWN) {
598 printf("widget %p ('%s' class:%s) ate the mouse down\n", 623 printf("widget %p ('%s' class:%s) ate the mouse down\n",
599 child, cstr_String(id_Widget(child)), 624 child, cstr_String(id_Widget(child)),
600 class_Widget(child)->name); 625 class_Widget(child)->name);
@@ -637,20 +662,25 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) {
637 postCommand_Widget(d, "mouse.moved coord:%d %d", ev->motion.x, ev->motion.y); 662 postCommand_Widget(d, "mouse.moved coord:%d %d", ev->motion.x, ev->motion.y);
638 return iTrue; 663 return iTrue;
639 } 664 }
640 else if (d->flags & overflowScrollable_WidgetFlag && ev->type == SDL_MOUSEWHEEL) { 665 else if (d->flags & overflowScrollable_WidgetFlag && ev->type == SDL_MOUSEWHEEL &&
666 ~d->flags & visualOffset_WidgetFlag) {
641 iRect bounds = bounds_Widget(d); 667 iRect bounds = bounds_Widget(d);
642 const iInt2 winSize = rootSize_Window(get_Window()); 668 const iInt2 rootSize = rootSize_Window(get_Window());
643 if (height_Rect(bounds) > winSize.y) { 669 const iRect winRect = safeRootRect_Window(get_Window());
670 const int yTop = top_Rect(winRect);
671 const int yBottom = bottom_Rect(winRect);
672 const int safeBottom = rootSize.y - yBottom;
673 if (height_Rect(bounds) > height_Rect(winRect)) {
644 int step = ev->wheel.y; 674 int step = ev->wheel.y;
645#if !defined (iPlatformApple) 675 if (!isPerPixel_MouseWheelEvent(&ev->wheel)) {
646 step *= lineHeight_Text(uiLabel_FontId); 676 step *= lineHeight_Text(uiLabel_FontId);
647#endif 677 }
648 bounds.pos.y += step; 678 bounds.pos.y += step;
649 if (step > 0) { 679 if (step > 0) {
650 bounds.pos.y = iMin(bounds.pos.y, 0); 680 bounds.pos.y = iMin(bounds.pos.y, yTop);
651 } 681 }
652 else { 682 else {
653 bounds.pos.y = iMax(bounds.pos.y, winSize.y - height_Rect(bounds)); 683 bounds.pos.y = iMax(bounds.pos.y, rootSize.y + safeBottom - height_Rect(bounds));
654 } 684 }
655 d->rect.pos = localCoord_Widget(d->parent, bounds.pos); 685 d->rect.pos = localCoord_Widget(d->parent, bounds.pos);
656 refresh_Widget(d); 686 refresh_Widget(d);
@@ -676,6 +706,15 @@ iBool processEvent_Widget(iWidget *d, const SDL_Event *ev) {
676 ev->button.y); 706 ev->button.y);
677 } 707 }
678 if (d->flags & mouseModal_WidgetFlag && isMouseEvent_(ev)) { 708 if (d->flags & mouseModal_WidgetFlag && isMouseEvent_(ev)) {
709 if ((ev->type == SDL_MOUSEBUTTONDOWN || ev->type == SDL_MOUSEBUTTONUP) &&
710 d->flags & commandOnClick_WidgetFlag) {
711 postCommand_Widget(d,
712 "mouse.clicked arg:%d button:%d coord:%d %d",
713 ev->type == SDL_MOUSEBUTTONDOWN ? 1 : 0,
714 ev->button.button,
715 ev->button.x,
716 ev->button.y);
717 }
679 setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW); 718 setCursor_Window(get_Window(), SDL_SYSTEM_CURSOR_ARROW);
680 return iTrue; 719 return iTrue;
681 } 720 }
@@ -801,14 +840,15 @@ void drawChildren_Widget(const iWidget *d) {
801 /* Root draws the on-top widgets on top of everything else. */ 840 /* Root draws the on-top widgets on top of everything else. */
802 if (!d->parent) { 841 if (!d->parent) {
803 iConstForEach(PtrArray, i, onTop_RootData_()) { 842 iConstForEach(PtrArray, i, onTop_RootData_()) {
804 draw_Widget(*i.value); 843 const iWidget *top = *i.value;
844 draw_Widget(top);
805 } 845 }
806 } 846 }
807} 847}
808 848
809void draw_Widget(const iWidget *d) { 849void draw_Widget(const iWidget *d) {
810 drawBackground_Widget(d); 850 drawBackground_Widget(d);
811 drawChildren_Widget(d); 851 drawChildren_Widget(d);
812} 852}
813 853
814iAny *addChild_Widget(iWidget *d, iAnyObject *child) { 854iAny *addChild_Widget(iWidget *d, iAnyObject *child) {
@@ -903,7 +943,7 @@ iAny *hitChild_Widget(const iWidget *d, iInt2 coord) {
903 } 943 }
904 /* Check for on-top widgets first. */ 944 /* Check for on-top widgets first. */
905 if (!d->parent) { 945 if (!d->parent) {
906 iForEach(PtrArray, i, onTop_RootData_()) { 946 iReverseForEach(PtrArray, i, onTop_RootData_()) {
907 iWidget *child = i.ptr; 947 iWidget *child = i.ptr;
908// printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)), 948// printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)),
909// class_Widget(child)->name, 949// class_Widget(child)->name,
@@ -920,8 +960,8 @@ iAny *hitChild_Widget(const iWidget *d, iInt2 coord) {
920 if (found) return found; 960 if (found) return found;
921 } 961 }
922 } 962 }
923 if ((d->flags & overflowScrollable_WidgetFlag || class_Widget(d) != &Class_Widget) && 963 if ((d->flags & overflowScrollable_WidgetFlag || class_Widget(d) != &Class_Widget ||
924 ~d->flags & unhittable_WidgetFlag && 964 d->flags & mouseModal_WidgetFlag) && ~d->flags & unhittable_WidgetFlag &&
925 contains_Widget(d, coord)) { 965 contains_Widget(d, coord)) {
926 return iConstCast(iWidget *, d); 966 return iConstCast(iWidget *, d);
927 } 967 }
@@ -1168,6 +1208,10 @@ iBool hasVisibleChildOnTop_Widget(const iWidget *parent) {
1168} 1208}
1169 1209
1170void printTree_Widget(const iWidget *d) { 1210void printTree_Widget(const iWidget *d) {
1211 if (!d) {
1212 printf("[NULL]\n");
1213 return;
1214 }
1171 printTree_Widget_(d, 0); 1215 printTree_Widget_(d, 0);
1172} 1216}
1173 1217