summaryrefslogtreecommitdiff
path: root/src/ui/widget.c
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2022-01-20 12:06:39 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2022-01-20 12:06:39 +0200
commit6da3bdb612e0ead07ff93f4f6dc5aef46c7b9c9e (patch)
tree4378984d744dc67b7453573524d5839b9ce7f9d5 /src/ui/widget.c
parentd5169339b3454c80a6f2ed5f8cb937e5d5613fc0 (diff)
parent33816278c84fd7ac7e895f4111229c4ff4436b53 (diff)
Merge branch 'dev' of skyjake.fi:gemini/lagrange into dev
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r--src/ui/widget.c102
1 files changed, 86 insertions, 16 deletions
diff --git a/src/ui/widget.c b/src/ui/widget.c
index cedda461..9f67b1c7 100644
--- a/src/ui/widget.c
+++ b/src/ui/widget.c
@@ -31,6 +31,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
31#include "util.h" 31#include "util.h"
32#include "window.h" 32#include "window.h"
33 33
34#include "labelwidget.h"
35
34#include <the_Foundation/ptrarray.h> 36#include <the_Foundation/ptrarray.h>
35#include <the_Foundation/ptrset.h> 37#include <the_Foundation/ptrset.h>
36#include <SDL_mouse.h> 38#include <SDL_mouse.h>
@@ -122,7 +124,9 @@ void init_Widget(iWidget *d) {
122 init_String(&d->id); 124 init_String(&d->id);
123 d->root = get_Root(); /* never changes after this */ 125 d->root = get_Root(); /* never changes after this */
124 d->flags = 0; 126 d->flags = 0;
127 d->flags2 = 0;
125 d->rect = zero_Rect(); 128 d->rect = zero_Rect();
129 d->oldSize = zero_I2();
126 d->minSize = zero_I2(); 130 d->minSize = zero_I2();
127 d->sizeRef = NULL; 131 d->sizeRef = NULL;
128 d->offsetRef = NULL; 132 d->offsetRef = NULL;
@@ -139,8 +143,11 @@ void init_Widget(iWidget *d) {
139static void visualOffsetAnimation_Widget_(void *ptr) { 143static void visualOffsetAnimation_Widget_(void *ptr) {
140 iWidget *d = ptr; 144 iWidget *d = ptr;
141 postRefresh_App(); 145 postRefresh_App();
146 d->root->didAnimateVisualOffsets = iTrue;
147// printf("'%s' visoffanim: fin:%d val:%f\n", cstr_String(&d->id),
148// isFinished_Anim(&d->visualOffset), value_Anim(&d->visualOffset)); fflush(stdout);
142 if (!isFinished_Anim(&d->visualOffset)) { 149 if (!isFinished_Anim(&d->visualOffset)) {
143 addTicker_App(visualOffsetAnimation_Widget_, ptr); 150 addTickerRoot_App(visualOffsetAnimation_Widget_, d->root, ptr);
144 } 151 }
145 else { 152 else {
146 d->flags &= ~visualOffset_WidgetFlag; 153 d->flags &= ~visualOffset_WidgetFlag;
@@ -269,10 +276,12 @@ void setMinSize_Widget(iWidget *d, iInt2 minSize) {
269} 276}
270 277
271void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) { 278void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) {
272 d->padding[0] = left; 279 if (d) {
273 d->padding[1] = top; 280 d->padding[0] = left;
274 d->padding[2] = right; 281 d->padding[1] = top;
275 d->padding[3] = bottom; 282 d->padding[2] = right;
283 d->padding[3] = bottom;
284 }
276} 285}
277 286
278iWidget *root_Widget(const iWidget *d) { 287iWidget *root_Widget(const iWidget *d) {
@@ -414,9 +423,10 @@ static iBool setWidth_Widget_(iWidget *d, int width) {
414 if (d->rect.size.x != width) { 423 if (d->rect.size.x != width) {
415 d->rect.size.x = width; 424 d->rect.size.x = width;
416 TRACE(d, "width has changed to %d", width); 425 TRACE(d, "width has changed to %d", width);
417 if (class_Widget(d)->sizeChanged) { 426// if (~d->flags2 & undefinedWidth_WidgetFlag2 && class_Widget(d)->sizeChanged) {
418 class_Widget(d)->sizeChanged(d); 427// class_Widget(d)->sizeChanged(d);
419 } 428// }
429// d->flags2 &= ~undefinedWidth_WidgetFlag2;
420 return iTrue; 430 return iTrue;
421 } 431 }
422 } 432 }
@@ -437,9 +447,10 @@ static iBool setHeight_Widget_(iWidget *d, int height) {
437 if (d->rect.size.y != height) { 447 if (d->rect.size.y != height) {
438 d->rect.size.y = height; 448 d->rect.size.y = height;
439 TRACE(d, "height has changed to %d", height); 449 TRACE(d, "height has changed to %d", height);
440 if (class_Widget(d)->sizeChanged) { 450// if (~d->flags2 & undefinedHeight_WidgetFlag2 && class_Widget(d)->sizeChanged) {
441 class_Widget(d)->sizeChanged(d); 451// class_Widget(d)->sizeChanged(d);
442 } 452// }
453// d->flags2 &= ~undefinedHeight_WidgetFlag2;
443 return iTrue; 454 return iTrue;
444 } 455 }
445 } 456 }
@@ -836,6 +847,13 @@ static void arrange_Widget_(iWidget *d) {
836} 847}
837 848
838static void resetArrangement_Widget_(iWidget *d) { 849static void resetArrangement_Widget_(iWidget *d) {
850 d->oldSize = d->rect.size;
851 if (d->flags & resizeToParentWidth_WidgetFlag) {
852 d->rect.size.x = 0;
853 }
854 if (d->flags & resizeToParentHeight_WidgetFlag) {
855 d->rect.size.y = 0;
856 }
839 iForEach(ObjectList, i, children_Widget(d)) { 857 iForEach(ObjectList, i, children_Widget(d)) {
840 iWidget *child = as_Widget(i.object); 858 iWidget *child = as_Widget(i.object);
841 resetArrangement_Widget_(child); 859 resetArrangement_Widget_(child);
@@ -847,6 +865,14 @@ static void resetArrangement_Widget_(iWidget *d) {
847 ~child->flags & fixedWidth_WidgetFlag) { 865 ~child->flags & fixedWidth_WidgetFlag) {
848 child->rect.size.x = 0; 866 child->rect.size.x = 0;
849 } 867 }
868 if (d->flags & resizeChildrenToWidestChild_WidgetFlag) {
869 if (isInstance_Object(child, &Class_LabelWidget)) {
870 updateSize_LabelWidget((iLabelWidget *) child);
871 }
872 else {
873 child->rect.size.x = 0;
874 }
875 }
850 if (d->flags & arrangeVertical_WidgetFlag) { 876 if (d->flags & arrangeVertical_WidgetFlag) {
851 child->rect.pos.y = 0; 877 child->rect.pos.y = 0;
852 } 878 }
@@ -858,6 +884,15 @@ static void resetArrangement_Widget_(iWidget *d) {
858 } 884 }
859} 885}
860 886
887static void notifySizeChanged_Widget_(iWidget *d) {
888 if (class_Widget(d)->sizeChanged && !isEqual_I2(d->rect.size, d->oldSize)) {
889 class_Widget(d)->sizeChanged(d);
890 }
891 iForEach(ObjectList, child, d->children) {
892 notifySizeChanged_Widget_(child.object);
893 }
894}
895
861void arrange_Widget(iWidget *d) { 896void arrange_Widget(iWidget *d) {
862 if (d) { 897 if (d) {
863#if !defined (NDEBUG) 898#if !defined (NDEBUG)
@@ -867,6 +902,8 @@ void arrange_Widget(iWidget *d) {
867#endif 902#endif
868 resetArrangement_Widget_(d); /* back to initial default sizes */ 903 resetArrangement_Widget_(d); /* back to initial default sizes */
869 arrange_Widget_(d); 904 arrange_Widget_(d);
905 notifySizeChanged_Widget_(d);
906 d->root->didChangeArrangement = iTrue;
870 } 907 }
871} 908}
872 909
@@ -884,6 +921,14 @@ int visualOffsetByReference_Widget(const iWidget *d) {
884// const float factor = width_Widget(d) / (float) size_Root(d->root).x; 921// const float factor = width_Widget(d) / (float) size_Root(d->root).x;
885 const int invOff = width_Widget(d) - iRound(value_Anim(&child->visualOffset)); 922 const int invOff = width_Widget(d) - iRound(value_Anim(&child->visualOffset));
886 offX -= invOff / 4; 923 offX -= invOff / 4;
924#if 0
925 if (invOff) {
926 printf(" [%p] %s (%p, fin:%d visoff:%d drag:%d): invOff %d\n", d, cstr_String(&child->id), child,
927 isFinished_Anim(&child->visualOffset),
928 (child->flags & visualOffset_WidgetFlag) != 0,
929 (child->flags & dragged_WidgetFlag) != 0, invOff); fflush(stdout);
930 }
931#endif
887 } 932 }
888 } 933 }
889 return offX; 934 return offX;
@@ -1183,6 +1228,9 @@ iBool scrollOverflow_Widget(iWidget *d, int delta) {
1183 bounds.pos.y = iMin(bounds.pos.y, validPosRange.end); 1228 bounds.pos.y = iMin(bounds.pos.y, validPosRange.end);
1184 } 1229 }
1185// printf("range: %d ... %d\n", range.start, range.end); 1230// printf("range: %d ... %d\n", range.start, range.end);
1231 if (delta) {
1232 d->root->didChangeArrangement = iTrue; /* ensure that widgets update if needed */
1233 }
1186 } 1234 }
1187 else { 1235 else {
1188 bounds.pos.y = iClamp(bounds.pos.y, validPosRange.start, validPosRange.end); 1236 bounds.pos.y = iClamp(bounds.pos.y, validPosRange.start, validPosRange.end);
@@ -1370,7 +1418,8 @@ void drawLayerEffects_Widget(const iWidget *d) {
1370 shadowBorder = iFalse; 1418 shadowBorder = iFalse;
1371 } 1419 }
1372 } 1420 }
1373 const iBool isFaded = fadeBackground && ~d->flags & noFadeBackground_WidgetFlag; 1421 const iBool isFaded = (fadeBackground && ~d->flags & noFadeBackground_WidgetFlag) ||
1422 (d->flags2 & fadeBackground_WidgetFlag2);
1374 if (shadowBorder && ~d->flags & noShadowBorder_WidgetFlag) { 1423 if (shadowBorder && ~d->flags & noShadowBorder_WidgetFlag) {
1375 iPaint p; 1424 iPaint p;
1376 init_Paint(&p); 1425 init_Paint(&p);
@@ -1381,9 +1430,19 @@ void drawLayerEffects_Widget(const iWidget *d) {
1381 init_Paint(&p); 1430 init_Paint(&p);
1382 p.alpha = 0x50; 1431 p.alpha = 0x50;
1383 if (flags_Widget(d) & (visualOffset_WidgetFlag | dragged_WidgetFlag)) { 1432 if (flags_Widget(d) & (visualOffset_WidgetFlag | dragged_WidgetFlag)) {
1384 const float area = d->rect.size.x * d->rect.size.y; 1433 const float area = d->rect.size.x * d->rect.size.y;
1434 const float rootArea = area_Rect(rect_Root(d->root));
1385 const float visibleArea = area_Rect(intersect_Rect(bounds_Widget(d), rect_Root(d->root))); 1435 const float visibleArea = area_Rect(intersect_Rect(bounds_Widget(d), rect_Root(d->root)));
1386 p.alpha *= (area > 0 ? visibleArea / area : 0.0f); 1436 if (isPortraitPhone_App() && !cmp_String(&d->id, "sidebar")) {
1437 p.alpha *= iClamp(visibleArea / rootArea * 2, 0.0f, 1.0f);
1438 }
1439 else if (area > 0) {
1440 p.alpha *= visibleArea / area;
1441 }
1442 else {
1443 p.alpha = 0;
1444 }
1445 //printf("area:%f visarea:%f alpha:%d\n", rootArea, visibleArea, p.alpha);
1387 } 1446 }
1388 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND); 1447 SDL_SetRenderDrawBlendMode(renderer_Window(get_Window()), SDL_BLENDMODE_BLEND);
1389 fillRect_Paint(&p, rect_Root(d->root), backgroundFadeColor_Widget()); 1448 fillRect_Paint(&p, rect_Root(d->root), backgroundFadeColor_Widget());
@@ -1851,7 +1910,7 @@ iAny *findParentClass_Widget(const iWidget *d, const iAnyClass *class) {
1851} 1910}
1852 1911
1853iAny *findOverflowScrollable_Widget(iWidget *d) { 1912iAny *findOverflowScrollable_Widget(iWidget *d) {
1854 const iRect rootRect = rect_Root(d->root); 1913 const iRect rootRect = visibleRect_Root(d->root);
1855 for (iWidget *w = d; w; w = parent_Widget(w)) { 1914 for (iWidget *w = d; w; w = parent_Widget(w)) {
1856 if (flags_Widget(w) & overflowScrollable_WidgetFlag) { 1915 if (flags_Widget(w) & overflowScrollable_WidgetFlag) {
1857 const iRect bounds = boundsWithoutVisualOffset_Widget(w); 1916 const iRect bounds = boundsWithoutVisualOffset_Widget(w);
@@ -1956,12 +2015,16 @@ iBool isAffectedByVisualOffset_Widget(const iWidget *d) {
1956 if (w->flags & visualOffset_WidgetFlag) { 2015 if (w->flags & visualOffset_WidgetFlag) {
1957 return iTrue; 2016 return iTrue;
1958 } 2017 }
2018 if (visualOffsetByReference_Widget(w) != 0) {
2019 return iTrue;
2020 }
1959 } 2021 }
1960 return iFalse; 2022 return iFalse;
1961} 2023}
1962 2024
1963void setFocus_Widget(iWidget *d) { 2025void setFocus_Widget(iWidget *d) {
1964 iWindow *win = get_Window(); 2026 iWindow *win = d ? window_Widget(d) : get_Window();
2027 iAssert(win);
1965 if (win->focus != d) { 2028 if (win->focus != d) {
1966 if (win->focus) { 2029 if (win->focus) {
1967 iAssert(!contains_PtrSet(win->focus->root->pendingDestruction, win->focus)); 2030 iAssert(!contains_PtrSet(win->focus->root->pendingDestruction, win->focus));
@@ -1976,6 +2039,13 @@ void setFocus_Widget(iWidget *d) {
1976 } 2039 }
1977} 2040}
1978 2041
2042void setKeyboardGrab_Widget(iWidget *d) {
2043 iWindow *win = d ? window_Widget(d) : get_Window();
2044 iAssert(win);
2045 win->focus = d;
2046 /* no notifications sent */
2047}
2048
1979iWidget *focus_Widget(void) { 2049iWidget *focus_Widget(void) {
1980 return get_Window()->focus; 2050 return get_Window()->focus;
1981} 2051}