Frame is a base type used as a fundamental UI building block for defining 'active' visible screen elements. The Frame type can be used for Layout due to LayoutFrame, and a full set of Appearance and Behaviour facilities. Provides a base type for Button, EditBox, ScrollingMessageFrame, and many others.
Inherited Elements: from LayoutFrame
- alpha (float) Default is 1.0. - opacity of the frame, where 1.0 is opaque and 0.0 is fully transparent
- parent (string) - name frame to use as parent. Overrides natural XML defined parent. Normally blank.
- toplevel (boolean) - if should be displayed on top of all the other frames in its strata. See frameStrata.
- movable (boolean) - if the frame can be moved by the user
- resizable (boolean) - if the frame can be resized by the user
- frameStrata (FRAMESTRATA) - which layer your frame should be on. Normally blank. Default is 'PARENT'.
- frameLevel (int) - position in the strata, overrides parent and XML order. Normally blank. See #frameLevel and frameStrata.
- id (int) Default is 0. - arbitrary frame id, like '1','2','3'. Accessible in Lua at runtime. Usually blank.
- enableMouse (boolean) - if mouse events are sent to the frame
- enableKeyboard (boolean) - if keystroke events are sent to the frame
- clampedToScreen (boolean) - if the frame is kept inside the screen boundaries
- protected (boolean) - if the frame is allowed to run protected code (only allowed in Blizzard code).
- jumpNavigateEnabled (boolean)
- jumpNavigateStart (boolean)
Inherited from LayoutFrame:
- name (string) - the name of the element. Creates Lua global variable holding a reference to this element at runtime. Prefixing with '$parent' replaces with next named parents name.
- parentKey (string) - name for a Lua key in the parent element, which will reference this element at runtime
- parentArray (string) - name for a Lua array in the parent, to hold a reference to this element at runtime
- inherits (string) - name of the virtual element as to use a template, to inherit properties and attributes from.
- virtual (boolean) - marks frame as inheritable type, causing runtime to not create frame. Default is false.
- setAllPoints (boolean) - automatically anchors the TOPLEFT and BOTTOMRIGHT points to the parent
- hidden (boolean) - makes the element hidden by default
Frame based elements facilitate 'Layout', 'Appearance' and 'Behaviour' mechanisms for the WoW UI at runtime. When used with <Scripts> along with the <Anchors> and the <Size> element from LayoutFrame, allows WoW to 'Layout' all of its visible and make them interactive and responsive, including the 3D views of the world. Frame works by providing a flexible set of layout and scripting constructs. Frames also provide a sophisicated 'Z order' based layering system, both in <Layers> element and between the frames themselves.
<Frame name="MyFrameTemplate" hidden="true" virtual="true"/> <Frame name="MyFrame" inherits="MyFrameTemplate"> <Size x="400" y="400"/> <Frames> <Frame name="$parentChild" parentKey="child"> <Size x="200" y="100"/> <Anchors> <Anchor point="TOP"> <Offset> <AbsDimension x="0" y="-22" /> </Offset> </Anchor> </Anchors> </Frame> </Frames> </Frame>
This example will align the top of the 'child' frame to the top of 'MyFrame', and then offset that alignment by -22 vertically. Also demonstrates use of Dimension with Size and Anchor, and using Abs and inline values, as well as use of '$parent' to specify the name of the child where the child 'name' will be 'MyFrameChild' at runtime. Finally this example shows use of 'inherits' and 'virtual' where 'MyFrameTemplate' is inherited by 'MyFrame' causing 'MyFrame' to inherit 'hidden' from 'MyFrameTemplate' making 'MyFrame' hidden by default. At runtime, you can refer to the child frame as either MyFrameChild or MyFrame.child.
Frames are the building blocks of the visual components of the user interface. All of the various visual elements of the UI are types of Frame, and inherit most if not all of the basic frame properties, in addition to adding some more. Frames are defined in the various .xml files in the Interface directory (except for the Bindings.xml files, which provide key bindings).
In addition to Frames being the things that you can see, Frames are also the things which UI and game events are delivered to. If you're writing code that needs to know about something, it will need a Frame (though not necessarily a visible one) to receive the event. There are many types of events, though often in AddOn development it refers to a Game Event rather than other UI events.
A frame indicates its interest in events in a number of ways:
The <Scripts> XML element of a frame definition defines a bunch of different handler types, for most of these (<OnEvent> being the exception) the Frame will automatically be informed of the appropriate events when they occur, via the defined handler script.
Most of the useful information comes from game events, which are all passed to the frame via the generic <OnEvent> script handler. There are literally hundreds of types of Game Events, so rather than spend a lot of time passing every event to every handler, an AddOn must register its interest in a frame receiving a certain event. This is accomplished through the Frame:RegisterEvent("event") function, and is typically performed within the <OnLoad> or <OnShow> handlers. Once an event has been registered, the Frame's <OnEvent> handler will be called whenever that event occurs.
Frames, like all LayoutFrame types, can be defined as virtual, in which case instead of defining an actual UI element that shows up, the definition provides a template which can then be used multiple times by other Frames. A good example of a virtual Frame is the chat window, there are actually several virtual frames which are assembled into a chat window, but then each potential chat window simply implements the virtual one, which reduces the amount of duplicated code required.
Frames have a parent frame. A complex visual element is likely formed of multiple Frames, and it's considered good design to designate a common parent Frame amongst them, and have the rest use that (or its children) as their parent. Well behaved UI AddOns will normally want their top level parent frames set expressly to 'UIParent'. Failure to do so means, amongst other things, that the AddOn's frame won't vanish when the Hide UI key is pressed.
Each Frame can be shown and hidden, if a Frame is Hidden, then it and all of its children cease to be visible. It's far simpler to show and hide the parent frame of a complex set, than to try and manage the visibility of many elements independently.
The UI engine is built to perform automatic scaling of UI elements, the entire UI (actually, the UIParent frame, which most frames are children of), or any component of it can be enlarged or shrunk to fit on a screen appropriately. Frames are scaled and located relative to their parent rather than the whole screen, which means that you only need to worry about how your subcomponents relate to each other, and then your component can be placed and sized any way necessary.
Frame levels are that which determines what frame will be on top of other frame. Each frame has a frame level value. If frame A is placed in the same area as frame B, then the frame with the highest frame level will be on top of the other frame.
Instead of going around and specifying that frame A should have frame level 12, and frame B frame level 15, Blizzard uses a set of predefined "groups" of frame levels called frameStrata. The valid values for frameStrata are "PARENT", "BACKGROUND", "LOW", "MEDIUM", "HIGH", "DIALOG", "FULLSCREEN_DIALOG" and "TOOLTIP" (there may be more). For the values "BACKGROUND" through "TOOLTIP" the values are listed in their assumed ascendancy (i.e. it is assumed that "BACKGROUND" will be below "LOW"). The default value is "PARENT" if no frameStrata is specified.
There is also a special attribute called toplevel - this means (hopefully) that the frame should be on top of any other frame (or, possibly, on top of any other frame in the same frameStrata).
frameLevel and frameStrata
- What is the difference between frameLevel and frameStrata?
Well first off, though you can set frameLevel in your <Frame> tag, frameLevel is dictated by XML nesting. Check this example out:
<Frame name="MyFrame" frameStrata="DIALOG" parent="UIParent"> <Frames> <Button name="MyButton"/> </Frames> </Frame>
Since UIParent's frameLevel is 1, the frame we created here should be frameLevel 2 and the Button should be frameLevel 3.
You can check a frame's level with Frame:GetFrameLevel() and you can set it with Frame:SetFrameLevel(). However, setting a frame's level is ill-advised. It is given its level automatically and it's best to leave it that way. If you need to change a frame's level in your own code, best thing to do is just nest your code differently.
Note: If the parent of a frame is changed by your code, the frame levels are not adjusted to compensate. You may need to adjust the frame's level to fix the way the frame displays.
- Possible Values
- 0 - No parent
- 1 - Parent is UIParent
- 2 and higher...
The maximum value seems to be 129. If you call SetFrameLevel with a value greater than 129, the value passed will be ignored, and the frame level will be set to 129.
In my experimentation, and with my WoW client (Windows), it seems higher values will stick, and be honored, if you call SetFrameLevel twice in a row. This is probably unreliable. If you find that you are having to set frame levels greater than 129, see if you can use a hierarchical set of parent frames instead.
A more complete explanation of how frame levels are used is found at How the user interface is rendered.