WoW Font Preview with dynamic scroll frames

This snippet creates a scroll frame in the center of your screen that displays all of the globally named font instances in your World of Warcraft installation. It also shows how to create a scroll frame and slider scroll bar dynamically. The following is an example of how it works:

WoW Font Preview Snippet

Snippet

-- Create the parent frame that will contain the inner scroll child,
-- all font strings, and the scroll bar slider.
local fp = FPreviewFrame or CreateFrame("ScrollFrame", "FPreviewFrame")

-- This is a bare-bones frame is used to encapsulate the contents of
-- the scroll frame.  Each scrollframe can have one scroll child.
local fpsc = FPreviewSC or CreateFrame("Frame", "FPreviewSC")

-- Create the slider that will be used to scroll through the results
local fpsb = FPreviewScrollBar or CreateFrame("Slider", "FPreviewScrollBar", fp)

-- Set up internal textures for the scrollbar, background and thumb texture
if not fpsb.bg then
   fpsb.bg = fpsb:CreateTexture(nil, "BACKGROUND")
   fpsb.bg:SetAllPoints(true)
   fpsb.bg:SetTexture(0, 0, 0, 0.5)
end

if not fpsb.thumb then
   fpsb.thumb = fpsb:CreateTexture(nil, "OVERLAY")
   fpsb.thumb:SetTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
   fpsb.thumb:SetSize(25, 25)
   fpsb:SetThumbTexture(fpsb.thumb)
end

local genv = getfenv(0)

-- Collect the names of all possible globally defined fonts
local fonts = {}
for k, v in pairs(genv) do
   if type(v) == "table" and type(v.GetObjectType) == "function" then
      local otype = v:GetObjectType()
      if otype == "Font" then
         table.insert(fonts, k)
      end
   end
end

-- Sort the list alphabetically
table.sort(fonts)

-- Create a table that will contain the font strings themselves
fpsc.fstrings = fpsc.fstrings or {}

-- This changes the padding between font strings vertically
local PADDING = 5

-- Store the max width and overall height of the scroll child
local height = 0
local width = 0

-- Iterate the list of fonts collected
for idx, fname in ipairs(fonts) do
   -- If the font string is not created, do so
   if not fpsc.fstrings[idx] then
      print(idx, fname)
      fpsc.fstrings[idx] = fpsc:CreateFontString("FPreviewFS" .. idx, "OVERLAY")
   end
   
   -- Set the font string to the correct font object, set the text to be the
   -- name of the font and set the height/width of the font string based on
   -- the size of the resulting 'string'.
   local fs = fpsc.fstrings[idx]
   fs:SetFontObject(genv[fname])
   fs:SetText(fname)
   local fwidth = fs:GetStringWidth()
   local fheight = fs:GetStringHeight()
   fs:SetSize(fwidth, fheight)
   
   -- Place the font strings in rows starting at the top-left
   if idx == 1 then
      fs:SetPoint("TOPLEFT", 0, 0)
      height = height + fheight
   else
      fs:SetPoint("TOPLEFT", fpsc.fstrings[idx - 1], "BOTTOMLEFT", 0, - PADDING)
      height = height + fheight + PADDING
   end
   
   -- Update the 'max' width of the frame
   width = (fwidth > width) and fwidth or width
end

-- Set the size of the scroll child
fpsc:SetSize(width, height)

-- Size and place the parent frame, and set the scrollchild to be the
-- frame of font strings we've created
fp:SetSize(width, 400)
fp:SetPoint("CENTER", UIParent, 0, 0)
fp:SetScrollChild(fpsc)
fp:Show()

fpsc:SetSize(width, height)

-- Set up the scrollbar to work properly
local scrollMax = height - 400
fpsb:SetOrientation("VERTICAL");
fpsb:SetSize(16, 400)
fpsb:SetPoint("TOPLEFT", fp, "TOPRIGHT", 0, 0)
fpsb:SetMinMaxValues(0, scrollMax)
fpsb:SetValue(0)
fpsb:SetScript("OnValueChanged", function(self)
      fp:SetVerticalScroll(self:GetValue())
end)

-- Enable mousewheel scrolling
fp:EnableMouseWheel(true)
fp:SetScript("OnMouseWheel", function(self, delta)
      local current = fpsb:GetValue()
      
      if IsShiftKeyDown() and (delta > 0) then
         fpsb:SetValue(0)
      elseif IsShiftKeyDown() and (delta < 0) then
         fpsb:SetValue(scrollMax)
      elseif (delta < 0) and (current < scrollMax) then
         fpsb:SetValue(current + 20)
      elseif (delta > 0) and (current > 1) then
         fpsb:SetValue(current - 20)
      end
end)
Posted by jnwhiteh at Fri, 23 Apr 2010 16:39:27 +0000