Skip to content
João Cardoso edited this page Dec 16, 2019 · 9 revisions

Welcome to the Poncho wiki. In this page follows a quick guide on how to build frame classes using Poncho and advised implementation procedure.

  • For a complete listing of class and frame methods, see API Reference.
  • For a standalone example of Poncho in action, see the library Sushi-3.1.

Class and Frame Objects

Frames bound to a Poncho class inherit all key-value pairs from their class, unless overwritten at a frame level:

local poncho = LibStub('Poncho-2.0')
local class = poncho('Frame')
class.numBananas = 5

local frame = class()
print(frame.numBananas) -- outputs 5

frame.numBananas = 7
print(frame.numBananas) -- outputs 7

frame.numBananas = nil
print(frame.numBananas) -- outputs 5

This allows you to setup methods and default values for frames of each class.

Class Inheritance

The most powerful feature of class oriented programming is inheritance. Note that Poncho only supports single-inheritance. As with frames and classes, a class inherits all key-value pairs from its parent class. It also inherits any class proprieties (such as frameType):

local subclass = class:NewClass()
print(subclass.numBananas) -- outputs 5

local otherFrame = subclass() -- an unnamed frame, per class proprieties
print(otherFrame.numBananas) -- outputs 5

But inheritance truly shines when shared API is overwritten or extended. Here is an example of a class overwriting an inherited method and of another extending it:

local fruit = poncho('Frame')
local banana = fruit:NewClass()
local exotic = fruit:NewClass()

function fruit:DisplayContent()
  print('These are ' .. self:GetContent())
end

function fruit:GetContent()
  return 'unknown fruits'
end

function banana:GetContent()
  return 'bananas'
end

function exotic:GetContent()
  return 'exotic ' .. self:Super(exotic):GetContent() -- returns 'exotic unknown fruits'
end

Frame Creation Cycle

On most object-oriented programming languages, a class only needs to specify a constructor method that is called when a new object instance is created. Potentially, the developer might also specify a deconstructor method that is called when the object is released from memory. Unfortunately, frames cannot be released from memory in the World of Warcraft Lua API. Thus, frames in Poncho are instead released - that is, kept in an inactive poll and recycled when a new instance is requested.

There are 3 major methods in Poncho you might want to extend to specify construction and release behaviour:

  • :New - called when an instance is requested
  • :Construct - called by :New when no inactive frames are available in the poll
  • :Reset - called before a frame is placed in the inactive poll

Construct

You should code here class code that should be run only once at frame creation. For example, creation of layered regions (textures, fontstrings) or additional frames your instance requires:

function class:Construct()
  local frame = self:Super(class):Construct()
  frame.icon = frame:CreateTexture()
  frame:SetSize(20, 20)
  return frame
end

You can also completely overwrite the method to implement less standard behaviour. This example ignores class proprieties when creating frames, using hardcoded values instead:

function class:Construct()
  return self:Bind(CreateFrame('Button', nil, 'SomeTemplate'))
end

New

This method can be called multiple times per frame, if the frame can be released in your code. On the other hand, if you don't make use of the inactive poll for this class, you could also write here single-use code instead of in :Construct, as it will only be called once. In either case, you can also specify input parameters in this method:

function class:New(parent, icon)
  local frame = self:Super(class):New(parent)
  frame.icon:SetTexture(icon)
  return frame
end

local glove = class(UIParent, 'ICONS/INV_GLOVE_01')
local pants = class(UIParent, 'ICONS/INV_PANTS_01')

Reset

Finally, you can add in this method code that ensures the frame is in a given known state before it is placed in the inactive poll. Take into account that this method, unlike the previous two, is called at the frame level, not at class level.

In this example, we account for the fact that the frame size could have been changed:

function class:Reset()
  self:Super(class):New(parent)
  self:SetSize(20, 20)
end

glove:Release()

Poncho-2.0 🎽

Documentation
Quick Introduction
API Reference

Feedback
Post an issue

Clone this wiki locally