From c6274f3d3367de16691beb9952b1acdebb730a6f Mon Sep 17 00:00:00 2001 From: Cyp Date: Thu, 28 Feb 2013 10:07:36 +0100 Subject: [PATCH] widget: Make IntFormAnimate self-delete after closing. This eliminates boilerplate code growing in src/hci.cpp for each animated form. --- lib/widget/widgbase.h | 2 + lib/widget/widget.cpp | 23 +++++ src/hci.cpp | 197 +----------------------------------------- src/hci.h | 9 -- src/ingameop.cpp | 7 +- src/ingameop.h | 1 - src/intdisplay.cpp | 15 +--- src/intdisplay.h | 3 +- src/intelmap.cpp | 8 +- src/intorder.cpp | 3 +- src/loop.cpp | 2 - src/multimenu.cpp | 11 +-- src/multimenu.h | 1 - src/transporter.cpp | 9 +- 14 files changed, 41 insertions(+), 250 deletions(-) diff --git a/lib/widget/widgbase.h b/lib/widget/widgbase.h index 7466fcc44..ac3769c89 100644 --- a/lib/widget/widgbase.h +++ b/lib/widget/widgbase.h @@ -85,6 +85,8 @@ struct WIDGET WIDGET(WIDGET *parent, WIDGET_TYPE type = WIDG_UNSPECIFIED_TYPE); virtual ~WIDGET(); + void deleteLater(); ///< Like "delete this;", but safe to call from display/run callbacks. + virtual void widgetLost(WIDGET *); virtual void clicked(W_CONTEXT *, WIDGET_KEY = WKEY_PRIMARY) {} diff --git a/lib/widget/widget.cpp b/lib/widget/widget.cpp index 7ead30a20..ad798c698 100644 --- a/lib/widget/widget.cpp +++ b/lib/widget/widget.cpp @@ -49,6 +49,8 @@ static SWORD ClickedAudioID = -1; static WIDGET_KEY lastReleasedKey_DEPRECATED = WKEY_NONE; +static std::vector widgetDeletionQueue; + /* Initialise the widget module */ bool widgInitialise() @@ -72,6 +74,18 @@ void widgShutDown(void) { } +static void deleteOldWidgets() +{ + while (!widgetDeletionQueue.empty()) + { + WIDGET *guiltyWidget = widgetDeletionQueue.back(); + widgetDeletionQueue.pop_back(); // Do this before deleting widget, in case it calls deleteLater() on other widgets. + + ASSERT_OR_RETURN(, std::find(widgetDeletionQueue.begin(), widgetDeletionQueue.end(), guiltyWidget) == widgetDeletionQueue.end(), "Called deleteLater() twice on the same widget."); + + delete guiltyWidget; + } +} W_INIT::W_INIT() : formID(0) @@ -129,6 +143,11 @@ WIDGET::~WIDGET() } } +void WIDGET::deleteLater() +{ + widgetDeletionQueue.push_back(this); +} + void WIDGET::attach(WIDGET *widget) { ASSERT_OR_RETURN(, widget != NULL && widget->parentWidget == NULL, "Bad attach."); @@ -731,6 +750,8 @@ WidgetTriggers const &widgRunScreen(W_SCREEN *psScreen) /* Process any user callback functions */ psScreen->psForm->processCallbacksRecursive(&sContext); + deleteOldWidgets(); // Delete any widgets that called deleteLater() while being run. + /* Return the ID of a pressed button or finished edit box if any */ return psScreen->retWidgets; } @@ -793,6 +814,8 @@ void widgDisplayScreen(W_SCREEN *psScreen) // Display the widgets. psScreen->psForm->displayRecursive(0, 0); + deleteOldWidgets(); // Delete any widgets that called deleteLater() while being displayed. + /* Display the tool tip if there is one */ tipDisplay(); } diff --git a/src/hci.cpp b/src/hci.cpp index e80d0e864..ca68c13b8 100644 --- a/src/hci.cpp +++ b/src/hci.cpp @@ -137,15 +137,7 @@ static BUTSTATE ReticuleEnabled[NUMRETBUTS] = // Reticule button enable states {IDRET_COMMAND, false, false}, }; -static bool ClosingObject = false; -static bool ClosingStats = false; static UDWORD keyButtonMapping = 0; -bool ClosingMessageView = false; -bool ClosingIntelMap = false; -bool ClosingOrder = false; -bool ClosingTrans = false; -bool ClosingTransCont = false; -bool ClosingTransDroids = false; static bool ReticuleUp = false; static bool Refreshing = false; @@ -3721,8 +3713,7 @@ void intRemoveObject(void) IntFormAnimated *Form = (IntFormAnimated *)widgGetFromID(psWScreen, IDOBJ_FORM); if (Form) { - Form->closeAnimate(); - ClosingObject = true; + Form->closeAnimateDelete(); } ClearObjectBuffers(); @@ -3762,8 +3753,7 @@ void intRemoveStats(void) IntFormAnimated *Form = (IntFormAnimated *)widgGetFromID(psWScreen, IDSTAT_FORM); if (Form) { - Form->closeAnimate(); - ClosingStats = true; + Form->closeAnimateDelete(); } ClearStatBuffers(); @@ -3786,189 +3776,6 @@ void intRemoveStatsNoAnim(void) psStatsScreenOwner = NULL; } -// Poll for closing windows and handle them, ensure called even if game is paused. -// -void HandleClosingWindows(void) -{ - WIDGET *Widg; - - if (ClosingObject) - { - Widg = widgGetFromID(psWScreen, IDOBJ_FORM); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDOBJ_FORM); - ClosingObject = false; - } - } - else - { - ClosingObject = false; - } - } - - if (ClosingStats) - { - Widg = widgGetFromID(psWScreen, IDSTAT_FORM); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDSTAT_FORM); - ClosingStats = false; - } - } - else - { - ClosingStats = false; - } - } - if (ClosingMessageView) - { - Widg = widgGetFromID(psWScreen, IDINTMAP_MSGVIEW); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDINTMAP_MSGVIEW); - ClosingMessageView = false; - } - } - else - { - ClosingMessageView = false; - } - } - if (ClosingIntelMap) - { - Widg = widgGetFromID(psWScreen, IDINTMAP_FORM); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDINTMAP_FORM); - ClosingIntelMap = false; - } - } - else - { - ClosingIntelMap = false; - } - } - - if (ClosingOrder) - { - Widg = widgGetFromID(psWScreen, IDORDER_FORM); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDORDER_FORM); - ClosingOrder = false; - } - } - else - { - ClosingOrder = false; - } - } - if (ClosingTrans) - { - Widg = widgGetFromID(psWScreen, IDTRANS_FORM); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDTRANS_FORM); - ClosingTrans = false; - } - } - else - { - ClosingTrans = false; - } - } - if (ClosingTransCont) - { - Widg = widgGetFromID(psWScreen, IDTRANS_CONTENTFORM); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDTRANS_CONTENTFORM); - ClosingTransCont = false; - } - } - else - { - ClosingTransCont = false; - } - } - if (ClosingTransDroids) - { - Widg = widgGetFromID(psWScreen, IDTRANS_DROIDS); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, IDTRANS_DROIDS); - ClosingTransDroids = false; - } - } - else - { - ClosingTransDroids = false; - } - } - - if (ClosingInGameOp) - { - Widg = widgGetFromID(psWScreen, INTINGAMEOP); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, INTINGAMEOP); - ClosingInGameOp = false; - } - } - else - { - ClosingInGameOp = false; - } - } - - if (ClosingMultiMenu) - { - Widg = widgGetFromID(psWScreen, MULTIMENU_FORM); - if (Widg) - { - // Has the window finished closing? - if (Widg->pUserData) - { - widgDelete(psWScreen, MULTIMENU_FORM); - ClosingMultiMenu = false; - } - } - else - { - ClosingMultiMenu = false; - } - } -} - - /** * Get the object refered to by a button ID on the object screen. This works for object or stats buttons. */ diff --git a/src/hci.h b/src/hci.h index 9c1a8e43a..646d01a4f 100644 --- a/src/hci.h +++ b/src/hci.h @@ -255,13 +255,6 @@ extern std::list localTemplates; ///< Unsychnronised list, /* pointer to hold the imd to use for a new template in the design screen */ extern iIMDShape *pNewDesignIMD; -extern bool ClosingMessageView; -extern bool ClosingIntelMap; -extern bool ClosingTrans; -extern bool ClosingTransCont; -extern bool ClosingTransDroids; -extern bool ClosingOrder; - /* Initialise the in game interface */ extern bool intInitialise(void); @@ -393,8 +386,6 @@ extern BASE_OBJECT *getCurrentSelected(void); //initialise all the previous obj - particularly useful for when go Off world! extern void intResetPreviousObj(void); -extern void HandleClosingWindows(void); - extern bool intIsRefreshing(void); extern void intDemolishCancel(void); diff --git a/src/ingameop.cpp b/src/ingameop.cpp index d89eaa93c..d399468b2 100644 --- a/src/ingameop.cpp +++ b/src/ingameop.cpp @@ -52,8 +52,7 @@ #include "main.h" #include "warzoneconfig.h" -//status bools.(for hci.h) -bool ClosingInGameOp = false; + bool InGameOpUp = false; bool isInGamePopupUp = false; // //////////////////////////////////////////////////////////////////////////// @@ -371,7 +370,6 @@ bool intCloseInGameOptions(bool bPutUpLoadSave, bool bResetMissionWidgets) } InGameOpUp = false; - ClosingInGameOp = true; } else { @@ -390,8 +388,7 @@ bool intCloseInGameOptions(bool bPutUpLoadSave, bool bResetMissionWidgets) if (form) { - form->closeAnimate(); - ClosingInGameOp = true; // like orderup/closingorder + form->closeAnimateDelete(); InGameOpUp = false; } } diff --git a/src/ingameop.h b/src/ingameop.h index 504240f35..a015d2d15 100644 --- a/src/ingameop.h +++ b/src/ingameop.h @@ -33,7 +33,6 @@ extern void intProcessInGameOptions (UDWORD); extern void intAddInGamePopup(void); // status bools. -extern bool ClosingInGameOp; extern bool InGameOpUp; extern bool isInGamePopupUp; // //////////////////////////////////////////////////////////////////////////// diff --git a/src/intdisplay.cpp b/src/intdisplay.cpp index 30699eb79..3290ddc70 100644 --- a/src/intdisplay.cpp +++ b/src/intdisplay.cpp @@ -1131,16 +1131,10 @@ IntFormAnimated::IntFormAnimated(WIDGET *parent, bool openAnimate) disableChildren = openAnimate; } -void IntFormAnimated::closeAnimate() +void IntFormAnimated::closeAnimateDelete() { currentAction = 3; disableChildren = true; - pUserData = nullptr; // Used to signal when the close anim has finished. -} - -bool IntFormAnimated::isClosed() const -{ - return currentAction == 5; } void IntFormAnimated::display(int xOffset, int yOffset) @@ -1187,11 +1181,6 @@ void IntFormAnimated::display(int xOffset, int yOffset) aBegin = aOpen; aEnd = aClosed; break; - case 5: // Closed. - aBegin = aClosed; - aEnd = aClosed; - startTime = realTime; - break; } int den = FORM_OPEN_ANIM_DURATION; int num = std::min(realTime - startTime, den); @@ -1201,7 +1190,7 @@ void IntFormAnimated::display(int xOffset, int yOffset) switch (currentAction) { case 2: disableChildren = false; break; - case 5: pUserData = (void *)1; break; + case 5: deleteLater(); break; } } diff --git a/src/intdisplay.h b/src/intdisplay.h index 9d4e3205e..99783c2d5 100644 --- a/src/intdisplay.h +++ b/src/intdisplay.h @@ -160,8 +160,7 @@ struct IntFormAnimated : public W_FORM void display(int xOffset, int yOffset); - void closeAnimate(); - bool isClosed() const; + void closeAnimateDelete(); ///< Animates the form closing, and deletes itself when done. private: void displayOpening(int xOffset, int yOffset); diff --git a/src/intelmap.cpp b/src/intelmap.cpp index 2955caf85..a8e1efb33 100644 --- a/src/intelmap.cpp +++ b/src/intelmap.cpp @@ -968,9 +968,8 @@ void intRemoveIntelMap(void) IntFormAnimated *form = (IntFormAnimated *)widgGetFromID(psWScreen, IDINTMAP_FORM); if (form) { - form->closeAnimate(); + form->closeAnimateDelete(); } - ClosingIntelMap = true; //remove the text label widgDelete(psWScreen, IDINTMAP_PAUSELABEL); @@ -1022,11 +1021,8 @@ void intRemoveMessageView(bool animated) if (animated) { - widgDelete(psWScreen, IDINTMAP_CLOSE); - // Start the window close animation. - form->closeAnimate(); - ClosingMessageView = true; + form->closeAnimateDelete(); } else { diff --git a/src/intorder.cpp b/src/intorder.cpp index 8990b7428..e4ad5f1fe 100644 --- a/src/intorder.cpp +++ b/src/intorder.cpp @@ -1082,8 +1082,7 @@ void intRemoveOrder(void) IntFormAnimated *form = (IntFormAnimated *)widgGetFromID(psWScreen, IDORDER_FORM); if (form != nullptr) { - form->closeAnimate(); - ClosingOrder = true; + form->closeAnimateDelete(); OrderUp = false; SelectedDroids.clear(); psSelectedFactory = NULL; diff --git a/src/loop.cpp b/src/loop.cpp index 622401c15..62c241817 100644 --- a/src/loop.cpp +++ b/src/loop.cpp @@ -146,8 +146,6 @@ static GAMECODE renderLoop() intAddInGamePopup(); } - HandleClosingWindows(); // Needs to be done outside the pause case. - audio_Update(); wzShowMouse(true); diff --git a/src/multimenu.cpp b/src/multimenu.cpp index 31699d726..dad2cfd63 100644 --- a/src/multimenu.cpp +++ b/src/multimenu.cpp @@ -70,7 +70,6 @@ W_SCREEN *psRScreen; // requester stuff. extern char MultiCustomMapsPath[PATH_MAX]; bool MultiMenuUp = false; -bool ClosingMultiMenu = false; bool DebugMenuUp = false; static UDWORD context = 0; UDWORD current_tech = 1; @@ -1311,12 +1310,11 @@ bool intAddMultiMenu(void) // //////////////////////////////////////////////////////////////////////////// void intCloseMultiMenuNoAnim(void) { - if (!MultiMenuUp && !ClosingMultiMenu) + widgDelete(psWScreen, MULTIMENU_FORM); + if (!MultiMenuUp) { return; } - widgDelete(psWScreen, MULTIMENU_CLOSE); - widgDelete(psWScreen, MULTIMENU_FORM); MultiMenuUp = false; if (intMode != INT_INTELMAP) { @@ -1333,14 +1331,11 @@ bool intCloseMultiMenu(void) return true; } - widgDelete(psWScreen, MULTIMENU_CLOSE); - // Start the window close animation. IntFormAnimated *form = (IntFormAnimated *)widgGetFromID(psWScreen, MULTIMENU_FORM); if (form != nullptr) { - form->closeAnimate(); - ClosingMultiMenu = true; + form->closeAnimateDelete(); MultiMenuUp = false; } diff --git a/src/multimenu.h b/src/multimenu.h index b6bbc2072..19908962f 100644 --- a/src/multimenu.h +++ b/src/multimenu.h @@ -46,7 +46,6 @@ extern void intCloseDebugMenuNoAnim (void); extern void setDebugMenuEntry(char *entry, SDWORD index); extern bool MultiMenuUp; -extern bool ClosingMultiMenu; extern bool DebugMenuUp; diff --git a/src/transporter.cpp b/src/transporter.cpp index 5a72d0c05..a41e62ee0 100644 --- a/src/transporter.cpp +++ b/src/transporter.cpp @@ -1034,8 +1034,7 @@ void intRemoveTrans(void) IntFormAnimated *form = (IntFormAnimated *)widgGetFromID(psWScreen, IDTRANS_FORM); if (form) { - form->closeAnimate(); - ClosingTrans = true; + form->closeAnimateDelete(); } intRemoveTransContent(); @@ -1060,8 +1059,7 @@ void intRemoveTransContent(void) IntFormAnimated *form = (IntFormAnimated *)widgGetFromID(psWScreen, IDTRANS_CONTENTFORM); if (form) { - form->closeAnimate(); - ClosingTransCont = true; + form->closeAnimateDelete(); } } @@ -1079,10 +1077,9 @@ void intRemoveTransDroidsAvail(void) IntFormAnimated *form = (IntFormAnimated *)widgGetFromID(psWScreen, IDTRANS_DROIDS); if (form) { - form->closeAnimate(); - ClosingTransDroids = true; //remember which tab we were on widgGetTabs(psWScreen, IDTRANS_DROIDTAB, &objMajor); + form->closeAnimateDelete(); } }