View Single Post
01-24-14, 11:46 PM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
Originally Posted by Jonisaurus View Post
For my OOP practice I made a class (prototype) that can display font strings of units and their different values.
Like level, name, HP, power of the specified units.
I understand you're just practicing, but what you're practicting is way more complicated than it needs to be, and has some issues regardless of efficiency. 220 is not a valid font size; anything larger than 36* will be treated as if it were 36. You don't need to hide and re-show a frame before and after registering events. You should be using RegisterUnitEvent instead of RegisterEvent for unit-specific events. You're limiting your "font strings" to a few pre-defined event handlers, but allowing any arbitrary events to be registered; either allow a custom handler, or just hardcode the right event(s) for the pre-defined handler (eg. if you're handling health, register UNIT_HEALTH and UNIT_MAXHEALTH). There's absolutely no reason to wrap every frame API in an additional function that stores the alpha/position/whatever on keys on the frame, as you can just call frame:GetWhatever() if you really need to know those values later. You should just create a frame and return it so you can use its own API methods directly.

* The maximum font size is specific to the font file you're using, and is closer to 32 for most fonts, but can be much lower for some. It is never higher than 36.

Here's how I would write the same thing, in a more straightforward and more easily extensible way:

Code:
local NewUnitFontString
do
	-- Define events and handlers for specific "display types":
	local displayEvents = {
		health = {
			UNIT_HEALTH = true,
			UNIT_MAXHEALTH = true,
		},
		name = {
			PLAYER_TARGET_CHANGED = false,
			UNIT_NAME_UPDATE = true,
		},
	}
	local displayHandlers = {
		health = function(self, event, unit)
			local hp = UnitHealth(unit or self.unit)
			self:SetText(hp and hp > 0 and hp or nil)
		end,
		name = function(self, event, unit)
			local name = GetUnitName(unit or self.unit, true)
			self:SetText(name)
		end,
	}

	-- Define functions to let the frame be moved:
	local function OnMouseDown(self)
		if IsAltKeyDown() then
			self.isMoving = true
			self:StartMoving()
		end
	end
	local function OnMouseUp(self)
		if self.isMoving then
			self:StopMoving()
			self.isMoving = nil
		end
	end

	function NewUnitFontString(unit, displayType)
		-- Only proceed if this displayType is defined:
		local events, handler = displayEvents[displayType], displayHandlers[displayType]
		if not events or not handler then
			return print("NewUnitFontString:", displayType, "is not a valid display type!")
		end

		-- Make the frame:
		local f = CreateFrame("Frame", nil, UIParent, "SecureHandlerStateTemplate")
		f:SetFrameStrata("BACKGROUND")
		f:SetPoint("CENTER")
		f:SetWidth(228)
		f:SetHeight(64)

		-- Add the font string:
		local text = f:CreateFontString(nil, "OVERLAY")
		text:SetFont("Fonts\\FRIZQT__.TTF", 22, "THICKOUTLINE")
		text:SetAllPoints(true)

		-- Let the frame be dragged around:
		f:EnableMouse(true)
		f:SetMovable(true)
		f:RegisterForDrag("LeftButton")
		f:SetScript("OnMouseDown", OnMouseDown)
		f:SetScript("OnMouseUp", OnMouseUp)
		f:SetScript("OnHide", OnMouseUp) -- otherwise it can get stuck to the cursor if it's being dragged when it gets hidden

		-- Register the events and assign the handler:
		f.unit = unit
		f:SetScript("OnEvent", handler)
		for event, unitSpecific in pairs(events) do
			if unitSpecific then
				f:RegisterUnitEvent(event, unit)
			else
				f:RegisterEvent(event)
			end
		end

		-- Hide the frame when the unit doesn't exist:
		RegisterStateDriver(f, "visibility", "[@"..unit..",exists]show;hide")
		f:SetShown(UnitExists(unit))

		-- Return the frame:
		return f
	end
end
Then you can just ask for and get a normal frame in a normal way, and access and manipulate its properties directly through the normal frame API:

Code:
local targetName = NewUnitFontString("target", "name")
print(targetName:GetWidth())
targetName:SetAlpha(0.5)
(I also made the frames movable when Alt is pressed, and automatically hide themselves when their unit doesn't exist.)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote