WoWWiki

This wiki contains inaccurate and out-of-date information. Please head over to https://wowpedia.fandom.com for more accurate and up-to-date game information.

READ MORE

WoWWiki
Advertisement

XML UI ← XML types < Anchor

An Anchor is also a fundamental UI building block for defining positional layout for UI elements of LayoutFrames. An Anchor is an element of an Anchors array defined in a LayoutFrame. Anchor XML elements, as a part of Anchors array, can be defined on any LayoutFrame or LayoutFrame type, which also includes Frames, Textures, and FontStrings.

Inheritance[]

Inherited by: none, Inherits: none, Defined in: LayoutFrame > Anchors

Elements[]

Attributes[]

  • point (FRAMEPOINT)
  • relativeTo (string) - global name of LayoutFrame to make relative to.
  • relativeKey (string) - a Lua reference to make relative to. alternate to 'relativeTo'. See 'parentKey' in LayoutFrame.
  • relativePoint (FRAMEPOINT)
  • x (int)
  • y (int)

Summary[]

An Anchor is also a fundamental UI building block for defining positional layout for UI elements of LayoutFrames. An Anchor is an element of an Anchors array defined in a LayoutFrame. Anchor XML elements, as a part of Anchors array, can be defined on any LayoutFrame or LayoutFrame type, which also includes Frames, Textures, and FontStrings.

Example[]

<Frame name="MyFrame">
  <Frames>
    <Frame name="$parentChild">
      <Anchors>
        <Anchor point="TOP">
          <Offset>
            <AbsDimension x="0" y="-22" />
          </Offset>
        </Anchor>
        <Anchor point="BOTTOM">
          <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 the bottom of 'child' to the bottom of 'MyFrame', and then offset that alignment by 22 vertically on both of those sides. This example would effectivly cause the child to stretch vertically to match its parent frame in wow, no matter how the parent frame changed size or position. Using anchors in this way lets wow automatically partially or wholely manage the actual position and size of the child.

Details[]

Every frame needs a final position and size in order to be drawn or to be available for user interaction in the WoW UI. Anchors and Size are used to define that layout postion and size. Anchors work by defining how to place the edge or corner of a layout frame. There is no limit to the number of anchors that can be defined on a layout frame. This makes for a very flexible layout system.

Points and Relative Points[]

A particular edge or corner of a layout frame is an anchor 'point'.

For a frame corner, a 'point' of 'TOPLEFT' refers to the top left corner of the of the layout frame the anchor is defined on. For an edge like 'LEFT', the center of that edge is considered to be the actual anchor point of the layout frame the anchor is defined on, if no other anchors overriding the verticle axis are defined.

The 'relativePoint' defines where, on another layout frame, to place a particular 'point' of the layout frame itself.

For this to matter, another layout frame must be cited using 'relativeTo' or 'relativeKey', which contains the relative point to which this frames 'point' is being anchored to.

  • relativeTo (string)
  • relativeKey (string)

The 'relativeTo' is the name of a frame to use for the 'relativePoint'. Alternativley, the 'relativeKey' is the name of a runtime Lua variable that contains a reference to the layout frame to be used for the 'relativePoint'. If 'relativeTo' is defined, then 'relativeKey' will be ignored.

Layouts[]

Layout in printing or computer graphics is concerned with the flow of elements with respect to each other. A layout system is a system for defining that layout. For WoW, flow in layout is defined by frames and anchors, and flow order is established by 'laying out' frames from their creation order from top to bottom, and from parent to child. Frames with the smae parent and render z-order, will be rendered from first to last in definition order as well.

<Frame name="Frame">
  <Frames>
    <Frame name="Frame2">
      <Size x="100" y="100">
      <Anchors><Anchor point="TOP" relativePoint="BOTTOM" x="0" y="-10" /></Anchors>
    </frame>
    <Frame name="Frame3">
      <Size x="100" y="100">
      <Anchors><Anchor point="TOPLEFT" /></Anchors>
    </frame>
  </Frames>
</Frame>

This will place the 'Frame2' child at an offset of 10 from the bottom of its parent frame; 'relativeTo' for 'Frame2' is its parent by default. Frame3 will be rendered on top of Frame2 is they overlap.

    <Frame name="Frame3">
      <Size x="50" y="50">
      <Anchors><Anchor point="TOPLEFT" relativeTo="Frame2" /></Anchors>
    </frame>

Would place the top left of Frame3 on the top left of frame 2.

Relative References[]

Frames can have names. This allows an 'anchor' to reference a frame by its name for relative layout using 'relativeTo'. The 'relativeTo' attribute can contain a replacable tag '$parent' for refereing to another frame without actually having to know its direct parents name, like '$parent3' would refrence 'Frame3' if the parent's name was 'Frame'. This is useful for allowing cleaner code, as parent frame's names could be changed without disturbing the layout. This is even more important with templates as a template may have no way of knowing its parents names and could still access known relative elements by name.

<Frame name="FrameTemplate" virtual='true'>
  <Frames>
    <Frame name="$parent2">
      <Size x="100" y="100">
      <Anchors><Anchor point="TOP" relativePoint="BOTTOM" x="0" y="-10" /></Anchors>
    </frame>
    <Frame name="$parent3">
      <Size x="50" y="50">
      <Anchors><Anchor point="TOPLEFT" relativeTo="$parent2" /></Anchors>
    </frame>
  </Frames>
</Frame>
<Frame name="Frame" inherits="FrameTemplate" />

This works the same as the last example, but using a tmplate with all manner of relative anchors and names.

<Frame name="FrameTemplate" virtual='true'>
  <Frames>
    <Frame parentKey="frame2">
      <Size x="100" y="100">
      <Anchors><Anchor point="TOP" relativePoint="BOTTOM" x="0" y="-10" /></Anchors>
    </frame>
    <Frame parentKey="frame3">
      <Size x="50" y="50">
      <Anchors><Anchor point="TOPLEFT" relativeKey="$parent.frame2" /></Anchors>
    </frame>
  </Frames>
</Frame>
<Frame name="Frame" inherits="FrameTemplate" />

This works the same as the last example, but using lua runtime based 'keys' instead of names.

Default References[]

This is one of those things you wish you could explain at the beginning, but needs to be at the end. :)

Each of these are, in the general case, equivalient:

<Anchor point="TOPLEFT" />
<Anchor point="TOPLEFT" relativeTo="$parent" />
<Anchor point="TOPLEFT" relativeKey="$parent" />

In each case the relative frame is parent. For the default case, the relative frame its the parent. For 'relativeTo', a named parent frame's full name will replace '$parent' causing 'relativeTo' to refer to the parent frame by name. For 'relativeKey', the named or unnamed parent frame's Lua 'reference' will be used as the relative frame, similar to 'self.GetParent()'.

However as of 5.2, this will bug and *not* be equivalent of either '$parent' or 'self':

<Anchor point="TOPLEFT" relativeKey="" />

In this case will ignore all size and anchors, and act as though layout was 'setallpoints' with this frame same size and position as parent,

Also, as of 5.2, May 13 2013, following may/will crash WoW:

<Anchor point="TOPLEFT" relativeKey="$parent.$parent.AccidentallyOnUIParent" />

Where Frame is top frame with no parent and contains a LayerFrame with above anchor, which would effectivly be asking for key on parent of UIParent, since the frame is using the default parent. This is exceedingly easy to accidentally set, or move a frame where some child asks UIParent instead of intended parents parent. So: <Frame><Layers><Layer><Texture><Anchors><Anchor ...CENTER relativeKey=$parent.$parent.Key"/>... will crash, but not <Frame><Frames><Frame><Layers><Layer><Texture><Anchors><Anchor ...CENTER relativeKey=$parent.$parent.$parent.Key"/>... or <Frame parent="UIParent"><Layers><Layer><Texture><Anchors><Anchor ...CENTER relativeKey=$parent.$parent.$parent.Key"/>... and it doesnt matter in any of the cases if the key exists or not.

And finally, for 'relativeTo' below, in the case where the immediate parent doesn't actually have a 'name':

<Anchor point="TOPLEFT" relativeTo="$parent" />

... will *not* be equivalient to:

<Anchor point="TOPLEFT" />

... and will look for a parent with a name up the hierarchy until finds, or hits UIParent which is always named.

Full Key Based Example[]

This is a more complex, albeit awkward, example using 'keys' rather than 'names' for referencing frames. The template in this case uses 'keys' instead of names to make for a cleaner global name space, as this template is used a lot.

The imputus for this template was to use explicit button layer frames, as the 'Button' frame type only knows how to stretch a single simple texture. Using three cuts down on horizontal scaling distortion at the ends for different button sizes. Notice that each original texture is sliced using texture coords so that the ends dont stretch, but is the same texture. Notice that the scripts have to manage the button's texture expressly, as the normal button texture management isn't used. Also important is that the parent keys are available to the script just like any other member of a frame's Lua side runtime object.

Note: Portions edited for brevity. See WoW UI Toolkit for complete original template. As always, if copy/paste give template another name.

<Button name="UIPanelButtonXxxTemplate" virtual="true">
  <Size x="40" y="22"/>
  <Layers>
    <Layer level="BACKGROUND">
      <Texture parentKey="Left" file="Interface\Buttons\UI-Panel-Button-Up">
        <Size x="12"/>
        <Anchors>
          <Anchor point="TOPLEFT"/>
          <Anchor point="BOTTOMLEFT"/>
        </Anchors>
        <TexCoords left="0" right="0.09375" top="0" bottom="0.6875"/>
      </Texture>
      <Texture parentKey="Right" file="Interface\Buttons\UI-Panel-Button-Up">
        <Size x="12"/>
        <Anchors>
          <Anchor point="TOPRIGHT"/>
          <Anchor point="BOTTOMRIGHT"/>
        </Anchors>
        <TexCoords left="0.53125" right="0.625" top="0" bottom="0.6875"/>
      </Texture>
      <Texture parentKey="Middle" file="Interface\Buttons\UI-Panel-Button-Up">
        <Anchors>
          <Anchor point="TOPLEFT" relativeKey="$parent.Left" relativePoint="TOPRIGHT"/>
          <Anchor point="BOTTOMRIGHT" relativeKey="$parent.Right" relativePoint="BOTTOMLEFT"/>
        </Anchors>
        <TexCoords left="0.09375" right="0.53125" top="0" bottom="0.6875"/>
      </Texture>
    </Layer>
  </Layers>
  <Scripts>
    <OnMouseDown>
      if not self:IsEnabled() then return end
      self.Left:SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
      self.Middle:SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
      self.Right:SetTexture("Interface\\Buttons\\UI-Panel-Button-Down");
    </OnMouseDown>
    <OnMouseUp>
      if not self:IsEnabled() then return end
      self.Left:SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
      self.Middle:SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
      self.Right:SetTexture("Interface\\Buttons\\UI-Panel-Button-Up");
    </OnMouseUp>
    <OnDisable>
      self.Left:SetTexture("Interface\\Buttons\\UI-Panel-Button-Disabled");
      self.Middle:SetTexture("Interface\\Buttons\\UI-Panel-Button-Disabled");
      self.Right:SetTexture("Interface\\Buttons\\UI-Panel-Button-Disabled");
    </OnDisable>
  </Scripts>
  <ButtonText name="$parentText"/>
  <NormalFont style="GameFontNormal"/>
  <HighlightFont style="GameFontHighlight"/>
  <DisabledFont style="GameFontDisable"/>
  <HighlightTexture inherits="UIPanelButtonHighlightTexture"/>
</Button>

See also XML Button.

Advertisement