LibQTip-1.0

How to add custom cells

Custom cells are handled using the "abstract factory" design pattern: LibQTip expects a factory (the CellProvider) able to create the cells. The CellProvider and the Cells should implement a given interface: CellProvider and Cell.

In each of the following examples, we create a custom cell providing colored labels.

Home brew CellProvider

The Cell

First look at the Cell interface. A LibQtip Cell should be a Frame widget that implements an additional method :SetupCell. Parenting, showing/hiding and anchoring of the cell itself is handled by LibQTip, so we do not care about this. We have to take care of any additional widgets though.

-- Create an empty cell prototype
local cellPrototype = {}

-- This prototype should "inherited" from the Frame prototype
-- So we create a dummy frame to be used in a metatable index.
setmetatable(cellPrototype, { __index = CreateFrame("Frame") })

We create an additionnal method for our internal use. We will call this method once per cell.

function cellPrototype:InitializeCell()
  -- Create the FontString to dispaly
  self.fontString = self:CreateFontString()
  self.fontString:SetAllPoints(self)
  self.fontString:SetFontObject(GameTooltipText)
  -- Setup the default color: white
  self.r, self.g, self.b = 1, 1, 1
end

The SetupCell method: this method can be called several times, the extra arguments after font should be remembered

function cellPrototype:SetupCell(tooltip, value, justification, font, r, g, b)
  -- Apply the setting
  local fs = self.fontString
  fs:SetFontObject(font or tooltip:GetFont())
  fs:SetJustifyH(justification)
  fs:SetText(tostring(value))
  
  -- Apply our specific settings, using default values if need be
  self.r, self.g, self.b = r or self.r, g or self.g, b or self.b
  fs:SetTextColor(self.r, self.g, self.b)

  -- Show the fontstring and return our size
  fs:Show()
  return fs:GetStringWidth(), fs:GetStringHeight()
end

Another internal method, that our provider call to cleanup the cell.

function cellPrototype:CleanupCell()
  -- This reset the default text color
  self.r, self.g, self.b = 1, 1, 1
end

The CellProvider

The CellProvider should implements the AcquireCell and ReleaseCell methods. Moreover, though it is not mandatory, it is recommended that it recycles the widgets.

-- The provider with some attributes
local myProvider = {
  -- The heap we will store unused cells into
  heap = {},
  -- The prototype we use for cells,
  cellPrototype = cellPrototype,
  -- The metatable for using the prototype above
  cellMetatable = { __index = cellPrototype }
}

The AcquireCell method: try to get a cell from the heap. If not possible, create a new cell. In this case, do not forget to initialize it. Notice we do not need the tooltip argument in this implementation.

function myProvider:AcquireCell(tooltip)
  -- Try to get an unused cell from the heap
  local cell = table.remove(self.heap)
  if not cell then
    -- Not cell available, create a new one
    cell = CreateFrame("Frame")
    -- Override the metatable
    setmetatable(cell, self.cellMetatable)
    -- Now initialize the cell with our method
    cell:InitializeCell()
  end
  return cell
end

The :ReleaseCell method: clean the cell and put it into the heap.

function myProvider:ReleaseCell(cell)
  -- Cleanup the cell
  cell:CleanupCell()
  -- Put it back into our heap
  table.insert(self.heap, cell)
end

The :GetCellPrototype method: just return our prototype and metatable.

function myProvider:GetCellPrototype()
  return self.cellPrototype, self.cellMetatable
end

Using the provider

Once our provider has been created, we can create cell using the :SetCell methods.

-- Create a tooltip with 2 columns
local tip = LibQTip:Acquire("MyOwnAddonTip", 2, "LEFT", "RIGHT")
-- Add a new line, filling only the left column
local y,x = tip:AddLine("Label:")
-- Add a custom cell using our provided
-- We simply pass :SetCell our provider, followed by the specific arguments (r, g, b)
tip:SetCell(y, x, "Red text", myProvider, 1, 0, 0)

Using LibQTip:CreateCellProvider()

This method creates a fully fledged provider, with cell recycling. Only the cell methods have to be provided. This save us some code. See Standard CellProvider API for more details.

Brand new provider

Compared to the homebrew method we have only to provide the cell methods.

First, let's create the cell provider.

local myProvider, cellPrototype = LibQTip:CreateCellProvider()

Now add the Cell methods into the cellPrototype. Theses are the same as for home brew Cells, except for the name.

function cellPrototype:InitializeCell()
  self.fontString = self:CreateFontString()
  self.fontString:SetAllPoints(self)
  self.fontString:SetFontObject(GameTooltipText)
  self.r, self.g, self.b = 1, 1, 1
end

function cellPrototype:SetupCell(tooltip, value, justification, font, r, g, b)
  local fs = self.fontString
  fs:SetFontObject(font or tooltip:GetFont())
  fs:SetJustifyH(justification)
  fs:SetText(tostring(value))
  self.r, self.g, self.b = r or self.r, g or self.g, b or self.b
  fs:SetTextColor(self.r, self.g, self.b)
  fs:Show()
  return fs:GetStringWidth(), fs:GetStringHeight()
end

function cellPrototype:ReleaseCell()
  self.r, self.g, self.b = 1, 1, 1
end

Subclassing existing provider

This is done using the baseProvider of the :CreateCellProvider method. Here we will implements our colored label based on the LibQTip LabelProvider.

First, we create the derived provider. We need to keep a reference to the base cell prototype to handler "super" calls.

 local myProvider, cellPrototype, baseCellPrototype = LibQTip:CreateCellProvider(LibQTip.LabelProvider)

Now we override the :InitializeCell method to setup the default color:

function cellPrototype:InitializeCell()
  -- This how to call the base method, notice the use of "dot" and "self"
  baseCellPrototype.InitializeCell(self)
  -- Additional code follow:
  self.r, self.g, self.b = 1, 1, 1
end

We also override the :SetupCell method:

function cellPrototype:SetupCell(tooltip, value, justification, font, r, g, b)
  -- Call the base method
  local width, height = baseCellPrototype.SetupCell(self, tooltip, value, justification, font, r, g, b)
  -- The base LabelProvider stores its FontString in the fontString attribute
  -- Sets it color
  self.r, self.g, self.b = r or self.r, g or self.g, b or self.b
  self.fontString:SetTextColor(self.r, self.g, self.b)
  -- Return the 
  return width, height
end

We add an additional method to cleanup the cell:

function cellPrototype:ReleaseCell()
  self.r, self.g, self.b = 1, 1, 1
end


You must login to post a comment. Don't have an account? Register to get one!