widget: Make IntFormAnimate self-delete after closing.

This eliminates boilerplate code growing in src/hci.cpp for each animated form.
master
Cyp 2013-02-28 10:07:36 +01:00
parent 6a71410927
commit c6274f3d33
14 changed files with 41 additions and 250 deletions

View File

@ -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) {}

View File

@ -49,6 +49,8 @@ static SWORD ClickedAudioID = -1;
static WIDGET_KEY lastReleasedKey_DEPRECATED = WKEY_NONE;
static std::vector<WIDGET *> 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();
}

View File

@ -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.
*/

View File

@ -255,13 +255,6 @@ extern std::list<DROID_TEMPLATE> 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);

View File

@ -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;
}
}

View File

@ -33,7 +33,6 @@ extern void intProcessInGameOptions (UDWORD);
extern void intAddInGamePopup(void);
// status bools.
extern bool ClosingInGameOp;
extern bool InGameOpUp;
extern bool isInGamePopupUp;
// ////////////////////////////////////////////////////////////////////////////

View File

@ -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<unsigned>(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;
}
}

View File

@ -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);

View File

@ -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
{

View File

@ -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;

View File

@ -146,8 +146,6 @@ static GAMECODE renderLoop()
intAddInGamePopup();
}
HandleClosingWindows(); // Needs to be done outside the pause case.
audio_Update();
wzShowMouse(true);

View File

@ -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;
}

View File

@ -46,7 +46,6 @@ extern void intCloseDebugMenuNoAnim (void);
extern void setDebugMenuEntry(char *entry, SDWORD index);
extern bool MultiMenuUp;
extern bool ClosingMultiMenu;
extern bool DebugMenuUp;

View File

@ -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();
}
}