Wowpedia

We have moved to Warcraft Wiki. Click here for information and the new URL.

READ MORE

Wowpedia
Tag: WoW API docs
(16 intermediate revisions by 12 users not shown)
Line 1: Line 1:
{{tocright}}
+
{{uitech}}
[[World of Warcraft]] has a fairly powerful layout engine for creating [[user interface]]s. When combined with [[lua]] for attaching behaviours to UI elements, this creates a flexible system with which the game's entire UI is created, as well as any custom [[AddOns]].
 
   
  +
[[World of Warcraft]] has two approaches for addons to build a [[user interface]]: '''XML''' predefines a layout for [[widgets]] on the screen, and [[Lua]] executes code while the game is playing. These approaches are complementary because Lua can manipulate widgets that were predefined in XML.
This page started as a braindump of various aspects of the XML engine and API; over time, it has become a more useful reference, though it is still far from complete.
 
For more information on creating AddOns, see [[AddOns]], [[Interface Customization]], [[World of Warcraft API]] and especially the [[Widget API]] which describes the programming aspects of all XML objects.
 
   
  +
Until [[patch 1.10.0]], [[Wowpedia:Interface customization|interface customization]] was only possible using this combination of XML and Lua. Functions such as {{api|CreateFrame()}} have since enabled Lua to assert a more prominent role, but the XML schema remains an accepted -- and regularly updated -- approach for both custom [[AddOns]] and Blizzard's own default UI.
Note that this assumes familiarity with XML; for a quick introduction, see [http://www.xmlfiles.com/xml/xml_intro.asp this XML Introduction at xmlfiles.com]. Also note that the XML declaration (<code>&lt;?xml version="1.0"?&gt;</code>) may be omitted from UI .xml files.
 
   
  +
== Schema basics ==
Also note that as of version 1.10, all types of frames can also be created from LUA with the new [[API CreateFrame|CreateFrame()]] API.
 
  +
:''For an introduction to the XML language, see [https://en.wikipedia.org/wiki/XML Wikipedia] or [https://developer.mozilla.org/en-US/docs/Web/XML/XML_introduction Mozilla Developer Network]''
   
  +
WoW defines its own schema in [https://www.townlong-yak.com/framexml/latest/UI.xsd FrameXML/UI.xsd]. In general, this schema has four kinds of elements:
  +
:; Document root : Every file has {{api|t=x|Ui}} as its outer-most element, and everything else is contained inside it.
  +
:; Widgets : The {{api|t=o|UIObject}}s appearing on the screen, such as {{api|t=x|Frame}}, which may be placed inside the document root and are usually a kind of {{api|t=x|LayoutFrame}}.
  +
:; Properties : Customizations specific to each kind of widget, such as adding <code><Scripts></code> to a {{api|t=x|Frame}}.
  +
:; Children : Certain kinds of widgets may also be children of other widgets, such as adding a {{api|t=x|Texture}} to a {{api|t=x|Frame}}.
   
  +
A complete XML file might appear like the following:
== The Basics ==
 
  +
<syntaxhighlight lang="xml">
  +
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
  +
<Frame name="MyAddonFrame"> <!-- a sample widget -->
  +
<!-- sample properties and children -->
  +
<Scripts>
  +
<OnLoad script="MyAddonFrame_OnLoad" />
  +
</Scripts>
  +
<Layers>
  +
<Layer level="ARTWORK">
  +
<Texture name="MyAddonFrameTexture" />
  +
</Layer>
  +
</Layers>
  +
</Frame> <!-- end of sample widget -->
  +
</Ui>
  +
</syntaxhighlight>
   
  +
Malformed XML will generate an error when logging in or reloading the game client. There are also online validators available with [https://validator.w3.org/ W3 Org] or [http://dev.averageurl.com/wow/xml Average URL] that can perform this task without running the game.
An [[XML]] file is a collection of ''elements'' (with a start and end tag), of which the User Interface files are no exception. There are two main types of elements that appear in the UI XML files. The first type are those that declare user interface items (or [[widgets]]), such as [[Buttons]], [[Frames]], [[Checkboxes]]. We will call these [[widget]] elements. The second type of elements, which always occur inside the first type, define properties and behaviour of the widgets. We will call these property elements. Here is an example:
 
   
  +
== Managing Widgets ==
<Button name="MyAddon_Button">
 
  +
{{api|t=x|LayoutFrame}} is an abstract type defining basic rules for most widgets, but typically addons will create specific kinds such as a {{api|t=x|Frame}}. These widgets have many common attributes, described in this section.
<Anchors>
 
<Anchor point="CENTER"/>
 
</Anchors>
 
</Button>
 
   
  +
=== Parent ===
The [[Button]] element is of the first type, in other words a [[widget]] element. Its appearance in the XML file causes a Button with the name '''MyAddon_Button''' to be created. The elements inside it (such as [[Anchors]], Anchor) define its properties, hence are of the second type. The general structure is always the same, you have elements representing widgets, and other elements inside them representing their properties. It can also happen that a widget element is inside another one. For example:
 
  +
Widgets have a {{api|t=w|UIObject:GetParent|parent}} if they are contained inside another widget, or if explicitly set using the parent attribute, <code>{{api|t=x|LayoutFrame parent.}}</code>. The latter approach is useful to add features to the existing UI, such as adding a button to the WorldMapFrame.
  +
<syntaxhighlight lang="xml">
  +
<Button name="WorldMapFrame_MyAddonButton" parent="WorldMapFrame">
  +
</Button>
  +
</syntaxhighlight>
   
  +
=== Name ===
<Frame name="MyAddon_Frame">
 
  +
Every widget can have a {{api|t=w|UIObject:GetName|name}}, which creates a global variable for referencing it from Lua during runtime. To prevent collisions, this name should truly be unique across all AddOns.
<Anchors>
 
<Anchor point="CENTER"/>
 
</Anchors>
 
<Frames>
 
<Button name="MyAddon_Button">
 
<Anchors>
 
<Anchor point="CENTER"/>
 
</Anchors>
 
</Button>
 
</Frames>
 
</Frame>
 
   
  +
The ''$parent'' keyword incorporates the name from a parent widget, so the button below becomes "MyAddonFrameButton".
This example has two [[widget]] elements ([[Frame]] and [[Button]]), and several property elements ([[Anchors]], Anchor). This creates a Frame, with a Button inside it. Here, '''MyAddon_Button''' is a ''child'' of '''MyAddon_Frame''', and '''MyAddon_Frame''' is a ''parent'' of '''MyAddon_Button'''. Also note how the XML convention of abbreviating an empty element such as <Anchor point="CENTER"></Anchor> as <Anchor point="CENTER"/> is used.
 
  +
<syntaxhighlight lang="xml">
  +
<Frame name="MyAddonFrame">
  +
<Frames>
  +
<Button name="$parentButton">
  +
</Button>
  +
</Frames>
  +
</Frame>
  +
</syntaxhighlight>
   
  +
In Lua, the button is manipulable using this global name. For example: <code>MyAddonFrameButton:[[API Button Disable|Disable()]]</code>.
Many of the elements (widget and property alike) can have ''attributes'', such as the '''name''' attribute in the above examples.
 
 
A complete and valid XML file must contain exactly one element named UI, with some rather long attributes (best use copy/paste for this). Hence a minimal example of a complete UI XML file would be something like:
 
 
<Ui xmlns="<nowiki>http://www.blizzard.com/wow/ui/</nowiki>"
 
xmlns:xsi="<nowiki>http://www.w3.org/2001/XMLSchema-instance</nowiki>"
 
xsi:schemaLocation="<nowiki>http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd</nowiki>">
 
<Frame name="MyAddon_Frame">
 
</Frame>
 
</Ui>
 
 
Such a file will create a single [[Frame]], named '''MyAddon_Frame'''. However, that Frame wouldn't be visible and wouldn't have any content.
 
 
== Validation with XSD ==
 
 
If you use the Blizzard Interface Customization tool to extract the contents of the Interface\FrameXML folder, you will come across the file UI.xsd which provides a schema definition for automated validation of your customized XML-files. Notice that [http://www.w3.org/XML/Schema XSD] is an advanced XML feature and requires a special editor as well as a good knowledge of advanced XML-concepts. If you've already worked with XML you might find this very helpful to get started with WoW.
 
 
There is also an [http://dev.averageurl.com/wow/xml/ online validator] available, which will take any XML you throw at it and check it against Blizzard's schema definitions. Unfortunately, it is not much use as a "getting started" reference, but rather it is much more useful to check what is going wrong should you lack access to the heavier tools that support XML editing with XSD support natively. Further, due to the way that the XSD was designed, it can some times throw errors which are not actually a problem. Be sure to check the [http://dev.averageurl.com/wow/xml/faq/ FAQ] for more information.
 
 
== Naming Widgets ==
 
 
Every widget element may have the '''name''' attribute. If an element has a name, it causes a global Lua variable to be created with that name. This variable can then be used to call API methods on that widget. (See [[Widget API]] for a list of methods available for the different UI widgets.) Note that global variables are truly global across the entire UI, meaning that every name must be unique across all XML files.
 
 
Here is an example. Let's say in your XML file you have a section like this:
 
 
<Frame name="MyAddon_Frame">
 
..
 
<Frames>
 
<Button name="MyAddon_Button">
 
..
 
</Button>
 
</Frames>
 
</Frame>
 
 
In any Lua code then you can use the variable MyAddon_Frame to refer to the frame and MyAddon_Button to refer to the button. For example, to show the frame, call MyAddon_Frame:[[API LayoutFrame Show|Show()]]. Or to disable the button, call MyAddon_Button:[[API Button Disable|Disable]]().
 
 
When defining the name of a widget, the special string '''$parent''' may be used. This will take on the name of whatever the parent of that widget is. For example:
 
 
<Frame name="MyAddon_Frame">
 
..
 
<Frames>
 
<Button name="$parent_Button">
 
..
 
</Button>
 
</Frames>
 
</Frame>
 
 
This results in two global Lua variables: MyAddon_Frame and MyAddon_Frame_Button.
 
 
== Managing Frames ==
 
 
''Note:'' A lot of this section applies to all user interface [[widgets]], not just [[Frames]]. Properties for layout, sizing and so on are common to all widgets.
 
   
 
=== Layout ===
 
=== Layout ===
  +
LayoutFrames are generally a rectangular {{api|t=o|Region}} on the screen, defined by [[anchors]] and sizes. To be {{api|t=w|Region:IsRectValid|valid}}, there must be sufficient non-contradictory information to compute its position and size. In XML, these are specified using <code>Size</code> and <code>Anchors</code>.
   
  +
A 100x100 frame anchored to its parent's top-left corner:
Frames have a combination of a size and one or more [[anchors]]. For a [[frame]] to be laid out, the combination of these needs to define a rectangle on the screen in which the frame is to be laid out.
 
  +
<syntaxhighlight lang="xml">
  +
<Frame name="MyAddonFrame">
  +
<Size>
  +
<AbsDimension x="100" y="100" />
  +
</Size>
  +
<Anchors>
  +
<Anchor point="TOPLEFT" />
  +
</Anchors>
  +
</Frame>
  +
</syntaxhighlight>
   
  +
A frame centered on its parent, covering a quarter of the screen regardless of resolution:
A size is specified using a <tt>Size</tt> element with either an <tt>AbsDimension</tt> or <tt>RelDimension</tt> child element.
 
  +
<syntaxhighlight lang="xml">
  +
<Frame name="MyAddonFrame">
  +
<Size>
  +
<RelDimension x="0.5" y="0.5" />
  +
</Size>
  +
<Anchors>
  +
<Anchor point="CENTER" />
  +
</Anchors>
  +
</Frame>
  +
</syntaxhighlight>
   
  +
See {{api|t=w|Region:SetPoint()}} and {{api|t=w|Region:SetSize()}} for additional details.
[[Anchors]] allow for relative positioning, and also to allow [[frames]] to dynamically reposition their content based on resizing. A group of anchors is expressed via an <tt>Anchors</tt> element with one or more <tt>Anchor</tt> children, each of which may have an <tt>Offset</tt>.
 
 
Some examples: ''TODO: Get screenshots of all of these''
 
 
<Frame>
 
<Size><AbsDimension x="100" y="100"/></Size>
 
<Anchors>
 
<Anchor point="TOPLEFT"/>
 
</Anchors>
 
</Frame>
 
 
This specifies a 100x100 [[frame]] anchored so that its top left is at the top left of its parent frame.
 
 
<Frame>
 
<Size><RelDimension x="0.5" y="0.5"/> </Size>
 
<Anchors>
 
<Anchor point="LEFT"/>
 
</Anchors>
 
</Frame>
 
 
This specifies a [[frame]] that covers a quarter of your [[UI]] (regardless to the selected resolution).
 
 
<Frame>
 
<Size><AbsDimension x="100" y="100"/></Size>
 
<Anchors>
 
<Anchor point="TOPLEFT" relativePoint="TOPRIGHT"/>
 
</Anchors>
 
</Frame>
 
 
This specifies a 100x100 [[frame]] [[anchored]] so that its top left is at the top right of its [[parent]] frame.
 
 
<Frame>
 
<Size><AbsDimension x="100" y="100"/></Size>
 
<Anchors>
 
<Anchor point="TOPLEFT" relativeTo="SomeOtherFrame">
 
<Offset><AbsDimension x="10" y="-10"/></Offset>
 
</Anchor>
 
</Anchors>
 
</Frame>
 
 
This specifies a 100x100 frame anchored at the top left of the frame <tt>SomeOtherFrame</tt>, and offset by 10 pixels to the right and 10 pixels down. (Note that the Y axis increases from the bottom up, so negative Y coordinates indicate downwards movement).
 
 
<Frame>
 
<Anchors>
 
<Anchor point="TOPLEFT" relativeTo="SomeOtherFrame">
 
<Offset><AbsDimension x="5" y="-5"/></Offset>
 
</Anchor>
 
<Anchor point="BOTTOMRIGHT" relativeTo="SomeOtherFrame">
 
<Offset><AbsDimension x="-5" y="5"/></Offset>
 
</Anchor>
 
</Anchors>
 
</Frame>
 
 
Note that no <tt>Size</tt> is specified here; the size and location of this frame is defined entirely by its relationship to <tt>SomeOtherFrame</tt>. In particular, it will be inset by 5 pixels from the top left and bottom right of <tt>SomeOtherFrame</tt>. As <tt>SomeOtherFrame</tt> changes size, our frame will change size as well.
 
   
 
=== Showing/Hiding ===
 
=== Showing/Hiding ===
  +
LayoutFrames default to a visible state unless one sets the hidden attribute, <code>{{api|t=x|LayoutFrame hidden.true}}</code>. In Lua, toggle this state using {{api|t=w|Region:SetShown()}}.
 
Frames may be shown or hidden by [[API LayoutFrame Hide|''FrameName'':Hide()]] and [[API LayoutFrame Show|''FrameName'':Show()]]. Also available are [[API ShowUIPanel|ShowUIPanel(''FrameName'')]] and [[API HideUIPanel|HideUIPanel(''FrameName'')]].
 
   
 
=== Layers and Textures ===
 
=== Layers and Textures ===
  +
Certain widgets exist only within the <code>Layers</code> part of a {{api|t=x|Frame}} to render potentially-overlapping text or texture (graphics) inside that Frame. There are five [[layer]]s, in order from furthest-back to forward:
There are 3 levels of [[layers]]: BACKGROUND is in the back, ARTWORK is in the middle and OVERLAY is in front. If you want to be sure that a object is before another, you must specify the level where you want to place it.
 
  +
* BACKGROUND - Place background textures here, to sit behind everything else.
  +
* BORDER - Place border textures here, to cover the background but sit behind the foreground.
  +
* ARTWORK - Place forground textures here, in front of backgrounds and borders (if overlapping).
  +
* OVERLAY - Place your text and interactive elements in this level to ensure visibility.
  +
* HIGHLIGHT - Additional level with [[layer#Details|special optional behaviour]].
   
  +
<syntaxhighlight lang="xml">
BACKGROUND - Level 0. Place the background of your frame here.<BR />
 
  +
<Frame>
BORDER - Level 1. Place the artwork of your frame here .<BR />
 
  +
<Layers>
ARTWORK - Level 2. Place the artwork of your frame here.<BR />
 
  +
<Layer level="BACKGROUND">
OVERLAY - Level 3. Place your text, objects, and buttons in this level<BR />
 
  +
<Texture />
HIGHLIGHT - Level 4. Place your text, objects, and buttons in this level<BR />
 
  +
</Layer>
*Elements in the '''HIGHLIGHT''' Layer are '''automatically shown or hidden''' when the mouse enters or leaves!
 
  +
<Layer level="OVERLAY">
*For Highlighting to work you need '''enableMouse="true"''' in your ''<Frame>'' attributes.
 
  +
<FontString />
  +
</Layer>
  +
</Layers>
  +
</Frame>
  +
</syntaxhighlight>
   
  +
=== Templates ===
  +
Templates define a common layout for reuse in many widgets. Widgets inheriting from a template will share the same properties, children, and attributes unless explicitly overwritten.
   
  +
Templates in XML:
''Note: The above are capitalized for a reason. See example:''<BR />
 
  +
* Reside in the document root, even if they are a kind of widget that is often a child of another.
  +
* Have the virtual property set to true, <code>{{api|t=x|LayoutFrame virtual.true}}</code>.
  +
* Have a unique global name, which shouldn't use the ''$parent'' keyword because it has no parents.
  +
* May have other widgets as children, but if those widgets have global names then the ''$parent'' keyword should be used to prevent collisions between each reuse of the template.
   
  +
Widgets inheriting the templates:
<Layers>
 
  +
* Reside in their usual locations within the XML file (either the document root or inside certain other kinds of widgets).
<Layer level="BACKGROUND">
 
  +
* Have the inherits property set to the name of the template, <code>{{api|t=x|LayoutFrame inherits.MyTemplate}}</code>.
...
 
  +
* May have a unique global name -- ''should'' have a unique name if the template has children using the ''$parent'' keyword.
</Layer>
 
<Layer level="ARTWORK">
 
...
 
</Layer>
 
<Layer level="OVERLAY">
 
...
 
</Layer>
 
</Layers>
 
   
  +
<syntaxhighlight lang="xml">
=== Using Templates ===
 
  +
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
Templates are used when you want to create a common layout for several frames. In this way you can save on the amount of code needed to recreate each frame, as the frames will automatically take on the properties, children, and attributes from whatever template it inherits. There are several rules that must be following when initially creating the template:
 
  +
<Button name="MyAddonButtonTemplate" virtual="true">
<ul><li>Templates are created at the root of the file. Meaning that you cannot have a template that is a child of another element</li><li>Templates must have their virtual attributes set to true</li><li>Templates must have a name, and it cannot use the $parent keyword</li><li>Children of a template do not need to be named, but when doing so, you should use the $parent keyword</li></ul><br/>
 
  +
<Size>
As discussed above, there is a special keyword that can be used when naming something inside the template. When you inherit a frame, any object inside the template that is inherited, which has the keyword $parent, will automatically replace the keyword with the name of the parent which inherited the template. Example:
 
  +
<AbsDimension x="40" y="22" />
 
  +
</Size>
<Button name="MyAddonButtonTemplate" parent="UIParent" virtual="true">
 
<ButtonText name="$parentText"/>
+
<ButtonText name="$parentText" />
</Button>
+
</Button>
<Button name="MyAddonSpecialButton" inherits="MyAddonButtonTemplate">
+
<Button inherits="MyAddonButtonTemplate" name="MyButton1" />
  +
</Ui>
<Size><AbsDimension x="40" y="22"/></Size>
 
  +
</syntaxhighlight>
</Button>
 
 
Is the same as doing:
 
 
<Button name="MyAddonSpecialButton" parent="UIParent">
 
<Size><AbsDimension x="40" y="22"/></Size>
 
<ButtonText name="MyAddonSpecialButtonText"/>
 
</Button>
 
 
Be aware that any inherited attributes, properties, or children can also be overridden. Example:
 
 
<Button name="MyAddonButtonTemplate" parent="UIParent" movable="true" virtual="true">
 
<ButtonText name="$parentText"/>
 
</Button>
 
<Button name="MyAddonSpecialButton" inherits="MyAddonButtonTemplate" movable="false">
 
<Size><AbsDimension x="40" y="22"/></Size>
 
</Button>
 
 
Is the same as doing:
 
 
<Button name="MyAddonSpecialButton" parent="UIParent" movable="false">
 
<Size><AbsDimension x="40" y="22"/></Size>
 
<ButtonText name="MyAddonSpecialButtonText"/>
 
</Button>
 
 
Templates can inherit other templates as well. When done in this way, any $parent keywords used in the template being inherited carry over to the template that inherits it. Example:
 
 
<Button name="MyAddonButtonTemplate1" parent="UIParent" movable="true" virtual="true">
 
<ButtonText name="$parentText"/>
 
</Button>
 
<Button name="MyAddonButtonTemplate2" clampedToScreen="true" inherits="MyAddonButtonTemplate1" virtual="true">
 
<NormalFont inherits="GameFontNormal"/>
 
</Button>
 
<Button name="MyAddonSpecialButton" inherits="MyAddonButtonTemplate2">
 
<Size><AbsDimension x="40" y="22"/></Size>
 
</Button>
 
 
Is the same as doing:
 
 
<Button name="MyAddonSpecialButton" parent="UIParent" clampedToScreen="true" movable="true">
 
<Size><AbsDimension x="40" y="22"/></Size>
 
<ButtonText name="MyAddonSpecialButtonText"/>
 
<NormalFont inherits="GameFontNormal"/>
 
<HighlightFont inherits="GameFontHighlight"/>
 
</Button>
 
   
 
== Scripts ==
 
== Scripts ==
Line 316: Line 216:
 
== Widget Elements ==
 
== Widget Elements ==
   
  +
Moved to [[XML elements]].
''Most of the information here is extracted from UI.xsd. It is by no means complete, and can change any time.''
 
   
  +
== Default User Interface ==
Widget elements have a hierarchical relationship between them. Some widget elements are derived from others, which means that they inherit the kind of attributes and property elements that are allowed for them. This inheritance also applies to the API functions available for that type of widget.
 
   
  +
The default user interface that is visible without any installed third-party addons is built into the MPQ files. It can't be modified because it is protected by a digital signature, but [[Viewing Blizzard's interface code|the files can be extracted]] to see how the interface works.
'''Note''': This hierarchy is not to be confused with the parent-child relationship of the concrete widgets created in the XML files. It also shouldn't be confused with inheriting templates (or virtual elements).
 
   
This list shows the inheritance relationship of the widget elements:
 
 
* [[#UI|UI]]
 
* [[#LayoutFrame|LayoutFrame]]
 
** [[#FontString|FontString]]
 
** [[#Texture|Texture]]
 
** [[#Frame|Frame]]
 
*** [[#Button|Button]]
 
**** [[#CheckButton|CheckButton]]
 
**** [[#LootButton|LootButton]]
 
*** [[#ColorSelect|ColorSelect]]
 
*** [[#EditBox|EditBox]]
 
*** [[#GameTooltip|GameTooltip]]
 
*** [[#MessageFrame|MessageFrame]]
 
*** [[#Minimap|Minimap]]
 
*** [[#Model|Model]]
 
**** [[#PlayerModel|PlayerModel]]
 
***** [[#TabardModel|TabardModel]]
 
*** [[#ScrollingMessageFrame|ScrollingMessageFrame]]
 
*** [[#ScrollFrame|ScrollFrame]]
 
*** [[#SimpleHTML|SimpleHTML]]
 
*** [[#Slider|Slider]]
 
*** [[#StatusBar|StatusBar]]
 
*** [[#MovieFrame|MovieFrame]]
 
*** [[#TaxiRouteFrame|TaxiRouteFrame]]
 
*** [[#WorldFrame|WorldFrame]]
 
 
In the XML files, wherever a widget element is expected, you may instead use a widget that is derived from that one. In the reference below, curly braces {} are used to indicate when such substitution is possible.
 
 
=== UI ===
 
 
Elements: Include, Script, {[[#LayoutFrame|LayoutFrame]]}
 
 
=== LayoutFrame ===
 
 
Elements: Size, Anchors
 
 
Attributes: name, inherits, virtual, setAllPoints, hidden
 
 
=== Texture ===
 
 
Derived from: [[#LayoutFrame|LayoutFrame]]
 
 
Elements: TexCoords, [[XML/Color elements|Color]], Gradient
 
 
Attributes: file, [[XML/Texture/alphaMode|alphaMode]]
 
 
Note: The Texture must be within a ''[[XML_User_Interface#Layers_and_Textures|<Layer>]]''
 
 
Note #2: When adding custom textures remember that the ''file'' '''must''' have power-of-two dimensions, or else you'll end up with a solid green texture. For reference: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048... You can always cut off any excess size with TexCoords.
 
 
=== FontString ===
 
 
Derived from: [[#LayoutFrame|LayoutFrame]]
 
 
Elements: FontHeight, Color, Shadow
 
 
Attributes: font, bytes, text, spacing, outline, monochrome, nonspacewrap, justifyV, justifyH, maxLines, inherits
 
 
''The Fontstring element is used to display a text in the user interface. The text displayed by the Fontstring element can be changed with the LUA function <fontstringobject>:SetText() or read with the function <fontstringobject>:GetText().''
 
 
outline = "NORMAL" or "THICK", monochrome = "true" or "false", justifyV = "TOP", "MIDDLE" or "BOTTOM", justifyH = "LEFT", "RIGHT", "CENTER"
 
 
inherits can be set to an existing font. If set, the current FontString will take on all of that font's settings, unless overridden in the current FontString.
 
 
Note: ''<FontString>'' must be within a ''[[XML_User_Interface#Layers_and_Textures|<Layer>]], Attribute "font" needs to be set for element "FontHeight" to work''
 
 
:{{icon-shortcut}}'''See [{{wdnlink|FrameXML/Fonts.xml}} FrameXML/Fonts.xml]''' for the system default list of inheritable fonts!
 
 
Code: [[Widget_API#FontString|FontString Widget API]]
 
 
==== Example ====
 
 
<FontString name="$parentFontString" font="Fonts\FRIZQT__.TTF" text="Example Text" justifyH="LEFT" justifyV="TOP">
 
<Color r="1" g="0.8" b="1" a="1"/>
 
<FontHeight>
 
<AbsValue val="12"/>
 
</FontHeight>
 
<Anchors>
 
<Anchor point="TOPLEFT" relativeTo="$parent">
 
<Offset>
 
<AbsDimension x="20" y="-20"/>
 
</Offset>
 
</Anchor>
 
</Anchors>
 
<Shadow>
 
<offset>
 
<AbsDimension x="1" y="1"/>
 
</offset>
 
<color r="0" g="0" b="0"/>
 
</Shadow>
 
</FontString>
 
 
 
 
=== Frame ===
 
 
Derived from: [[#LayoutFrame|LayoutFrame]]
 
 
Elements: [[XML/Frame/TitleRegion|TitleRegion]], ResizeBounds, [[XML/Frame/Backdrop|BackDrop]], [[XML/Frame/HitRectInsets|HitRectInsets]], Layers, Frames, Scripts, [[XML/Frame/BackDrop/BackgroundInsets|BackgroundInsets]]
 
 
Attributes: [[XML/Frame/alpha|alpha]], parent, [[XML/Frame/toplevel|toplevel]], movable, resizable, [[XML/Frame/frameStrata|frameStrata]], [[XML/Frame/frameLevel|frameLevel]], id, enableMouse, enableKeyboard
 
 
=== Button ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: NormalTexture, PushedTexture, DisabledTexture, HighlightTexture, [[XML/Button/NormalText|NormalText]], HighlightText, DisabledText, PushedTextOffset
 
 
Attributes: text
 
 
Notes: The various textures, once inherited or set to art of your choice, will automatically behave as expect. (highlight on mouseover, pushed while clicked, disabled when disabled) The same goes for the different texts.
 
 
==== Example ====
 
Included in [[XML/Frame/Backdrop|Backdrop]]
 
<Button name="$parentButtonClose" inherits="OptionsButtonTemplate" text="Close">
 
<Anchors>
 
<Anchor point="BOTTOMRIGHT">
 
<Offset>
 
<AbsDimension x="-12" y="16"/>
 
</Offset>
 
</Anchor>
 
</Anchors>
 
<Scripts>
 
<OnClick> autoInviteMainConfigFrame:Hide(); </OnClick>
 
</Scripts>
 
</Button>
 
 
[[Image:Close-button.jpg]]
 
 
=== CheckButton ===
 
 
Derived from: [[#Button|Button]]
 
 
Elements: CheckedTexture, DisabledCheckedTexture
 
 
Attributes: checked
 
 
Note: For checkbuttons, setting the label of the checkbutton works differently from normal buttons. Using MyCheckButton:SetText("monkey"); will not give you a visible result. Instead, you need to address the text property of the checkbuttons invisible FontString frame. The FontString frame is named "<checkButtonName>Text", so to address it, use the following lua code:
 
getglobal(MyCheckButton:GetName() .. "Text"):SetText("Monkey");
 
 
 
==== Example ====
 
Included in [[XML/Frame/Backdrop|Backdrop]]
 
<CheckButton name="$parentCheckButton" inherits="OptionsCheckButtonTemplate" checked="true">
 
<Anchors>
 
<Anchor point="LEFT">
 
<Offset>
 
<AbsDimension x="20" y="0"></AbsDimension>
 
</Offset>
 
</Anchor>
 
</Anchors>
 
</CheckButton>
 
 
[[Image:Checkbutton.jpg]]
 
 
=== StatusBar ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: BarTexture, BarColor
 
 
Attributes: [[XML/StatusBar/drawLayer|drawLayer]], minValue, maxValue, defaultValue
 
 
=== Slider ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: ThumbTexture
 
 
Attributes: drawLayer, minValue, maxValue, defaultValue, valueStep, orientation
 
 
=== EditBox ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: FontString, HighlightColor, TextInsets
 
 
Attributes: letters, blinkSpeed, numeric, password, multiLine, historyLines, autoFocus, ignoreArrows
 
 
==== Example ====
 
Included in [[XML/Frame/Backdrop|Backdrop]]
 
<EditBox name="$parentEditBox" letters="80">
 
<Size>
 
<AbsDimension x="100" y="32"></AbsDimension>
 
</Size>
 
<Anchors>
 
<Anchor point="LEFT">
 
<Offset>
 
<AbsDimension x="50" y="0"></AbsDimension>
 
</Offset>
 
</Anchor>
 
</Anchors>
 
<Layers>
 
<Layer level="BACKGROUND">
 
<Texture file="Interface\ChatFrame\UI-ChatInputBorder-Left">
 
<Size>
 
<AbsDimension x="75" y="32"></AbsDimension>
 
</Size>
 
<Anchors>
 
<Anchor point="LEFT">
 
<Offset>
 
<AbsDimension x="-10" y="0"></AbsDimension>
 
</Offset>
 
</Anchor>
 
</Anchors>
 
<TexCoords left="0" right="0.2" top="0" bottom="1.0"></TexCoords>
 
</Texture>
 
<Texture file="Interface\ChatFrame\UI-ChatInputBorder-Right">
 
<Size>
 
<AbsDimension x="75" y="32"></AbsDimension>
 
</Size>
 
<Anchors>
 
<Anchor point="RIGHT">
 
<Offset>
 
<AbsDimension x="10" y="0"></AbsDimension>
 
</Offset>
 
</Anchor>
 
</Anchors>
 
<TexCoords left="0.7" right="1.0" top="0" bottom="1.0"></TexCoords>
 
</Texture>
 
</Layer>
 
</Layers>
 
<Scripts>
 
<OnLoad></OnLoad>
 
</Scripts>
 
<FontString inherits="ChatFontNormal"></FontString>
 
</EditBox>
 
 
[[Image:Editbox.jpg]]
 
 
=== ColorSelect ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: ColorWheelTexture, ColorWheelThumbTexture, ColorValueTexture, ColorValueThumbTexture
 
 
==== Example ====
 
Included in [[XML/Frame/Backdrop|Backdrop]]
 
<ColorSelect name="$parentColorSelect" enableMouse="true">
 
<Size>
 
<AbsDimension x="100" y="100"></AbsDimension>
 
</Size>
 
<Anchors>
 
<Anchor point="LEFT">
 
<Offset>
 
<AbsDimension x="50" y="0"></AbsDimension>
 
</Offset>
 
</Anchor>
 
</Anchors>
 
<ColorWheelTexture></ColorWheelTexture>
 
</ColorSelect>
 
 
[[Image:Colorselect.jpg]]
 
 
=== Model ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: FogColor
 
 
Attributes: file, scale, fogNear, fogFar
 
 
=== SimpleHTML ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: FontString, FontStringHeader1, FontStringHeader2, FontStringHeader3
 
 
Attributes: files
 
 
=== MessageFrame ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: FontString, TextInsets
 
 
Attributes: fadeDuration, insertMode
 
 
=== ScrollingMessageFrame ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: FontString, TextInsets
 
 
Attributes: fade, fadeDuration, displayDuration, maxLines
 
 
=== ScrollFrame ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: ScrollChild
 
 
=== MovieFrame ===
 
 
Derived from: [[#Frame|Frame]]
 
 
=== GameTooltip ===
 
 
For a Lua pseudo code representation of the tooltip widget's methods, see [[Tooltip Pseudo Code]]
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: ?
 
 
Attributes: ?
 
 
=== TaxiRouteFrame ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: ?
 
 
Attributes: ?
 
 
=== LootButton ===
 
 
Derived from: [[#Button|Button]]
 
 
Elements: ?
 
 
Attributes: ?
 
 
=== TabardModel ===
 
 
Derived from: [[#PlayerModel|PlayerModel]]
 
 
Elements: ?
 
 
Attributes: ?
 
 
=== PlayerModel ===
 
 
Derived from: [[#Model|Model]]
 
 
Elements: ?
 
 
Attributes: ?
 
 
=== Minimap ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: ?
 
 
Attributes: ?
 
 
=== WorldFrame ===
 
 
Derived from: [[#Frame|Frame]]
 
 
Elements: ?
 
 
Attributes: ?
 
   
 
[[Category:Interface customization]]
 
[[Category:Interface customization]]
 
== Default User Interface ==
 
 
The default user interface that is visible without any installed third-party addons is built into the MPQ files. It can't be modified because it is protected by a digital signature, but using the [http://www.blizzard.com/support/wow/?id=aww01669p User Interface Customization tool] provided by Blizzard, the files can be extracted to see how the interface works.
 
 
== Widget Reference ==
 
 
I have not yet finished and probably will never since not all properties of elements used in default interface and addons not guarantee because patch changes rules from time to time. Still [[XML Basic|here]] is the reference for everything used in standart interface, with a new view on some of details of understanding schemes.
 
 
== External links ==
 
{{elink|site=wow&#91;"compares"&#93;.com|link=http://wowcompares.com/|desc= - a WoW interface .lua, .toc, and .xml viewer}}
 

Revision as of 16:43, 7 September 2020

World of Warcraft has two approaches for addons to build a user interface: XML predefines a layout for widgets on the screen, and Lua executes code while the game is playing. These approaches are complementary because Lua can manipulate widgets that were predefined in XML.

Until patch 1.10.0, interface customization was only possible using this combination of XML and Lua. Functions such as CreateFrame() have since enabled Lua to assert a more prominent role, but the XML schema remains an accepted -- and regularly updated -- approach for both custom AddOns and Blizzard's own default UI.

Schema basics

For an introduction to the XML language, see Wikipedia or Mozilla Developer Network

WoW defines its own schema in FrameXML/UI.xsd. In general, this schema has four kinds of elements:

Document root
Every file has <Ui> as its outer-most element, and everything else is contained inside it.
Widgets
The UIObjects appearing on the screen, such as <Frame>, which may be placed inside the document root and are usually a kind of <LayoutFrame>.
Properties
Customizations specific to each kind of widget, such as adding <Scripts> to a <Frame>.
Children
Certain kinds of widgets may also be children of other widgets, such as adding a <Texture> to a <Frame>.

A complete XML file might appear like the following:

<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
	<Frame name="MyAddonFrame">  <!-- a sample widget -->
		<!-- sample properties and children -->
		<Scripts>   
			<OnLoad script="MyAddonFrame_OnLoad" />
		</Scripts>
		<Layers>
			<Layer level="ARTWORK">
				<Texture name="MyAddonFrameTexture" />
			</Layer>
		</Layers>
	</Frame>  <!-- end of sample widget -->
</Ui>

Malformed XML will generate an error when logging in or reloading the game client. There are also online validators available with W3 Org or Average URL that can perform this task without running the game.

Managing Widgets

<LayoutFrame> is an abstract type defining basic rules for most widgets, but typically addons will create specific kinds such as a <Frame>. These widgets have many common attributes, described in this section.

Parent

Widgets have a parent if they are contained inside another widget, or if explicitly set using the parent attribute, <LayoutFrame parent="">. The latter approach is useful to add features to the existing UI, such as adding a button to the WorldMapFrame.

<Button name="WorldMapFrame_MyAddonButton" parent="WorldMapFrame">
</Button>

Name

Every widget can have a name, which creates a global variable for referencing it from Lua during runtime. To prevent collisions, this name should truly be unique across all AddOns.

The $parent keyword incorporates the name from a parent widget, so the button below becomes "MyAddonFrameButton".

<Frame name="MyAddonFrame">
	<Frames>
		<Button name="$parentButton">
		</Button>
	</Frames>
</Frame>

In Lua, the button is manipulable using this global name. For example: MyAddonFrameButton:Disable().

Layout

LayoutFrames are generally a rectangular Region on the screen, defined by anchors and sizes. To be valid, there must be sufficient non-contradictory information to compute its position and size. In XML, these are specified using Size and Anchors.

A 100x100 frame anchored to its parent's top-left corner:

<Frame name="MyAddonFrame">
	<Size>
		<AbsDimension x="100" y="100" />
	</Size>
	<Anchors>
		<Anchor point="TOPLEFT" />
	</Anchors>
</Frame>

A frame centered on its parent, covering a quarter of the screen regardless of resolution:

<Frame name="MyAddonFrame">
	<Size>
		<RelDimension x="0.5" y="0.5" />
	</Size>
	<Anchors>
		<Anchor point="CENTER" />
	</Anchors>
</Frame>

See Region:SetPoint() and Region:SetSize() for additional details.

Showing/Hiding

LayoutFrames default to a visible state unless one sets the hidden attribute, <LayoutFrame hidden="true">. In Lua, toggle this state using Region:SetShown().

Layers and Textures

Certain widgets exist only within the Layers part of a <Frame> to render potentially-overlapping text or texture (graphics) inside that Frame. There are five layers, in order from furthest-back to forward:

  • BACKGROUND - Place background textures here, to sit behind everything else.
  • BORDER - Place border textures here, to cover the background but sit behind the foreground.
  • ARTWORK - Place forground textures here, in front of backgrounds and borders (if overlapping).
  • OVERLAY - Place your text and interactive elements in this level to ensure visibility.
  • HIGHLIGHT - Additional level with special optional behaviour.
<Frame>
	<Layers>
   		<Layer level="BACKGROUND">
    			<Texture />
  		</Layer>
  		<Layer level="OVERLAY">
  			<FontString />
		</Layer>
 	</Layers>
</Frame>

Templates

Templates define a common layout for reuse in many widgets. Widgets inheriting from a template will share the same properties, children, and attributes unless explicitly overwritten.

Templates in XML:

  • Reside in the document root, even if they are a kind of widget that is often a child of another.
  • Have the virtual property set to true, <LayoutFrame virtual="true">.
  • Have a unique global name, which shouldn't use the $parent keyword because it has no parents.
  • May have other widgets as children, but if those widgets have global names then the $parent keyword should be used to prevent collisions between each reuse of the template.

Widgets inheriting the templates:

  • Reside in their usual locations within the XML file (either the document root or inside certain other kinds of widgets).
  • Have the inherits property set to the name of the template, <LayoutFrame inherits="MyTemplate">.
  • May have a unique global name -- should have a unique name if the template has children using the $parent keyword.
 <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
 	<Button name="MyAddonButtonTemplate" virtual="true">
 		<Size>
 			<AbsDimension x="40" y="22" />
 		</Size>
 		<ButtonText name="$parentText" />
 	</Button>
	<Button inherits="MyAddonButtonTemplate" name="MyButton1" />
</Ui>

Scripts

To attach behaviour to the UI elements defined in the XML files, you must use Lua. There are two methods of attaching Lua code to UI elements.

  • Short codes can go directly in the XML files in the appropriate event handler element (see later).
  • Long codes should go in a separate .lua file, and included via a Script element.

To include Lua code via a Script element, you must have one or more <Script> elements at the start of the XML file. For example:

<Ui ... >
 <Script file="mycode.lua"/>
 <Frame name="MyFrame">
  ...
 </Frame>
</Ui>

When the XML file is read, the contents of the mycode.lua file is read and interpreted. The code in that file is then available for the rest of this XML file, and any XML files that are read after this one. Functions that are defined in mycode.lua can be called from event handlers in the XML file.

Basic Event Handling concepts

If you are not used to event handled programming, read this section, otherwise you can skip right through it.

Traditional programming style involves writing a program that has a start and finish. Execution starts at the beginning, and after following through the algorithm in the program, it eventually gets to the end.

Event handled programming is somewhat different. In this case, you create several, independent sections of code, with no clear start or finish. Each of these sections of code are designed to be executed in response to a certain event occurring. Such a section of code is called an event handler. An event handler may get executed once, many times, or maybe even never. This kind of programming style is used whenever you want your code to interact with an external program, and do things in response to whatever that program is doing.

In the case of World of Warcraft, the core game is external to the interface code. Whenever something happens in the game, it asks the interface code to respond to it, by calling one of the event handlers.

Handling UI Events

To handle UI events, you must include event handler elements in your XML code. You do this by having a Scripts element, inside of which you have one or more Onxxxx event handler elements. For example:

<Frame name="MyFrame">
 <Scripts>
  <OnShow>
   message("Hello!");
  </OnShow>
 </Scripts>
</Frame>

This frame has one event handler only, which is executed every time this Frame becomes visible. The contents of the OnShow element can be any valid Lua code. In this example, it's a single statement, which calls the function message, which causes a dialog box to pop up with "Hello" inside it. (message is a function defined in BasicControls.xml and is available by default.)

Here is a more complete example of how you include Lua code and then reference it from the event handlers.

mymod.xml:

<Ui ... >
  <Script file="mymod.lua"/>
  <Frame name="MyModMainFrame">
    <Scripts>
      <OnLoad>
        MyMod_ShowMessage();
      </OnLoad>
    </Scripts>
  </Frame>
</Ui>

mymod.lua:

function MyMod_ShowMessage()
  message("Hello World!");
end

When MyModMainFrame gets loaded (which happens once, at the start of the game, when all the XML files are read in), the OnLoad handler gets executed. In this case, the single Lua statement there simply calls the MyMod_ShowMessage function.

It is recommended that you prefix the names of all of your functions, UI objects and global variables with the name of your AddOn like above; all data is shared between Blizzard's own UI and all your addons, so picking a unique prefix helps avoid clashes with other people's code.

For the above example to actually work, you must either create an AddOn with the mymod.lua and mymod.xml files, or include them in the FrameXML directory and reference myframe.xml from FrameXML.toc. See AddOns on how to combine these files into an AddOn.

Event Handler reference

Widget Handlers is a complete reference of what event handlers can be used by each object type.

  • Note: the OnEvent handler is special (see below).

You will notice that the event handlers in the list mostly cover UI related events. The OnEvent handler is special in that it is a general, collective handler for a large number of other events. It gets called for any of the remaining hundreds of game related events. See Events for a list of game events and how to register for them and handle them.

Widget Elements

Moved to XML elements.

Default User Interface

The default user interface that is visible without any installed third-party addons is built into the MPQ files. It can't be modified because it is protected by a digital signature, but the files can be extracted to see how the interface works.