Chapter 26: Page 506 - 'Creating Unit Frames with Group Templates'

The version of this addon written in the book takes advantage of a special function called initialConfigFunction. This function was called with secure privileges even during combat so it allowed us to move frames, change sizes, set attributes, etc. This function no longer exists in this state.

Instead, we can create a secure snippet to do the secure initialization for us, but it cannot do any of the insecure things, such as registering events). Instead, we'll use an OnLoad function on our main frame to do that sort of work.

In the <Scripts> section of the SquareUnitFrames_UnitTemplate XML definition in SquareUnitFrames.xml, add a line for the OnLoad event, so it looks like this:

     <Scripts>
       <OnLoad function="SquareUnitFrames_Frame_OnLoad"/>
       <OnShow function="SquareUnitFrames_Frame_OnShow"/>
       <OnEvent function="SquareUnitFrames_Frame_OnEvent"/>
     </Scripts>

Now we need to change the name of the SquareUnitFrames_InitialConfig function in SquareUnitFrames.lua to SquareUnitFrames_Frame_OnLoad. This works because the outer-most frame of our template does not inherit from any other template, so we're free to set an OnLoad on it to do some initialisation. We'll also change the contents of this function slightly, so make it look like this:

 function SquareUnitFrames_Frame_OnLoad(frame)
   -- Nudge the status bar frame levels down
   frame.unit.healthBar:SetFrameLevel(frame.unit:GetFrameLevel())
   frame.unit.powerBar:SetFrameLevel(frame.unit:GetFrameLevel())
   frame.unit:RegisterForDrag("LeftButton")

   frame:RegisterEvent("UNIT_HEALTH")
   frame:RegisterEvent("UNIT_MAXHEALTH")
   frame:RegisterEvent("PLAYER_ENTERING_WORLD")
   frame:RegisterEvent("UNIT_DISPLAYPOWER")
   frame:RegisterEvent("UNIT_NAME_UPDATE")
   frame:RegisterEvent("PLAYER_TARGET_CHANGED")
   frame:RegisterEvent("UNIT_THREAT_SITUATION_UPDATE")

   -- Set it up so the 'insecure' parts of the unit frame are properly resized
   -- when the pet frame shows/hides, particularly the health and power bars.
   frame.pet.unit = frame.unit
   frame.pet:HookScript("OnShow", SquareUnitFrames_Pet_OnShow)
   frame.pet:HookScript("OnHide", SquareUnitFrames_Pet_OnHide)
 end

All that's left from the original function are the two secure snippets and the associated setup. At the bottom of SquareUnitFrames.lua, change the lines that set the initialConfigFunction and show the header to the following lines:

 -- Register the pet frame for unit watch, and give the pet button a handle to
 -- the unit frame so it can re-size it on show/hide.
 SquareUnitFrames_Header:SetAttribute("initialConfigFunction", [=[
   local unit, pet = self:GetChildren()

   RegisterUnitWatch(pet)
   pet:SetAttribute("unitButton", unit)
 ]=])

This is all a bit of magic/hackery due to the changes to this secure template that make doing something with this particular structure slightly messy. Hopefully the template can be updated at some point to be a bit more straightforward.

Finally, we need to make one last change to the XML file. Change the <Attributes> section of the $parent_Pet button in the unit button template to be the following:

    <Attributes>
      <Attribute name="useparent-unit" type="boolean" value="true"/>
      <Attribute name="unitsuffix" type="string" value="pet"/>
      <Attribute name="*type1" type="string" value="target"/>
      <Attribute name="_onshow" type="string" value="unit = self:GetAttribute('unitButton'); if unit then unit:SetHeight(28) end"/>
      <Attribute name="_onhide" type="string" value="unit = self:GetAttribute('unitButton'); if unit then unit:SetHeight(34) end"/>
    </Attributes>

We're adding two new attributes, _onshow and _onhide which take care of resizing the unit button. They have to (again) do a bit more work in getting the handle to the unit button, but they should function properly.

Be careful when making this last change, there are two different types of quotation marks that are necessary due to the way they next in XML files. You can always copy and paste what is written here and it should work properly.