From 86c151ebaabf4d2a89065fe2c99c2c430354642a Mon Sep 17 00:00:00 2001 From: elexis Date: Fri, 16 Aug 2019 18:46:04 +0000 Subject: [PATCH] PushGuiPage support for passing a function instead of a function name. Allows coding the GUI without global functions which break prototype-oriented coding, refs #5322, fixing the concern in 4b1297b328. Supports stacked message boxes and removes the according workaround. Change structree / civinfo switch-dialog code from 760a47335d to perform the callback for page that actually registered the callback. Ensure the parent that the callbackhandler is always called if the page is closed. Merge PopGuiPage and PopGuiPageCB following that choice, incidentally leaving cleaner code. Differential Revision: https://code.wildfiregames.com/D1684 Comments by: Yves, Vladislav, wraitii, leper This was SVN commit r22676. --- .../mods/mod/gui/common/functions_msgbox.js | 58 +++------- binaries/data/mods/mod/gui/common/terms.js | 37 +++--- binaries/data/mods/mod/gui/modio/modio.js | 4 +- binaries/data/mods/mod/gui/modmod/modmodio.js | 4 +- binaries/data/mods/mod/gui/msgbox/msgbox.js | 15 +-- .../mods/mod/gui/termsdialog/termsdialog.js | 2 +- .../data/mods/public/gui/aiconfig/aiconfig.js | 5 +- .../data/mods/public/gui/civinfo/civinfo.js | 16 +-- .../mods/public/gui/gamesetup/gamesetup.js | 57 ++++----- .../mods/public/gui/gamesetup/gamesetup.xml | 8 +- .../data/mods/public/gui/locale/locale.js | 2 +- .../gui/locale_advanced/locale_advanced.js | 2 +- .../data/mods/public/gui/manual/manual.js | 15 --- .../data/mods/public/gui/manual/manual.xml | 7 +- .../data/mods/public/gui/options/options.js | 17 +-- .../data/mods/public/gui/pregame/mainmenu.js | 16 ++- .../data/mods/public/gui/pregame/mainmenu.xml | 10 +- .../mods/public/gui/reference/common/core.js | 9 -- .../gui/reference/structree/structree.js | 16 +-- .../public/gui/reference/viewer/viewer.js | 6 - .../public/gui/reference/viewer/viewer.xml | 2 +- .../data/mods/public/gui/savegame/save.js | 2 +- .../mods/public/gui/session/hotkeys/misc.xml | 8 +- binaries/data/mods/public/gui/session/menu.js | 88 +++++++------- .../public/gui/session/selection_panels.js | 12 +- .../public/gui/session/top_panel/civ_icon.xml | 2 +- .../public/gui/splashscreen/splashscreen.js | 2 +- .../data/mods/public/gui/summary/summary.js | 2 +- source/gui/GUIManager.cpp | 108 +++++++++--------- source/gui/GUIManager.h | 30 ++++- .../gui/scripting/JSInterface_GUIManager.cpp | 20 ++-- source/gui/scripting/JSInterface_GUIManager.h | 5 +- 32 files changed, 258 insertions(+), 329 deletions(-) delete mode 100644 binaries/data/mods/public/gui/manual/manual.js diff --git a/binaries/data/mods/mod/gui/common/functions_msgbox.js b/binaries/data/mods/mod/gui/common/functions_msgbox.js index f289749a72..acf524bff3 100644 --- a/binaries/data/mods/mod/gui/common/functions_msgbox.js +++ b/binaries/data/mods/mod/gui/common/functions_msgbox.js @@ -1,50 +1,18 @@ -// We want to pass callback functions for the different buttons in a convenient way. -// Because passing functions accross compartment boundaries is a pain, we just store them here together with some optional arguments. -// The messageBox page will return the code of the pressed button and the according function will be called. -var g_MessageBoxBtnFunctions = []; -var g_MessageBoxCallbackArgs = []; - -function messageBoxCallbackFunction(btnCode) -{ - if (btnCode !== undefined && g_MessageBoxBtnFunctions[btnCode]) - { - // Cache the variables to make it possible to call a messageBox from a callback function. - let callbackFunction = g_MessageBoxBtnFunctions[btnCode]; - let callbackArgs = g_MessageBoxCallbackArgs[btnCode]; - - g_MessageBoxBtnFunctions = []; - g_MessageBoxCallbackArgs = []; - - if (callbackArgs !== undefined) - callbackFunction(callbackArgs); - else - callbackFunction(); - return; - } - - g_MessageBoxBtnFunctions = []; - g_MessageBoxCallbackArgs = []; -} - function messageBox(mbWidth, mbHeight, mbMessage, mbTitle, mbButtonCaptions, mbBtnCode, mbCallbackArgs) { - if (g_MessageBoxBtnFunctions && g_MessageBoxBtnFunctions.length) - { - warn("A messagebox was called when a previous callback function is still set, aborting!"); - return; - } - - g_MessageBoxBtnFunctions = mbBtnCode; - g_MessageBoxCallbackArgs = mbCallbackArgs || g_MessageBoxCallbackArgs; - - Engine.PushGuiPage("page_msgbox.xml", { - "width": mbWidth, - "height": mbHeight, - "message": mbMessage, - "title": mbTitle, - "buttonCaptions": mbButtonCaptions, - "callback": mbBtnCode && "messageBoxCallbackFunction" - }); + Engine.PushGuiPage( + "page_msgbox.xml", + { + "width": mbWidth, + "height": mbHeight, + "message": mbMessage, + "title": mbTitle, + "buttonCaptions": mbButtonCaptions + }, + btnCode => { + if (mbBtnCode !== undefined && mbBtnCode[btnCode]) + mbBtnCode[btnCode](mbCallbackArgs ? mbCallbackArgs[btnCode] : undefined); + }); } function openURL(url) diff --git a/binaries/data/mods/mod/gui/common/terms.js b/binaries/data/mods/mod/gui/common/terms.js index 6992d7056c..6d6a4b7a6b 100644 --- a/binaries/data/mods/mod/gui/common/terms.js +++ b/binaries/data/mods/mod/gui/common/terms.js @@ -7,24 +7,29 @@ function initTerms(terms) function openTerms(page) { - Engine.PushGuiPage("page_termsdialog.xml", { - "file": g_Terms[page].file, - "title": g_Terms[page].title, - "sprintf": g_Terms[page].sprintf, - "urlButtons": g_Terms[page].urlButtons || [], - "termsURL": g_Terms[page].termsURL || undefined, - "page": page, - "callback": "acceptTerms" - }); -} + Engine.PushGuiPage( + "page_termsdialog.xml", + { + "file": g_Terms[page].file, + "title": g_Terms[page].title, + "sprintf": g_Terms[page].sprintf, + "urlButtons": g_Terms[page].urlButtons || [], + "termsURL": g_Terms[page].termsURL || undefined, + "page": page + }, + data => { + g_Terms[data.page].accepted = data.accepted; -function acceptTerms(data) -{ - g_Terms[data.page].accepted = data.accepted; - Engine.ConfigDB_CreateAndWriteValueToFile("user", g_Terms[data.page].config, data.accepted ? getTermsHash(data.page) : "0", "config/user.cfg"); + Engine.ConfigDB_CreateAndWriteValueToFile( + "user", + g_Terms[data.page].config, + data.accepted ? getTermsHash(data.page) : "0", + "config/user.cfg"); - if (g_Terms[data.page].callback) - g_Terms[data.page].callback(data); + if (g_Terms[data.page].callback) + g_Terms[data.page].callback(data); + } + ); } function checkTerms() diff --git a/binaries/data/mods/mod/gui/modio/modio.js b/binaries/data/mods/mod/gui/modio/modio.js index c31c5912eb..f5cc5b9837 100644 --- a/binaries/data/mods/mod/gui/modio/modio.js +++ b/binaries/data/mods/mod/gui/modio/modio.js @@ -268,9 +268,9 @@ function cancelRequest() hideDialog(); } -function closePage(data) +function closePage() { - Engine.PopGuiPageCB(undefined); + Engine.PopGuiPage(); } function showErrorMessageBox(caption, title, buttonCaptions, buttonActions) diff --git a/binaries/data/mods/mod/gui/modmod/modmodio.js b/binaries/data/mods/mod/gui/modmod/modmodio.js index 3125b41029..b3e69f1044 100644 --- a/binaries/data/mods/mod/gui/modmod/modmodio.js +++ b/binaries/data/mods/mod/gui/modmod/modmodio.js @@ -26,7 +26,5 @@ function downloadModsButton() function openModIo(data) { if (data.accepted) - Engine.PushGuiPage("page_modio.xml", { - "callback": "initMods" - }); + Engine.PushGuiPage("page_modio.xml", {}, initMods); } diff --git a/binaries/data/mods/mod/gui/msgbox/msgbox.js b/binaries/data/mods/mod/gui/msgbox/msgbox.js index 58f2b09356..9276a482c6 100644 --- a/binaries/data/mods/mod/gui/msgbox/msgbox.js +++ b/binaries/data/mods/mod/gui/msgbox/msgbox.js @@ -28,22 +28,15 @@ function init(data) let mbButton = []; captions.forEach((caption, i) => { mbButton[i] = Engine.GetGUIObjectByName("mbButton" + (i + 1)); - - let action = function() - { - if (data.callback) - Engine.PopGuiPageCB(i); - else - Engine.PopGuiPage(); - }; - mbButton[i].caption = caption; - mbButton[i].onPress = action; mbButton[i].hidden = false; + mbButton[i].onPress = () => { + Engine.PopGuiPage(i); + }; // Convention: Cancel is the first button if (i == 0) - mbCancelHotkey.onPress = action; + mbCancelHotkey.onPress = mbButton[i].onPress; }); // Distribute buttons horizontally diff --git a/binaries/data/mods/mod/gui/termsdialog/termsdialog.js b/binaries/data/mods/mod/gui/termsdialog/termsdialog.js index 818b19039f..4420e990bb 100644 --- a/binaries/data/mods/mod/gui/termsdialog/termsdialog.js +++ b/binaries/data/mods/mod/gui/termsdialog/termsdialog.js @@ -82,7 +82,7 @@ function initLanguageSelection() function closeTerms(accepted) { - Engine.PopGuiPageCB({ + Engine.PopGuiPage({ "page": g_TermsPage, "accepted": accepted }); diff --git a/binaries/data/mods/public/gui/aiconfig/aiconfig.js b/binaries/data/mods/public/gui/aiconfig/aiconfig.js index 9d44575564..5a3bb81d4f 100644 --- a/binaries/data/mods/public/gui/aiconfig/aiconfig.js +++ b/binaries/data/mods/public/gui/aiconfig/aiconfig.js @@ -69,10 +69,7 @@ function checkBehavior() function returnAI(save = true) { let idx = Engine.GetGUIObjectByName("aiSelection").selected; - - // Pop the page before calling the callback, so the callback runs - // in the parent GUI page's context - Engine.PopGuiPageCB({ + Engine.PopGuiPage({ "save": save, "id": g_AIDescriptions[idx].id, "name": g_AIDescriptions[idx].data.name, diff --git a/binaries/data/mods/public/gui/civinfo/civinfo.js b/binaries/data/mods/public/gui/civinfo/civinfo.js index f20d78012a..2dbc5d81ee 100644 --- a/binaries/data/mods/public/gui/civinfo/civinfo.js +++ b/binaries/data/mods/public/gui/civinfo/civinfo.js @@ -3,11 +3,6 @@ */ const g_CivData = loadCivData(true, false); -/** - * Callback function name on closing gui via Engine.PopGuiPage(). - */ -var g_Callback = ""; - var g_SelectedCiv = ""; /** @@ -15,9 +10,6 @@ var g_SelectedCiv = ""; */ function init(data = {}) { - if (data.callback) - g_Callback = data.callback; - var civList = Object.keys(g_CivData).map(civ => ({ "name": g_CivData[civ].Name, "code": civ })).sort(sortNameIgnoreCase); var civSelection = Engine.GetGUIObjectByName("civSelection"); @@ -94,16 +86,12 @@ function subHeading(obj) function switchToStrucTreePage() { - Engine.PopGuiPage(); - Engine.PushGuiPage("page_structree.xml", { "civ": g_SelectedCiv, "callback": g_Callback }); + Engine.PopGuiPage({ "civ": g_SelectedCiv, "nextPage": "page_structree.xml" }); } function closePage() { - if (g_Callback) - Engine.PopGuiPageCB({ "civ": g_SelectedCiv, "page": "page_civinfo.xml" }); - else - Engine.PopGuiPage(); + Engine.PopGuiPage({ "civ": g_SelectedCiv, "page": "page_civinfo.xml" }); } /** diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js index 1567bf68c3..a3953cd6ec 100644 --- a/binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -22,7 +22,7 @@ const g_CivData = loadCivData(false, false); * Store civilization code and page (structree or history) opened in civilization info. */ var g_CivInfo = { - "code": "", + "civ": "", "page": "page_civinfo.xml" }; @@ -1047,10 +1047,10 @@ var g_MiscControls = { "hotkey_structree": colorizeHotkey("%(hotkey)s", "structree") }), "onPress": () => function() { - Engine.PushGuiPage(g_CivInfo.page, { - "civ": g_CivInfo.code, - "callback": "storeCivInfoPage" - }); + Engine.PushGuiPage( + g_CivInfo.page, + { "civ": g_CivInfo.civ }, + storeCivInfoPage); } }, "civResetButton": { @@ -2423,30 +2423,26 @@ function openAIConfig(playerSlot) { g_LastViewedAIPlayer = playerSlot; - Engine.PushGuiPage("page_aiconfig.xml", { - "callback": "AIConfigCallback", - "playerSlot": playerSlot, - "id": g_GameAttributes.settings.PlayerData[playerSlot].AI, - "difficulty": g_GameAttributes.settings.PlayerData[playerSlot].AIDiff, - "behavior": g_GameAttributes.settings.PlayerData[playerSlot].AIBehavior - }); -} + Engine.PushGuiPage( + "page_aiconfig.xml", + { + "playerSlot": playerSlot, + "id": g_GameAttributes.settings.PlayerData[playerSlot].AI, + "difficulty": g_GameAttributes.settings.PlayerData[playerSlot].AIDiff, + "behavior": g_GameAttributes.settings.PlayerData[playerSlot].AIBehavior + }, + ai => { + g_LastViewedAIPlayer = -1; -/** - * Called after closing the dialog. - */ -function AIConfigCallback(ai) -{ - g_LastViewedAIPlayer = -1; + if (!ai.save || !g_IsController) + return; - if (!ai.save || !g_IsController) - return; + g_GameAttributes.settings.PlayerData[ai.playerSlot].AI = ai.id; + g_GameAttributes.settings.PlayerData[ai.playerSlot].AIDiff = ai.difficulty; + g_GameAttributes.settings.PlayerData[ai.playerSlot].AIBehavior = ai.behavior; - g_GameAttributes.settings.PlayerData[ai.playerSlot].AI = ai.id; - g_GameAttributes.settings.PlayerData[ai.playerSlot].AIDiff = ai.difficulty; - g_GameAttributes.settings.PlayerData[ai.playerSlot].AIBehavior = ai.behavior; - - updateGameAttributes(); + updateGameAttributes(); + }); } function reloadPlayerAssignmentChoices() @@ -2775,6 +2771,11 @@ function updateAutocompleteEntries() function storeCivInfoPage(data) { - g_CivInfo.code = data.civ; - g_CivInfo.page = data.page; + if (data.nextPage) + Engine.PushGuiPage( + data.nextPage, + { "civ": data.civ }, + storeCivInfoPage); + else + g_CivInfo = data; } diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.xml b/binaries/data/mods/public/gui/gamesetup/gamesetup.xml index 5b3aeee277..5c3538b3b3 100644 --- a/binaries/data/mods/public/gui/gamesetup/gamesetup.xml +++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.xml @@ -6,15 +6,11 @@