Lore archive · Warcraft Wiki, 2023 dump
Creating simple pop-up dialog boxes
Last wiki revision 2021-08-02
Static popups are simple dialog boxes seen with logging off, accepting summons, sending money through the mail, renaming a pet, and so forth. This tutorial describes using StaticPopup code to insert simple dialogs to an addon.
handles all of the basic UI elements (positioning, sound effects, layout).
New dialogs are created by adding an entry to the global table, and populating the entry with required and optional information. Here is a simple two-button entry:
The index into the array is an arbitrary string, but it should be unique within the array. Many elements in this example are optional, but have customary uses suitable for most addons.
To display the dialog, call with the name of the entry. This function returns a reference to the static popup frame, or nil if unsuccessful (i.e. if four simultaneous static popups are already shown).
Usually the dialog will be configured to hide itself (pressing a button, pressing escape or after a timeout), but this may also be done programmatically with. Different addons may have concurrent popups, so it is necessary to supply arguments indicating which entry to hide.
For a simple popup in any language, use YES, NO, ACCEPT, CANCEL, DELETE, OKAY, or CONTINUE on button labels; and CONFIRM_CONTINUE for text ("Do you wish to continue?").
- OnAccept - This function can take up to two arguments, both optional. They are for passing arbitrary data around the callbacks. In general this is used with dialogs that have an editable text field, to pass the entered text back to the function; also for chaining dialog boxes together. For details, see "Passing arguments to local functions" below.
- OnCancel - This function can take up to three arguments, all optional. The first and second are used the same way as the first parameter in OnAccept (whatever that may actually be). The third is a string describing the reason the popup was cancelled; the game will pass this as required:
- "override" - Another popup cancelled this one, or is set to 'exclusive' (see below), or the player is dead or logging out.
- "timeout" - The popup's entry specified a nonzero timeout field, and the time expired.
- "clicked" - The player clicked button2, or hit the escape key and hideOnEscape is set.
The text field of an entry can contain formatting placeholders. When the popup is actually displayed, the calling function can pass two additional arguments to. The text field and these two arguments will be passed through the format function before being added to the dialog.
For example, the default guild invitation popup sets, and the display call is to.
To add a editbox in the popup set the hasEditBox option field to true. The EditBox gets the name "$parentEditBox", relative to the Popup, and is also available in the popup's .editBox field. (Recall that the popup dialog is the value returned from the StaticPopup_Show function.) To get and set the value of the EditBox use the following code:
OnShow = function (self, data) self.editBox:SetText("Some text goes here") end, OnAccept = function (self, data, data2) local text = self.editBox:GetText -- do whatever you want with it end, hasEditBox = true
More complicated usage might be to use OnShow to call (graying out the Accept button), and then including the following in your options table to allow the Accept button to be clicked as soon as the user types something in the text field:
EditBoxOnTextChanged = function (self, data) -- careful! 'self' here points to the editbox, not the dialog self:GetParent.button1:Enable -- self:GetParent is the dialog end
Using hasEditBox/.editBox causes a small one-line text field to appear. By default this is 130 pixels wide; you can set the optional editBoxWidth key to change the width. (There used to be a hasWideEditBox boolean key that would create a .wideEditBox field in the dialog; in Cataclysm these were replaced by a editBoxWidth of 260 to 350.) The editbox will respect the maxLetters field if you set it (most editbox popups used by Blizzard set this to 24 or 31).
It is possible, though not immediately obvious how, to pass arbitrary user data to the local functions (e.g. OnAccept, OnCancel). Write your local function like this:
OnAccept = function (self, data, data2) DoSomethingWith(data) end
And make the call like this:
varName = "Some value" -- This is the data you want to use in OnAccept varName2 = "Some other value" -- This is the data you want to use in OnAccept local dialog = StaticPopup_Show("YOUR_POPUP") -- dialog contains the frame object if (dialog) then dialog.data = varName -- set the frame's data field to the value you want dialog.data2 = varName2 end
The dialog's fields "data" and "data2" are passed as additional arguments to OnAccept. The "data" field is passed to OnCancel and OnAlt (the function called if button3 is set), but not "data2". They are also accessible through the dialog itself, as self.data and self.data2. In this example they are strings, but they can be of any type including tables.
Notice that you are actually setting the frame's data after you have called StaticPopup_Show. This works because popping up a dialog box does not halt script execution. The dialog box isn't even visible to the player until after the current script execution cycle completes. By the time the player clicks a button to run OnAccept/OnCancel/etc, all of this code will have long since finished.
If you need to manipulate any of the dialog's visual elements, most of them are directly accessible as table fields of the dialog, so you do not need to use an expensive sequence of getglobal(self:GetName.."Something"). For example, dialog.button1 points to the first button. See the StaticPopup.xml file's various OnLoad sections for the full list.
- Creating a static popup with an editbox and only one button will cause the button and the editbox to overlap. Having more than one button will get the desired behavior. (Tested on 2.4.1)
- While creating your popup entries, you will probably be doing a lot of UI reloading. Extract the file from the default UI, copy it into your addon's folder, and add it to your .toc file. This has two effects: it starts verbose logging into FrameXML.log, and it adds a "Reload UI" button to your screen. Very handy timesaver. :-)
- Added by Layrajha: The OnHide function will always be called after OnAccept or OnCancel have finished their execution. Therefore, it is safe to assume that your changes done in OnAccept or OnCancel will be done when OnHide is called. Also note that you can prevent the popup from hiding after clicking the "Accept" button: just make the OnAccept function return "true" (or anything different from "nil" and "false", it will work just as well).
As an example, consider the pre WoW 1.11.0 "Ready Check" from CT_RaidAssist, which pops up a two-button dialog box with a 30-second timeout. The CT authors implemented everything from scratch: 107 lines of XML specifying window, field, and button sizes, plus a couple lines of Lua here and there. It could be replaced with something like the following:
StaticPopupDialogs["EXAMPLE_CTRA_READY"] = { text = "%s has performed a ready check. Are you ready?", -- YES, NO, ACCEPT, CANCEL, etc, are global WoW variables containing localized -- strings, and should be used wherever possible. button1 = YES, button2 = NO, OnAccept = function CT_RA_SendReady end, OnCancel = function (_,_, reason) if reason == "timeout" or reason == "clicked" then CT_RA_SendNotReady else -- "override" ...? end; end, sound = "levelup2", timeout = 30, whileDead = true, hideOnEscape = true, }
and called via
StaticPopup_Show ("EXAMPLE_CTRA_READY", CT_RA_CheckReady_Person)
(Note: the above was written before the 1.11 game patch added a builtin ready check. While ready checks no longer need to be implemented by addon authors, the example is simple enough to remain here.)
Categories
- HOWTOs
Source
https://warcraft.wiki.gg/wiki/Creating_simple_pop-up_dialog_boxes · retrieved 2023-11-13 · CC BY-SA 4.0
Converted from wikitext with templates, tables and images removed, so some sentences may be missing values.
This archive predates WoW: Forever. For collected gameplay facts see the Forever database. Search the archive.