diff options
author | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-27 11:40:50 +0300 |
---|---|---|
committer | Jaakko Keränen <jaakko.keranen@iki.fi> | 2021-04-27 11:40:50 +0300 |
commit | 170209cf926e2f714d507fefaa6b30fd245811ad (patch) | |
tree | 1dd6ff1e7c9ecf69c0857b8524bfdc82f07794b9 /src/ui/widget.c | |
parent | 83e14d99ba75316da265cfa5f3fd092caa1498cf (diff) |
Refactor: Moving RootData so it can become non-global state
Diffstat (limited to 'src/ui/widget.c')
-rw-r--r-- | src/ui/widget.c | 96 |
1 files changed, 30 insertions, 66 deletions
diff --git a/src/ui/widget.c b/src/ui/widget.c index b7458528..b3f7b27f 100644 --- a/src/ui/widget.c +++ b/src/ui/widget.c | |||
@@ -39,42 +39,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ | |||
39 | # include "../ios.h" | 39 | # include "../ios.h" |
40 | #endif | 40 | #endif |
41 | 41 | ||
42 | iDeclareType(RootData) | ||
43 | |||
44 | /* TODO: Move to root.c, one instance per root widget. */ | ||
45 | struct Impl_RootData { | ||
46 | iWidget *hover; | ||
47 | iWidget *mouseGrab; | ||
48 | iWidget *focus; | ||
49 | iPtrArray *onTop; /* order is important; last one is topmost */ | ||
50 | iPtrSet *pendingDestruction; | ||
51 | }; | ||
52 | |||
53 | static iRootData rootData_; | ||
54 | |||
55 | iPtrArray *onTop_RootData_(void) { | ||
56 | if (!rootData_.onTop) { | ||
57 | rootData_.onTop = new_PtrArray(); | ||
58 | } | ||
59 | return rootData_.onTop; | ||
60 | } | ||
61 | |||
62 | void destroyPending_Widget(void) { | ||
63 | iForEach(PtrSet, i, rootData_.pendingDestruction) { | ||
64 | iWidget *widget = *i.value; | ||
65 | if (!isFinished_Anim(&widget->visualOffset)) { | ||
66 | continue; | ||
67 | } | ||
68 | if (widget->parent) { | ||
69 | removeChild_Widget(widget->parent, widget); | ||
70 | } | ||
71 | iAssert(widget->parent == NULL); | ||
72 | // iAssert(widget->object.refCount == 1); /* ref could be held in garbage still */ | ||
73 | iRelease(widget); | ||
74 | remove_PtrSetIterator(&i); | ||
75 | } | ||
76 | } | ||
77 | |||
78 | void releaseChildren_Widget(iWidget *d) { | 42 | void releaseChildren_Widget(iWidget *d) { |
79 | iForEach(ObjectList, i, d->children) { | 43 | iForEach(ObjectList, i, d->children) { |
80 | ((iWidget *) i.object)->parent = NULL; /* the actual reference being held */ | 44 | ((iWidget *) i.object)->parent = NULL; /* the actual reference being held */ |
@@ -117,7 +81,7 @@ void deinit_Widget(iWidget *d) { | |||
117 | //#endif | 81 | //#endif |
118 | deinit_String(&d->id); | 82 | deinit_String(&d->id); |
119 | if (d->flags & keepOnTop_WidgetFlag) { | 83 | if (d->flags & keepOnTop_WidgetFlag) { |
120 | removeAll_PtrArray(onTop_RootData_(), d); | 84 | removeAll_PtrArray(onTop_RootData(), d); |
121 | } | 85 | } |
122 | if (d->flags & visualOffset_WidgetFlag) { | 86 | if (d->flags & visualOffset_WidgetFlag) { |
123 | removeTicker_App(visualOffsetAnimation_Widget_, d); | 87 | removeTicker_App(visualOffsetAnimation_Widget_, d); |
@@ -131,10 +95,10 @@ static void aboutToBeDestroyed_Widget_(iWidget *d) { | |||
131 | return; | 95 | return; |
132 | } | 96 | } |
133 | if (flags_Widget(d) & keepOnTop_WidgetFlag) { | 97 | if (flags_Widget(d) & keepOnTop_WidgetFlag) { |
134 | removeOne_PtrArray(onTop_RootData_(), d); | 98 | removeOne_PtrArray(onTop_RootData(), d); |
135 | } | 99 | } |
136 | if (isHover_Widget(d)) { | 100 | if (isHover_Widget(d)) { |
137 | rootData_.hover = NULL; | 101 | data_Root()->hover = NULL; |
138 | } | 102 | } |
139 | iForEach(ObjectList, i, d->children) { | 103 | iForEach(ObjectList, i, d->children) { |
140 | aboutToBeDestroyed_Widget_(as_Widget(i.object)); | 104 | aboutToBeDestroyed_Widget_(as_Widget(i.object)); |
@@ -147,10 +111,10 @@ void destroy_Widget(iWidget *d) { | |||
147 | postRefresh_App(); | 111 | postRefresh_App(); |
148 | } | 112 | } |
149 | aboutToBeDestroyed_Widget_(d); | 113 | aboutToBeDestroyed_Widget_(d); |
150 | if (!rootData_.pendingDestruction) { | 114 | if (!data_Root()->pendingDestruction) { |
151 | rootData_.pendingDestruction = new_PtrSet(); | 115 | data_Root()->pendingDestruction = new_PtrSet(); |
152 | } | 116 | } |
153 | insert_PtrSet(rootData_.pendingDestruction, d); | 117 | insert_PtrSet(data_Root()->pendingDestruction, d); |
154 | } | 118 | } |
155 | } | 119 | } |
156 | 120 | ||
@@ -174,7 +138,7 @@ void setFlags_Widget(iWidget *d, int64_t flags, iBool set) { | |||
174 | } | 138 | } |
175 | iChangeFlags(d->flags, flags, set); | 139 | iChangeFlags(d->flags, flags, set); |
176 | if (flags & keepOnTop_WidgetFlag) { | 140 | if (flags & keepOnTop_WidgetFlag) { |
177 | iPtrArray *onTop = onTop_RootData_(); | 141 | iPtrArray *onTop = onTop_RootData(); |
178 | if (set) { | 142 | if (set) { |
179 | iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos); | 143 | iAssert(indexOf_PtrArray(onTop, d) == iInvalidPos); |
180 | pushBack_PtrArray(onTop, d); | 144 | pushBack_PtrArray(onTop, d); |
@@ -769,24 +733,24 @@ static iBool filterEvent_Widget_(const iWidget *d, const SDL_Event *ev) { | |||
769 | } | 733 | } |
770 | 734 | ||
771 | void unhover_Widget(void) { | 735 | void unhover_Widget(void) { |
772 | rootData_.hover = NULL; | 736 | data_Root()->hover = NULL; |
773 | } | 737 | } |
774 | 738 | ||
775 | iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | 739 | iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { |
776 | if (!d->parent) { | 740 | if (!d->parent) { |
777 | setCurrent_Root(d); | 741 | //setCurrent_Root(d); |
778 | if (ev->type == SDL_MOUSEMOTION) { | 742 | if (ev->type == SDL_MOUSEMOTION) { |
779 | /* Hover widget may change. */ | 743 | /* Hover widget may change. */ |
780 | setHover_Widget(NULL); | 744 | setHover_Widget(NULL); |
781 | } | 745 | } |
782 | if (rootData_.focus && isKeyboardEvent_(ev)) { | 746 | if (data_Root()->focus && isKeyboardEvent_(ev)) { |
783 | /* Root dispatches keyboard events directly to the focused widget. */ | 747 | /* Root dispatches keyboard events directly to the focused widget. */ |
784 | if (dispatchEvent_Widget(rootData_.focus, ev)) { | 748 | if (dispatchEvent_Widget(data_Root()->focus, ev)) { |
785 | return iTrue; | 749 | return iTrue; |
786 | } | 750 | } |
787 | } | 751 | } |
788 | /* Root offers events first to widgets on top. */ | 752 | /* Root offers events first to widgets on top. */ |
789 | iReverseForEach(PtrArray, i, rootData_.onTop) { | 753 | iReverseForEach(PtrArray, i, data_Root()->onTop) { |
790 | iWidget *widget = *i.value; | 754 | iWidget *widget = *i.value; |
791 | if (isVisible_Widget(widget) && dispatchEvent_Widget(widget, ev)) { | 755 | if (isVisible_Widget(widget) && dispatchEvent_Widget(widget, ev)) { |
792 | #if 0 | 756 | #if 0 |
@@ -810,7 +774,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
810 | } | 774 | } |
811 | } | 775 | } |
812 | else if (ev->type == SDL_MOUSEMOTION && | 776 | else if (ev->type == SDL_MOUSEMOTION && |
813 | (!rootData_.hover || hasParent_Widget(d, rootData_.hover)) && | 777 | (!data_Root()->hover || hasParent_Widget(d, data_Root()->hover)) && |
814 | flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag && | 778 | flags_Widget(d) & hover_WidgetFlag && ~flags_Widget(d) & hidden_WidgetFlag && |
815 | ~flags_Widget(d) & disabled_WidgetFlag) { | 779 | ~flags_Widget(d) & disabled_WidgetFlag) { |
816 | if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) { | 780 | if (contains_Widget(d, init_I2(ev->motion.x, ev->motion.y))) { |
@@ -828,7 +792,7 @@ iBool dispatchEvent_Widget(iWidget *d, const SDL_Event *ev) { | |||
828 | handle the events first. */ | 792 | handle the events first. */ |
829 | iReverseForEach(ObjectList, i, d->children) { | 793 | iReverseForEach(ObjectList, i, d->children) { |
830 | iWidget *child = as_Widget(i.object); | 794 | iWidget *child = as_Widget(i.object); |
831 | if (child == rootData_.focus && isKeyboardEvent_(ev)) { | 795 | if (child == data_Root()->focus && isKeyboardEvent_(ev)) { |
832 | continue; /* Already dispatched. */ | 796 | continue; /* Already dispatched. */ |
833 | } | 797 | } |
834 | if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) { | 798 | if (isVisible_Widget(child) && child->flags & keepOnTop_WidgetFlag) { |
@@ -1117,7 +1081,7 @@ void drawChildren_Widget(const iWidget *d) { | |||
1117 | } | 1081 | } |
1118 | /* Root draws the on-top widgets on top of everything else. */ | 1082 | /* Root draws the on-top widgets on top of everything else. */ |
1119 | if (!d->parent) { | 1083 | if (!d->parent) { |
1120 | iConstForEach(PtrArray, i, onTop_RootData_()) { | 1084 | iConstForEach(PtrArray, i, onTop_RootData()) { |
1121 | const iWidget *top = *i.value; | 1085 | const iWidget *top = *i.value; |
1122 | draw_Widget(top); | 1086 | draw_Widget(top); |
1123 | } | 1087 | } |
@@ -1234,7 +1198,7 @@ iAny *hitChild_Widget(const iWidget *d, iInt2 coord) { | |||
1234 | } | 1198 | } |
1235 | /* Check for on-top widgets first. */ | 1199 | /* Check for on-top widgets first. */ |
1236 | if (!d->parent) { | 1200 | if (!d->parent) { |
1237 | iReverseForEach(PtrArray, i, onTop_RootData_()) { | 1201 | iReverseForEach(PtrArray, i, onTop_RootData()) { |
1238 | iWidget *child = i.ptr; | 1202 | iWidget *child = i.ptr; |
1239 | // printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)), | 1203 | // printf("ontop: %s (%s) hidden:%d hittable:%d\n", cstr_String(id_Widget(child)), |
1240 | // class_Widget(child)->name, | 1204 | // class_Widget(child)->name, |
@@ -1322,12 +1286,12 @@ iBool isDisabled_Widget(const iAnyObject *d) { | |||
1322 | 1286 | ||
1323 | iBool isFocused_Widget(const iAnyObject *d) { | 1287 | iBool isFocused_Widget(const iAnyObject *d) { |
1324 | iAssert(isInstance_Object(d, &Class_Widget)); | 1288 | iAssert(isInstance_Object(d, &Class_Widget)); |
1325 | return rootData_.focus == d; | 1289 | return data_Root()->focus == d; |
1326 | } | 1290 | } |
1327 | 1291 | ||
1328 | iBool isHover_Widget(const iAnyObject *d) { | 1292 | iBool isHover_Widget(const iAnyObject *d) { |
1329 | iAssert(isInstance_Object(d, &Class_Widget)); | 1293 | iAssert(isInstance_Object(d, &Class_Widget)); |
1330 | return rootData_.hover == d; | 1294 | return data_Root()->hover == d; |
1331 | } | 1295 | } |
1332 | 1296 | ||
1333 | iBool isSelected_Widget(const iAnyObject *d) { | 1297 | iBool isSelected_Widget(const iAnyObject *d) { |
@@ -1373,12 +1337,12 @@ iBool isAffectedByVisualOffset_Widget(const iWidget *d) { | |||
1373 | } | 1337 | } |
1374 | 1338 | ||
1375 | void setFocus_Widget(iWidget *d) { | 1339 | void setFocus_Widget(iWidget *d) { |
1376 | if (rootData_.focus != d) { | 1340 | if (data_Root()->focus != d) { |
1377 | if (rootData_.focus) { | 1341 | if (data_Root()->focus) { |
1378 | iAssert(!contains_PtrSet(rootData_.pendingDestruction, rootData_.focus)); | 1342 | iAssert(!contains_PtrSet(data_Root()->pendingDestruction, data_Root()->focus)); |
1379 | postCommand_Widget(rootData_.focus, "focus.lost"); | 1343 | postCommand_Widget(data_Root()->focus, "focus.lost"); |
1380 | } | 1344 | } |
1381 | rootData_.focus = d; | 1345 | data_Root()->focus = d; |
1382 | if (d) { | 1346 | if (d) { |
1383 | iAssert(flags_Widget(d) & focusable_WidgetFlag); | 1347 | iAssert(flags_Widget(d) & focusable_WidgetFlag); |
1384 | postCommand_Widget(d, "focus.gained"); | 1348 | postCommand_Widget(d, "focus.gained"); |
@@ -1387,15 +1351,15 @@ void setFocus_Widget(iWidget *d) { | |||
1387 | } | 1351 | } |
1388 | 1352 | ||
1389 | iWidget *focus_Widget(void) { | 1353 | iWidget *focus_Widget(void) { |
1390 | return rootData_.focus; | 1354 | return data_Root()->focus; |
1391 | } | 1355 | } |
1392 | 1356 | ||
1393 | void setHover_Widget(iWidget *d) { | 1357 | void setHover_Widget(iWidget *d) { |
1394 | rootData_.hover = d; | 1358 | data_Root()->hover = d; |
1395 | } | 1359 | } |
1396 | 1360 | ||
1397 | iWidget *hover_Widget(void) { | 1361 | iWidget *hover_Widget(void) { |
1398 | return rootData_.hover; | 1362 | return data_Root()->hover; |
1399 | } | 1363 | } |
1400 | 1364 | ||
1401 | static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *startFrom, | 1365 | static const iWidget *findFocusable_Widget_(const iWidget *d, const iWidget *startFrom, |
@@ -1451,14 +1415,14 @@ iAny *findFocusable_Widget(const iWidget *startFrom, enum iWidgetFocusDir focusD | |||
1451 | } | 1415 | } |
1452 | 1416 | ||
1453 | void setMouseGrab_Widget(iWidget *d) { | 1417 | void setMouseGrab_Widget(iWidget *d) { |
1454 | if (rootData_.mouseGrab != d) { | 1418 | if (data_Root()->mouseGrab != d) { |
1455 | rootData_.mouseGrab = d; | 1419 | data_Root()->mouseGrab = d; |
1456 | SDL_CaptureMouse(d != NULL); | 1420 | SDL_CaptureMouse(d != NULL); |
1457 | } | 1421 | } |
1458 | } | 1422 | } |
1459 | 1423 | ||
1460 | iWidget *mouseGrab_Widget(void) { | 1424 | iWidget *mouseGrab_Widget(void) { |
1461 | return rootData_.mouseGrab; | 1425 | return data_Root()->mouseGrab; |
1462 | } | 1426 | } |
1463 | 1427 | ||
1464 | void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) { | 1428 | void postCommand_Widget(const iAnyObject *d, const char *cmd, ...) { |
@@ -1492,7 +1456,7 @@ void refresh_Widget(const iAnyObject *d) { | |||
1492 | } | 1456 | } |
1493 | 1457 | ||
1494 | void raise_Widget(iWidget *d) { | 1458 | void raise_Widget(iWidget *d) { |
1495 | iPtrArray *onTop = onTop_RootData_(); | 1459 | iPtrArray *onTop = onTop_RootData(); |
1496 | if (d->flags & keepOnTop_WidgetFlag) { | 1460 | if (d->flags & keepOnTop_WidgetFlag) { |
1497 | iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos); | 1461 | iAssert(indexOf_PtrArray(onTop, d) != iInvalidPos); |
1498 | removeOne_PtrArray(onTop, d); | 1462 | removeOne_PtrArray(onTop, d); |