diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-20 12:06:39 +0200 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2022-01-20 12:06:39 +0200 |
commit | 6da3bdb612e0ead07ff93f4f6dc5aef46c7b9c9e (patch) | |
tree | 4378984d744dc67b7453573524d5839b9ce7f9d5 /src/ui/widget.c | |
parent | d5169339b3454c80a6f2ed5f8cb937e5d5613fc0 (diff) | |
parent | 33816278c84fd7ac7e895f4111229c4ff4436b53 (diff) |
Merge branch 'dev' of skyjake.fi:gemini/lagrange into dev
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r-- | src/ui/widget.c | 102 |
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) { | |||
139 | static void visualOffsetAnimation_Widget_(void *ptr) { | 143 | static 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 | ||
271 | void setPadding_Widget(iWidget *d, int left, int top, int right, int bottom) { | 278 | void 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 | ||
278 | iWidget *root_Widget(const iWidget *d) { | 287 | iWidget *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 | ||
838 | static void resetArrangement_Widget_(iWidget *d) { | 849 | static 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 | ||
887 | static 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 | |||
861 | void arrange_Widget(iWidget *d) { | 896 | void 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 | ||
1853 | iAny *findOverflowScrollable_Widget(iWidget *d) { | 1912 | iAny *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 | ||
1963 | void setFocus_Widget(iWidget *d) { | 2025 | void 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 | ||
2042 | void 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 | |||
1979 | iWidget *focus_Widget(void) { | 2049 | iWidget *focus_Widget(void) { |
1980 | return get_Window()->focus; | 2050 | return get_Window()->focus; |
1981 | } | 2051 | } |