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 additional 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
Comments