Files
pfUI/api/ui-widgets.lua
T
Brues 00292ca3b4 Focus/Nameplates now respond solely to UNIT_* events
commit 70b1e66c2d
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sun Jul 26 18:30:18 2026 -0500

    Use SetSize/SetShown and simplify minimap/map

commit 7b6bfe9975
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 11:27:14 2026 -0500

    Include raidpet frames in /pftest test mode

    The unit-frame test toggle (showall) only previews frames that exist and
    are positioned. Raidpet frames are created when raidpet.visible == "1",
    but LayoutPets' collapse mode only positions pets whose raidpet<N> unit
    actually exists, so solo/in test mode they stayed hidden.

    Add a showall branch to LayoutPets that mirror-lays every pet cell and
    shows it (bypassing collapse and the roster gate), still guarded by the
    existing showpets check so nothing happens when raidpet is disabled. Call
    LayoutPets from the /pftest handler so the grid updates immediately on
    toggle-on and restores to the normal layout on toggle-off.

commit 4c65c38647
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:34:33 2026 -0500

    Remove unused RangeCache local in UnitInRange

commit 6c96bbbe6c
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:34:33 2026 -0500

    Use Clamp() for the two-sided clamps in ui-widgets

    Replace the hand-rolled math.min/math.max and if/elseif clamp idioms in the
    status bar and scroll frame with Clamp(). Equivalent for every value seen
    (min <= max always holds), just clearer.

commit 830e0a0be1
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:34:33 2026 -0500

    Drop vanilla GetItemInfo shim for C_Item.GetItemInfo

    The compat/vanilla.lua GetItemInfo override reshaped vanilla's tuple into
    retail order by inserting nil at slot 4 (itemLevel), but truncated at 8
    fields, dropping itemEquipLoc/itemTexture. ClassicAPI's global GetItemInfo
    keeps the vanilla shape (its hook only warms the item cache), so the shim
    stayed necessary but incomplete.

    Remove it and point the three callers at ClassicAPI's C_Item.GetItemInfo,
    which returns the full 18-field retail tuple. Positions 1-8 are identical
    to the old shim output, so bags/roll are unchanged; character.lua's
    itemSlot (equipLoc, field 9) was always nil under the truncating shim and
    now resolves correctly for ShaguScore.

commit c0da63657d
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 10:09:34 2026 -0500

    Various cleanup

    Removes version compatibility checks for TBC/Vanilla, consolidating code to target a single WoW version. Refactors repetitive SetWidth/SetHeight calls to SetSize for cleaner code. Removes duplicate function definitions from unitxp module and simplifies conditional show/hide operations using SetShown.

commit 11a6302c2d
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 09:53:37 2026 -0500

    Delegate pfUI.api.strsplit to ClassicAPI's strsplit

    Replace the Lua pattern-based implementation with a thin wrapper around
    ClassicAPI's C-level strsplit. Keeps the pfUI.api.strsplit entry point for
    backwards compatibility with addons that call it, while dropping the
    redundant reimplementation.

    Behavioral note: the old version used ([^delim]+) which silently collapsed
    empty fields; delegating to real strsplit now preserves them
    ("a,,b" -> "a", "", "b"). All in-repo callers split numeric color tuples,
    version strings, or build name-keyed lookup tables, none of which are
    affected by empty-field preservation.

commit 67c126eac8
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 01:01:02 2026 -0500

    Bump ClassicAPI minimum version to 1.8.0

commit a6cf157518
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 00:49:50 2026 -0500

    read spell rank via C_Spell.GetSpellSubtext

    The rank string comes from the spell subtext ("Rank N"), which ClassicAPI's
    C_Spell.GetSpellSubtext returns directly -- so drop nampower's
    GetSpellRecField(spellId, "rank") here. The existing "Rank " gsub parse is
    unchanged.

commit 4b1ba99b4f
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 00:33:20 2026 -0500

    Move player info overlay onto ClassicAPI (drop Nampower)

    The haste/spell-power overlay read both values through Nampower and disabled
    itself entirely without it. Move both to ClassicAPI so it works on any
    ClassicAPI client:

    - Spell power: GetSpellPower("net") (nampower) -> GetSpellBonusDamage(i)
      (ClassicAPI, same per-school field). Merged the build+scan into one loop;
      the default school seeds the tiebreak so equal schools still favor it.
    - Haste: GetUnitField("player", "modCastSpeed") -> UnitSpellHaste("player"),
      which returns the haste percentage directly (the (1/modCastSpeed-1)*100
      conversion is now baked in, off the same UNIT_MOD_CAST_SPEED field, signed).
    - Dropped the "if not GetUnitField then return" gate -- UpdateInfoText no
      longer touches Nampower, so the overlay runs everywhere.

commit 7df4aa6d50
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Sat Jul 25 00:32:44 2026 -0500

    Hook the real global _G.UnitHealth for feign death

    Inside a RegisterModule body, `function UnitHealth(...)` defines UnitHealth on
    the pfUI environment, not the real global -- so the feign-death real-HP fix
    only reached callers that resolve UnitHealth through pfUI's env, and missed
    _G consumers (Blizzard frames, other addons). Hook _G.UnitHealth explicitly
    (and capture oldUnitHealth from _G) so the un-gate applies everywhere.

commit b0bf2fd869
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 21:10:58 2026 -0500

    Refactor nampower module

    Simplify reactive spell storage by using spell IDs instead of texture/name tables. Update to use modern C_Spell APIs (GetSpellTexture, GetSpellName) instead of manual texture paths. Consolidate SetWidth/SetHeight calls to SetSize and use print() instead of DEFAULT_CHAT_FRAME:AddMessage().

commit 0b06961333
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 20:54:23 2026 -0500

    Use GetNamePlateForUnit for target lookups; drop dead ScanGuid block

    - Replace the three GetNamePlateForGUID(UnitGUID("target")) round-trips with
      GetNamePlateForUnit("target"), which resolves the token to a GUID internally
      -- no UnitGUID string detour, and it returns nil for no-target/no-plate so
      the UnitExists guards collapse. GetNamePlateForGUID is left for raw-GUID cases.
    - Remove the dead libunitscan.ScanGuid nameplate block (ScanGuid was deleted
      from libunitscan long ago, so the guard was never true) -- it carried the
      last GetUnitField("npcFlags") read.

commit 3e6210086e
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 20:54:23 2026 -0500

    Drop Nampower stats system and polling from unit frames

    GetUnitStats now reads health/power straight from UnitHealth/UnitPower
    (the descriptor fields the server broadcasts) -- for a real unit token
    GetUnitField read nothing different, so the whole Nampower-vs-fallback
    apparatus was measuring a distinction that no longer exists. Removed:

    - The stats system: pfUI.uf.stats, pfUIStatsFrame + UpdateStatsDisplay, the
      lastUnitStats change-cache, the /pfuistats slash command, and every counter
      increment (event/heartbeat/earlyReturn/throttledSkip/nampower/fallback).
    - All GetUnitField health reads (GetUnitStats, heal-prediction, health-gradient
      color) -- collapsed to the UnitHealth/UnitHealthMax they already fell back to.
    - The heartbeat-polling backstop and its fallbackThrottle/lastEventUpdate deps.
      Frames now refresh on events only; eventless frames still use their own tick,
      and range/aggro still run in the eventless-actions block.

commit 63001b7b0c
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 20:09:42 2026 -0500

    Move nameplates onto ClassicAPI stable nameplate tokens

    ClassicAPI now assigns retail-exact, per-plate-stable "nameplateN" tokens and
    fires vanilla UNIT_* events for them, so the nameplate module can key off the
    token instead of Nampower/SuperWoW GUID primitives:

    - Events: UNIT_AURA_GUID/UNIT_FLAGS_GUID -> UNIT_AURA/UNIT_FLAGS, matched by
      the "nameplateN" token (guarded on the token prefix, since these also fire
      for target/party/raid). Registered unconditionally -- no GetUnitField gate.
    - Health: GetUnitField(guid, "health"/"maxHealth") -> UnitHealth/UnitHealthMax
      on the plate's cached token. Same UNIT_FIELD_HEALTH the server broadcasts
      (real HP on Turtle; the ~= 100 scaled-vs-real guard is unchanged).
    - Combat/target in GetCombatStateColor: GetUnitField("flags") + HasFlag ->
      UnitAffectingCombat(token); GetUnitField("target") + SuperWoW "<guid>target"
      -> the "nameplateNtarget" chain. Dropped the now-dead HasFlag,
      UNIT_FLAG_IN_COMBAT, and guidTargetTokenCache.
    - GetCastInfo now takes the token directly; every caller already holds it, so
      the UnitTokenFromGUID(guid) round-trip is gone (unused module-wide now).

    NAME_PLATE_UNIT_ADDED caches the token as plate.nameplate.unit alongside the
    GUID; REMOVED clears both. GUID is retained only as the stable cache key
    (debuffCache/threatMemory/combatColorCache). Only GetUnitField("npcFlags")
    remains -- it has no token/vanilla equivalent.

commit ce1c49fcbb
Author: Brues <5278969+brues-code@users.noreply.github.com>
Date:   Fri Jul 24 18:20:06 2026 -0500

    Make focus/focustarget event-driven via ClassicAPI unit events

    ClassicAPI now fires UNIT_* (health/mana/aura/...) with arg1 == "focus" and
    arg1 == "focustarget", observed per-unit like target/party/raid. Both frames
    already registered those events (focus/focustarget are in pfValidUnits) and
    their OnEvent already matches arg1 == label, so the 0.2s polling ticks were
    pure workarounds for the missing events. Drop both ticks; the frames now
    refresh on-event like target, with range/glow still on the shared 0.5s state
    pass and PLAYER_FOCUS_CHANGED still driving assign/clear.
2026-07-26 18:32:36 -05:00

1250 lines
37 KiB
Lua

-- load pfUI environment
setfenv(1, pfUI:GetEnvironment())
do -- statusbars
local animations = {}
local stepsize, val
local width, height, point
local animate = CreateFrame("Frame", "pfStatusBarAnimation", UIParent)
animate:SetScript("OnUpdate", function()
stepsize = tonumber(pfUI_config.unitframes.animation_speed)
for bar in pairs(animations) do
if not bar.val_ or abs(bar.val_ - bar.val) < stepsize or bar.instant then
bar:DisplayValue(bar.val)
elseif bar.val ~= bar.val_ then
bar:DisplayValue(bar.val_ + min((bar.val-bar.val_) / stepsize, max(bar.val-bar.val_, 30 / GetFramerate())))
end
end
end)
local handlers = {
["DisplayValue"] = function(self, val)
val = Clamp(val, self.min, self.max)
-- remove animation queue
if val == self.val_ then
animations[self] = nil
end
-- set current visible value
self.val_ = val
if self.mode == "vertical" then
height = self:GetHeight()
height = height / self:GetEffectiveScale()
point = height / (self.max - self.min) * (val - self.min)
-- keep values in limits
point = Clamp(point, 0, height)
-- set point to zero if value and max is zero
if val == 0 then point = 0 end
-- set status bar position/size
self.bar:SetPoint("TOPLEFT", self, "TOPLEFT", 0, - height + point)
self.bar:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 0)
-- set background bar position/size
self.bg:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)
self.bg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, point)
else
width = self:GetWidth()
width = width / self:GetEffectiveScale()
point = width / (self.max - self.min) * (val - self.min)
-- keep values in limits
point = Clamp(point, 0, width)
-- set point to zero if value and max is zero
if val == 0 then point = 0 end
-- set status bar position/size
self.bar:SetPoint("TOPLEFT", self, "TOPLEFT", 0, 0)
self.bar:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", - width + point, 0)
-- set background bar position/size
self.bg:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", 0, 0)
self.bg:SetPoint("TOPLEFT", self, "TOPLEFT", point, 0)
end
end,
["SetMinMaxValues"] = function(self, smin, smax, smooth)
-- smoothen the transition by keeping the value at the same percentage as before
if smooth and self.max and self.max > 0 and smax > 0 and self.max ~= smax then
self.val_ = (self.val_ or self.val) / self.max * smax
end
self.min, self.max = smin, smax
self:DisplayValue(self.val_ or self.val)
end,
["SetValue"] = function(self, val)
self.val = val or 0
-- start animation on difference
if self.val_ ~= self.val then
animations[self] = true
end
end,
["SetStatusBarTexture"] = function(self, r, g, b, a)
self.bar:SetTexture(r, g, b, a)
end,
["SetStatusBarColor"] = function(self, r, g, b, a)
self.bar:SetVertexColor(r, g, b, a)
end,
["SetStatusBarBackgroundTexture"] = function(self, r, g, b, a)
self.bg:SetTexture(r, g, b, a)
end,
["SetStatusBarBackgroundColor"] = function(self, r, g, b, a)
self.bg:SetVertexColor(r, g, b, a)
end,
["SetOrientation"] = function(self, mode)
self.mode = strlower(mode)
end,
}
function pfUI.api.CreateStatusBar(name, parent)
local f = CreateFrame("Button", name, parent)
f:EnableMouse(false)
f.bar = f:CreateTexture(nil, "NORMAL")
f.bar:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
f.bar:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
f.bg = f:CreateTexture(nil, "BACKGROUND")
f.bg:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
f.bg:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 0)
-- set some default values
f.min, f.max, f.val = 0, 100, 0
-- add all handler functions to the object
for name, func in pairs(handlers) do
f[name] = func
end
return f
end
end
do -- dropdown
local function ListEntryOnShow()
this.icon:SetShown(this.parent.id == this.id)
end
local function ListEntryOnClick()
this.parent:SetSelection(this.id)
if this.parent.mode == "MULTISELECT" then
this.parent:ShowMenu()
else
this.parent:HideMenu()
end
if this.parent.menu[this.id].func then
this.parent.menu[this.id].func()
end
end
local function ListEntryOnEnter()
this.hover:Show()
end
local function ListEntryOnLeave()
this.hover:Hide()
end
local function ListButtonOnClick()
if this.ToggleMenu then
this:ToggleMenu()
else
this:GetParent():ToggleMenu()
end
end
local function MenuOnUpdate()
if not MouseIsOver(this, 100, -100, -100, 100) then
this.button:HideMenu()
end
end
local function ListButtonOnEnter()
this.button:SetBackdropBorderColor(this.button.cr,this.button.cg,this.button.cb,(this.button.ca or 1))
end
local function ListButtonOnLeave()
this.button:SetBackdropBorderColor(this.button.rr,this.button.rg,this.button.rb,(this.button.ra or 1))
end
local handlers = {
["SetSelection"] = function(self, id)
if id and self.menu and self.menu[id] then
self.text:SetText(self.menu[id].text)
self.id = id
end
end,
["SetSelectionByText"] = function(self, name)
self:UpdateMenu()
for id, entry in pairs(self.menu) do
if entry.text == name then
self:SetSelection(id)
return true
end
end
self.text:SetText(name)
return nil
end,
["GetSelection"] = function(self)
self:UpdateMenu()
if self.menu and self.menu[self.id] then
return self.id, self.menu[self.id].text, self.menu[self.id].func
end
end,
["SetMenu"] = function(self, menu)
if type(menu) == "function" then
self.menu = menu()
self.menufunc = menu
else
self.menu = menu
self.menufunc = nil
end
end,
["GetMenu"] = function(self)
self:UpdateMenu()
return self.menu
end,
["ShowMenu"] = function(self)
self:UpdateMenu()
self.menuframe:SetFrameLevel(self:GetFrameLevel() + 8)
self.menuframe:SetHeight(table.getn(self.menu)*20+4)
self.menuframe:Show()
end,
["HideMenu"] = function(self)
self.menuframe:Hide()
end,
["ToggleMenu"] = function(self)
if self.menuframe:IsShown() then
self:HideMenu()
else
self:ShowMenu()
end
end,
["UpdateMenu"] = function(self)
-- run/reload menu function if available
if self.menufunc then self.menu = self.menufunc() end
if not self.menu then return end
-- set caption to the current value
self.text:SetText(self.menu[self.id] and self.menu[self.id].text or "")
-- refresh menu buttons
for id, element in pairs(self.menuframe.elements) do
element:Hide()
end
for id, data in pairs(self.menu) do
self:CreateMenuEntry(id)
end
end,
["CreateMenuEntry"] = function(self, id)
if not self.menu[id] then return end
local frame, entry
for count, existing in pairs(self.menuframe.elements) do
if not existing:IsShown() then
frame = existing
entry = count
break
end
end
if not frame and not entry then
entry = table.getn(self.menuframe.elements) + 1
frame = CreateFrame("Button", nil, self.menuframe)
frame:SetFrameStrata("FULLSCREEN")
frame:ClearAllPoints()
frame:SetPoint("TOPLEFT", self.menuframe, "TOPLEFT", 2, -(entry-1)*20-2)
frame:SetPoint("TOPRIGHT", self.menuframe, "TOPRIGHT", -2, -(entry-1)*20-2)
frame:SetHeight(20)
frame.parent = self
frame.icon = frame:CreateTexture(nil, "OVERLAY")
frame.icon:SetPoint("RIGHT", frame, "RIGHT", -2, 0)
frame.icon:SetSize(16, 16)
frame.icon:SetTexture("Interface\\Buttons\\UI-CheckBox-Check")
frame.text = frame:CreateFontString(nil, "OVERLAY")
frame.text:SetFontObject(GameFontWhite)
frame.text:SetFont(pfUI.font_default, pfUI_config.global.font_size-1, "OUTLINE")
frame.text:SetJustifyH("RIGHT")
frame.text:SetPoint("LEFT", frame, "LEFT", 2, 0)
frame.text:SetPoint("RIGHT", frame.icon, "LEFT", -2, 0)
frame.hover = frame:CreateTexture(nil, "BACKGROUND")
frame.hover:SetAllPoints(frame)
frame.hover:SetTexture(.4,.4,.4,.4)
frame.hover:Hide()
table.insert(self.menuframe.elements, frame)
end
frame.id = id
frame.text:SetText(self.menu[id].text)
frame:SetScript("OnShow", ListEntryOnShow)
frame:SetScript("OnClick", ListEntryOnClick)
frame:SetScript("OnEnter", ListEntryOnEnter)
frame:SetScript("OnLeave", ListEntryOnLeave)
frame:Show()
end,
}
function pfUI.api.CreateDropDownButton(name, parent)
local frame = CreateFrame("Button", name, parent)
frame:SetScript("OnEnter", ListButtonOnEnter)
frame:SetScript("OnLeave", ListButtonOnLeave)
frame:SetScript("OnClick", ListButtonOnClick)
frame:SetHeight(20)
frame.id = nil
CreateBackdrop(frame, nil, true)
local button = CreateFrame("Button", nil, frame)
button:SetPoint("RIGHT", frame, "RIGHT", -2, 0)
button:SetSize(16, 16)
button:SetScript("OnClick", ListButtonOnClick)
SkinArrowButton(button, "down")
button.icon:SetVertexColor(1,.9,.1)
local text = frame:CreateFontString(nil, "OVERLAY")
text:SetFontObject(GameFontWhite)
text:SetFont(pfUI.font_default, pfUI_config.global.font_size-1, "OUTLINE")
text:SetPoint("RIGHT", button, "LEFT", -4, 0)
text:SetJustifyH("RIGHT")
local menuframe = CreateFrame("Frame", tostring(frame).."menu", parent)
menuframe.button = frame
menuframe.elements = {}
menuframe:SetPoint("TOPLEFT", frame, "BOTTOMLEFT", 0, -2)
menuframe:SetPoint("TOPRIGHT", frame, "TOPRIGHT", 0, 2)
menuframe:SetScript("OnUpdate", MenuOnUpdate)
menuframe:Hide()
CreateBackdrop(menuframe, nil, true)
for name, func in pairs(handlers) do
frame[name] = func
end
frame.menuframe = menuframe
frame.button = button
frame.text = text
return frame
end
end
function pfUI.api.CreateTabChild(self, title, bwidth, bheight, bottom, static)
-- create tab button
local b = CreateFrame("Button", "pfConfig" .. title .. "Button", self, "UIPanelButtonTemplate")
b:SetText(title)
-- setup env
local childcount = table.getn(self.childs) + 1
local button_width = bwidth
local button_height = bheight or 20
local border = 4
if not button_width then
button_width = 150
elseif button_width == true then
button_width = _G["pfConfig" .. title .. "ButtonText"]:GetStringWidth() + 4 * border
end
-- set dimensions
b:SetSize(button_width, button_height)
b:SetID(childcount)
if not self.align or self.align == "LEFT" then
local outside = self.outside and -2 * border - button_width or 0
if bottom then
b:SetPoint("BOTTOMLEFT", self, "BOTTOMLEFT", border + outside, (self.bottomcount-1) * (button_height) + (self.bottomcount * border) )
else
b:SetPoint("TOPLEFT", self, "TOPLEFT", border + outside, -(childcount-1) * (button_height) - (childcount * border) )
end
elseif self.align == "TOP" then
local outside = self.outside and 2 * border + button_height or 0
local prev_button = self.buttons[getn(self.buttons)]
if prev_button then
b:SetPoint("TOPLEFT", prev_button, "TOPRIGHT", border, 0)
else
b:SetPoint("TOPLEFT", self, "TOPLEFT", border + (self.outside and -border), -border + outside )
end
end
SkinButton(b,.2,1,.8)
if childcount ~= 1 then
b:SetTextColor(.5,.5,.5)
else
b:SetTextColor(.2,1,.8)
end
b:SetScript("OnClick", function()
for k,v in pairs(self.childs) do
v:Hide()
end
self.childs[this:GetID()]:Show()
for k,v in pairs(self.buttons) do
v.active = false
v:SetTextColor(.5,.5,.5)
end
self.buttons[this:GetID()]:SetTextColor(.2,1,.8)
end)
self.buttons[childcount] = b
self.bottomcount = bottom and self.bottomcount + 1 or self.bottomcount
-- create child frame
local child, scrollchild = nil, nil
if not static then
child = CreateScrollFrame("pfConfig" .. title .. "Frame", self)
scrollchild = CreateScrollChild("pfConfig" .. title .. "ScrollChild", child)
else
child = CreateFrame("Frame", "pfConfig" .. title .. "Frame", self)
end
if childcount ~= 1 then child:Hide() end
if not self.align or self.align == "LEFT" then
child:SetPoint("TOPLEFT", self, "TOPLEFT", button_width + 2*border + 5, -border -5)
child:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -border -5 , border + 5)
elseif self.align == "TOP" then
if self.outside then
child:SetPoint("TOPLEFT", self, "TOPLEFT", 5, -5)
child:SetPoint("BOTTOMRIGHT", self, "BOTTOMRIGHT", -5, 5)
end
end
CreateBackdrop(child)
SetAllPointsOffset(child.backdrop, child, -5,5)
local ret = scrollchild or child
ret.button = b
table.insert(self.childs, child)
return ret
end
function pfUI.api.CreateTabFrame(parent, align, outside)
local f = CreateFrame("Frame", nil, parent)
f:SetPoint("TOPLEFT", parent, "TOPLEFT", -5, 5)
f:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", 5, -5)
-- setup env
f.childs = { }
f.buttons = { }
f.align = align
f.outside = outside
f.bottomcount = 1
-- Create Child Frame
f.CreateTabChild = pfUI.api.CreateTabChild
return f
end
function pfUI.api.CreateScrollFrame(name, parent)
local f = CreateFrame("ScrollFrame", name, parent)
-- create slider
f.slider = CreateFrame("Slider", nil, f)
f.slider:SetOrientation('VERTICAL')
f.slider:SetPoint("TOPLEFT", f, "TOPRIGHT", -7, 0)
f.slider:SetPoint("BOTTOMRIGHT", 0, 0)
f.slider:SetThumbTexture(pfUI.media["img:col"])
f.slider.thumb = f.slider:GetThumbTexture()
f.slider.thumb:SetHeight(50)
f.slider.thumb:SetTexture(.3,1,.8,.5)
f.slider:SetScript("OnValueChanged", function()
f:SetVerticalScroll(this:GetValue())
f.UpdateScrollState()
end)
f.UpdateScrollState = function()
f.slider:SetMinMaxValues(0, f:GetVerticalScrollRange())
f.slider:SetValue(f:GetVerticalScroll())
local m = f:GetHeight()+f:GetVerticalScrollRange()
local v = f:GetHeight()
local ratio = v / m
if ratio < 1 then
local size = math.floor(v * ratio)
f.slider.thumb:SetHeight(size)
f.slider:Show()
else
f.slider:Hide()
end
end
f.Scroll = function(self, step)
local step = step or 0
local current = f:GetVerticalScroll()
local max = f:GetVerticalScrollRange()
local new = current - step
f:SetVerticalScroll(Clamp(new, 0, max))
f:UpdateScrollState()
end
f:EnableMouseWheel(1)
f:SetScript("OnMouseWheel", function()
this:Scroll(arg1*10)
end)
return f
end
function pfUI.api.CreateScrollChild(name, parent)
local f = CreateFrame("Frame", name, parent)
-- dummy values required
f:SetSize(1, 1)
f:SetAllPoints(parent)
parent:SetScrollChild(f)
f:SetScript("OnUpdate", function()
this:GetParent():UpdateScrollState()
end)
return f
end
-- [ CreateTextBox ]
-- Creates and returns a default pfUI skinned EditBox
function pfUI.api.CreateTextBox(name, parent)
local f = CreateFrame("EditBox", name, parent)
f:SetScript("OnEscapePressed", function() this:ClearFocus() end)
f:SetAutoFocus(false)
f:SetTextInsets(5, 5, 5, 5)
f:SetFontObject(GameFontNormal)
CreateBackdrop(f, nil, true)
return f
end
-- [ EnableClickRotate ]
-- Enables Modelframes to be rotated by click-drag
-- 'frame' [frame] the modelframe that should be used
function pfUI.api.EnableClickRotate(frame)
frame:EnableMouse(true)
frame:HookScript("OnUpdate", function()
if this.rotate then
local x,_ = GetCursorPosition()
if this.curx > x then
this.rotation = this.rotation - abs(x-this.curx) * 0.025
elseif this.curx < x then
this.rotation = this.rotation + abs(x-this.curx) * 0.025
end
this:SetRotation(this.rotation)
this.curx, this.cury = x, y
end
end)
frame:HookScript("OnMouseDown", function()
if arg1 == "LeftButton" then
this.rotate = true
this.curx, this.cury = GetCursorPosition()
end
end)
frame:HookScript("OnMouseUp", function()
this.rotate, this.curx, this.cury = nil, nil, nil
end)
end
local function SetHighlightEnter()
if this.locked then return end
(this.backdrop or this):SetBackdropBorderColor(this.cr,this.cg,this.cb,(this.ca or 1))
end
local function SetHighlightLeave()
if this.locked then return end
(this.backdrop or this):SetBackdropBorderColor(this.rr,this.rg,this.rb,(this.ra or 1))
end
function pfUI.api.SetHighlight(frame, cr, cg, cb)
if not frame then return end
if not cr or not cg or not cb then
cr, cg, cb = GetClassColor(UnitClassBase('player'))
end
frame.cr, frame.cg, frame.cb = cr, cg, cb, ca
frame.rr, frame.rg, frame.rb, frame.ra = GetStringColor(pfUI_config.appearance.border.color)
if not frame.pfEnterLeave then
local enter, leave = frame:GetScript("OnEnter"), frame:GetScript("OnLeave")
if enter then
frame:HookScript("OnEnter", SetHighlightEnter)
else
frame:SetScript("OnEnter", SetHighlightEnter)
end
if leave then
frame:HookScript("OnLeave", SetHighlightLeave)
else
frame:SetScript("OnLeave", SetHighlightLeave)
end
frame.pfEnterLeave = true
end
end
function pfUI.api.HandleIcon(frame, icon)
if not frame or not icon then return end
SetAllPointsOffset(icon, frame, 3)
icon:SetTexCoord(.08, .92, .08, .92)
end
-- [ Skin Button ]
-- Applies pfUI skin to buttons:
-- 'button' [frame/string] the button that should be skinned.
-- 'cr' [int] mouseover color (red), defaults to classcolor.
-- 'cg' [int] mouseover color (green), defaults to classcolor.
-- 'cb' [int] mouseover color (blue), defaults to classcolor.
-- 'icon' [texture] the button icon that should be skinned.
-- 'disableHighlight' [bool] disable mouseover highlight.
function pfUI.api.SkinButton(button, cr, cg, cb, icon, disableHighlight)
local b = _G[button]
if not b then b = button end
if not b then return end
if not cr or not cg or not cb then
cr, cg, cb = GetClassColor(UnitClassBase('player'))
end
pfUI.api.CreateBackdrop(b, nil, true)
b:SetNormalTexture("")
b:SetHighlightTexture("")
b:SetPushedTexture("")
b:SetDisabledTexture("")
if b.SetCheckedTexture and b:GetCheckedTexture() then
b:GetCheckedTexture():SetTexture(cr, cg, cb, .25)
end
if not disableHighlight then
SetHighlight(b, cr, cg, cb)
end
if icon then
HandleIcon(b, icon)
b:SetPushedTexture(nil)
end
b:SetFont(pfUI.font_default, pfUI_config.global.font_size, "OUTLINE")
b.LockHighlight = function()
b:SetBackdropBorderColor(cr,cg,cb,1)
b.locked = true
end
b.UnlockHighlight = function()
if not MouseIsOver(b) then
b:SetBackdropBorderColor(GetStringColor(pfUI_config.appearance.border.color))
end
b.locked = false
end
end
-- [ Skin Collapse Button ]
-- Applies pfUI skin to collapse/expand buttons:
-- 'button' [frame/string] the button that should be skinned.
function pfUI.api.SkinCollapseButton(button, all)
local b = _G[button]
if not b then b = button end
if not b then return end
local name = b:GetName() .. "CollapseButton"
local size = 10
b.icon = _G[name] or CreateFrame("Button", name, b)
if all then size = 14 end
b.icon:SetSize(size, size)
b.icon:SetPoint("LEFT", 2, 2)
CreateBackdrop(b.icon)
b.icon.text = b.icon:CreateFontString(nil, "OVERLAY")
b.icon.text:SetFontObject(GameFontWhite)
b.icon.text:SetPoint("CENTER", -1, 0)
b:SetNormalTexture(nil)
b.SetNormalTexture = function(self, tex)
if not tex or tex == "" then
self.icon:Hide()
else
self.icon.text:SetText(strfind(tex, "MinusButton") and "-" or "+")
self.icon:Show()
end
end
local highlight = _G[b:GetName().."Highlight"]
if highlight then
highlight:SetTexture("")
highlight.SetTexture = function(self, tex) return end
end
end
-- [ Skin Rotate Button]
-- Applies pfUI skin to rotation buttons like in character pane:
-- 'button' [frame/string] the button that should be skinned.
function pfUI.api.SkinRotateButton(button)
pfUI.api.CreateBackdrop(button)
local cr, cg, cb = GetClassColor(UnitClassBase('player'))
local btnW, btnH = button:GetSize()
button:SetSize(btnW - 18, btnH - 18)
button:GetNormalTexture():SetTexCoord(0.3, 0.29, 0.3, 0.65, 0.69, 0.29, 0.69, 0.65)
button:GetPushedTexture():SetTexCoord(0.3, 0.29, 0.3, 0.65, 0.69, 0.29, 0.69, 0.65)
button:GetHighlightTexture():SetTexture(cr, cg, cb, .25)
button:GetPushedTexture():SetAllPoints(button:GetNormalTexture())
button:GetHighlightTexture():SetAllPoints(button:GetNormalTexture())
end
-- [ Skin Close Button ]
-- Applies pfUI close skin to buttons and can also be positioned
-- 'button' [frame] the button that should be skinned.
-- 'parentFrame' [frame] will anchor to the top right of the parent.
-- 'offsetX' [integer] offsets the button horizontally
-- 'offsetY' [integer] offsets the button vertically
function pfUI.api.SkinCloseButton(button, parentFrame, offsetX, offsetY)
if not button then return end
SkinButton(button, 1, .25, .25)
button:SetSize(15, 15)
if parentFrame then
button:ClearAllPoints()
button:SetPoint("TOPRIGHT", parentFrame, "TOPRIGHT", offsetX, offsetY)
end
button.texture = button:CreateTexture("pfQuestionDialogCloseTex")
button.texture:SetTexture(pfUI.media["img:close"])
button.texture:ClearAllPoints()
button.texture:SetAllPoints(button)
button.texture:SetVertexColor(1,.25,.25,1)
end
function pfUI.api.SkinArrowButton(button, dir, size)
if not button then return end
SkinButton(button)
button:SetHitRectInsets(-3,-3,-3,-3)
button:SetNormalTexture(nil)
button:SetPushedTexture(nil)
button:SetHighlightTexture(nil)
button:SetDisabledTexture(nil)
if size then
button:SetSize(size, size)
end
if not button.icon then
button.icon = button:CreateTexture(nil, "ARTWORK")
button.icon:SetAlpha(.8)
SetAllPointsOffset(button.icon, button, 3)
end
button.icon:SetTexture(pfUI.media["img:"..dir])
if not button.pficonfade then
local button, state = button, nil
button.pficonfade = CreateFrame("Frame", nil, button)
button.pficonfade:SetScript("OnUpdate", function()
if state == button:IsEnabled() then return end
state = button:IsEnabled()
if state > 0 then
button.icon:SetVertexColor(.8,.8,.8,1)
else
button.icon:SetVertexColor(.2,.2,.2,1)
end
end)
end
end
function pfUI.api.SkinScrollbar(frame, always)
local parent = frame:GetParent()
local name = frame:GetName()
local up = _G[name .. "ScrollUpButton"]
local down = _G[name .. "ScrollDownButton"]
local thumb = frame:GetThumbTexture()
pfUI.api.SkinArrowButton(up, "up")
pfUI.api.SkinArrowButton(down, "down")
if not frame.bg then
frame.bg = CreateFrame("Frame", nil, frame)
frame.bg:SetPoint("TOPLEFT", up, "BOTTOMLEFT", 0, -3)
frame.bg:SetPoint("BOTTOMRIGHT", down, "TOPRIGHT", 0, 3)
CreateBackdrop(frame.bg, nil, true)
end
if not frame.thumb then
thumb:SetTexture(nil)
frame.thumb = frame.bg:CreateTexture(nil, "ARTWORK")
frame.thumb:SetTexture(.8,.8,.8,.8)
frame.thumb:SetPoint("TOPLEFT", thumb, "TOPLEFT", 1, -4)
frame.thumb:SetPoint("BOTTOMRIGHT", thumb, "BOTTOMRIGHT", -1, 4)
end
-- always show parent frame
if always then
RunOOC(function()
parent:HookScript("OnHide", function() this:Show() end)
end)
end
end
-- [ CenterFrame ]
-- Clears points and centers a frame
-- 'frame' [frame] the frame that should be centered.
-- 'relativeFrame' [frame] frame that should be used for centering if not use ui parent.
function pfUI.api.CenterFrame(frame, relativeFrame)
frame:ClearAllPoints()
if relativeFrame then
frame:SetPoint("CENTER", relativeFrame, "CENTER", 0, 0)
else
frame:SetPoint("CENTER", UIParent, "CENTER", 0, 0)
end
end
-- [ StripTextures ]
-- Strips all textures off a frame.
-- 'frame' [frame] the frame that should be stripped.
-- 'layer' [string] texture layer.
function pfUI.api.StripTextures(frame, hide, layer)
if not frame then return end
for _,v in ipairs({frame:GetRegions()}) do
if v.SetTexture then
local check = true
if layer and v:GetDrawLayer() ~= layer then check = false end
if check then
if hide then
v:Hide()
else
v:SetTexture(nil)
end
end
end
end
end
function pfUI.api.SetAllPointsOffset(frame, parent, offset)
frame:SetPoint("TOPLEFT", parent, "TOPLEFT", offset, -offset)
frame:SetPoint("BOTTOMRIGHT", parent, "BOTTOMRIGHT", -offset, offset)
end
function pfUI.api.SkinCheckbox(frame, size)
if not frame then return end
frame:SetNormalTexture("")
frame:SetPushedTexture("")
frame:SetHighlightTexture("")
if size then
frame:SetSize(size, size)
end
CreateBackdrop(frame)
SetAllPointsOffset(frame.backdrop, frame, 4)
if frame.backdrop_border then
-- make sure the blizzard border doesn't overlap the checkmark
frame.backdrop_border:SetFrameLevel(frame.backdrop:GetFrameLevel())
end
end
function pfUI.api.SkinDropDown(frame, cr, cg, cb, useSmall)
if not frame then return end
StripTextures(frame)
CreateBackdrop(frame)
frame.backdrop:SetPoint("TOPLEFT", 15, -1)
frame.backdrop:SetPoint("BOTTOMRIGHT", -15, 6)
local button = _G[frame:GetName() .. "Button"]
button:SetNormalTexture(nil)
button:SetPushedTexture(nil)
button:SetHighlightTexture(nil)
button:SetDisabledTexture(nil)
button:SetAllPoints(frame.backdrop)
CreateBackdrop(button)
button.backdrop:ClearAllPoints()
button.backdrop:SetWidth(18)
button.backdrop:SetHeight(18)
button.backdrop:SetPoint("RIGHT", frame.backdrop, "RIGHT", -2, 0)
if not button.icon then
button.icon = button:CreateTexture(nil, "OVERLAY")
button.icon:SetTexture(pfUI.media["img:down"])
button.icon:SetVertexColor(1,.9,.1)
button.icon:SetAlpha(.8)
SetAllPointsOffset(button.icon, button.backdrop, 5)
end
if not cr or not cg or not cb then
cr, cg, cb = GetClassColor(UnitClassBase('player'))
end
SetHighlight(button, cr, cg, cb)
if not useSmall then
-- fix small width
button:Click() -- open list
local list_width = DropDownList1:GetWidth()
if frame:GetWidth() < list_width then
UIDropDownMenu_SetWidth(list_width, frame)
end
CloseDropDownMenus()
end
local funcc = button:GetScript("OnClick")
button:SetScript("OnClick", function()
if funcc then funcc() end
local DropDownListWidth = DropDownList1:GetWidth()
local DropDownFrameWidth = frame.backdrop:GetWidth()
if DropDownListWidth < DropDownFrameWidth then
local diff = DropDownFrameWidth - DropDownListWidth
DropDownList1:SetWidth(DropDownList1:GetWidth() + diff)
for i=1, UIDROPDOWNMENU_MAXBUTTONS do
_G["DropDownList1Button" .. i]:SetWidth(_G["DropDownList1Button" .. i]:GetWidth() + diff)
end
end
DropDownList1:SetPoint("TOPLEFT", frame.backdrop, "BOTTOMLEFT", 0, -4)
end)
frame.button = button
end
function pfUI.api.SkinTab(frame, fixed)
if not frame then return end
frame:SetHeight(20)
StripTextures(frame)
CreateBackdrop(frame)
if not fixed then
frame:SetScript("OnShow", function()
this:SetWidth(this:GetTextWidth() + 20)
if this.GetFontString and this:GetFontString() then
this:GetFontString():SetPoint("CENTER", 0, 0)
end
end)
end
end
function pfUI.api.SkinSlider(frame)
local orientation = frame:GetOrientation()
local thumb = frame:GetThumbTexture()
CreateBackdrop(frame, nil, true)
thumb:SetTexture(1, .82, 0)
for i,region in ipairs({frame:GetRegions()}) do
if region:GetObjectType() == 'FontString' then
local point, anchor, anchorPoint, x, y = region:GetPoint()
if orientation == 'VERTICAL' then
if string.find(anchorPoint, "TOP") then -- top text
region:ClearAllPoints()
region:SetPoint("BOTTOM", anchor, "TOP", 0, 4)
elseif string.find(anchorPoint, "BOTTOM") then -- bottom text
region:ClearAllPoints()
region:SetPoint("TOP", anchor, "BOTTOM", 0, -4)
end
anchor:SetHeight(anchor:GetHeight() - 4)
else
if string.find(anchorPoint, 'BOTTOM') then
region:SetPoint(point, anchor, anchorPoint, x, y - 6)
elseif string.find(anchorPoint, 'TOP') then
region:SetPoint(point, anchor, anchorPoint, x, y + 2)
end
end
end
end
if orientation == 'VERTICAL' then
frame:SetWidth(10)
thumb:SetHeight(22)
thumb:SetWidth(frame:GetWidth())
else
frame:SetHeight(10)
thumb:SetHeight(frame:GetHeight())
thumb:SetWidth(17)
end
end
-- [ Question Dialog ]
-- Creates a pfUI user dialog popup:
-- 'text' [string] text that will be displayed.
-- 'yes' [function] function that is triggered on 'Okay' button.
-- 'no' [function] function that is triggered on 'Cancel' button.
-- 'editbox' [bool] if set, a inputfield will be shown. it can be.
-- accessed with "GetParent().input".
function pfUI.api.CreateQuestionDialog(text, yes, no, editbox, onclose)
-- do not allow multiple instances of question dialogs
if _G["pfQuestionDialog"] and _G["pfQuestionDialog"]:IsShown() then
_G["pfQuestionDialog"]:Hide()
_G["pfQuestionDialog"] = nil
return
end
local yes, no = yes, no
local yescap, nocap = YES, NO
if yes and type(yes) == "table" then
yescap = yes[1]
yes = yes[2]
end
if no and type(no) == "table" then
nocap = no[1]
no = no[2]
end
if not text then text = "Are you sure?" end
local rawborder, border = GetBorderSize()
local padding = 15
-- frame
local question = CreateFrame("Frame", "pfQuestionDialog", UIParent)
question:ClearAllPoints()
question:SetPoint("CENTER", 0, 0)
question:SetFrameStrata("TOOLTIP")
question:SetMovable(true)
question:EnableMouse(true)
question:RegisterForDrag("LeftButton")
question:SetScript("OnDragStart",function()
this:StartMoving()
end)
question:SetScript("OnDragStop",function()
this:StopMovingOrSizing()
end)
question:SetScript("OnHide", onclose)
pfUI.api.CreateBackdrop(question, nil, nil, .85)
pfUI.api.CreateBackdropShadow(question)
-- text
question.text = question:CreateFontString("Status", "LOW", "GameFontNormal")
question.text:SetFontObject(GameFontWhite)
question.text:SetPoint("TOPLEFT", question, "TOPLEFT", padding, -padding)
question.text:SetPoint("TOPRIGHT", question, "TOPRIGHT", -padding, -padding)
question.text:SetText(text)
-- editbox
if editbox then
question.input = CreateFrame("EditBox", "pfQuestionDialogEdit", question)
pfUI.api.CreateBackdrop(question.input)
question.input:SetTextColor(.2,1,.8,1)
question.input:SetJustifyH("CENTER")
question.input:SetAutoFocus(false)
question.input:SetPoint("TOPLEFT", question.text, "BOTTOMLEFT", border, -padding)
question.input:SetPoint("TOPRIGHT", question.text, "BOTTOMRIGHT", -border, -padding)
question.input:SetHeight(20)
question.input:SetFontObject(GameFontNormal)
question.input:SetScript("OnEscapePressed", function() this:ClearFocus() end)
question.input:SetAutoFocus(true)
end
-- buttons
question.yes = CreateFrame("Button", "pfQuestionDialogYes", question, "UIPanelButtonTemplate")
pfUI.api.SkinButton(question.yes)
question.yes:SetSize(100, 22)
question.yes:SetText(yescap)
question.yes:SetScript("OnClick", function()
if yes then yes() end
this:GetParent():Hide()
end)
if question.input then
question.yes:SetPoint("TOPRIGHT", question.input, "BOTTOM", -3*border, -padding)
else
question.yes:SetPoint("TOPRIGHT", question.text, "BOTTOM", -3*border, -padding)
end
question.no = CreateFrame("Button", "pfQuestionDialogNo", question, "UIPanelButtonTemplate")
pfUI.api.SkinButton(question.no)
question.no:SetSize(100, 22)
question.no:SetText(nocap)
question.no:SetScript("OnClick", function()
if no then no() end
this:GetParent():Hide()
end)
if question.input then
question.no:SetPoint("TOPLEFT", question.input, "BOTTOM", 3*border, -padding)
else
question.no:SetPoint("TOPLEFT", question.text, "BOTTOM", 3*border, -padding)
end
question.close = CreateFrame("Button", "pfQuestionDialogClose", question)
question.close:SetPoint("TOPRIGHT", -border, -border)
pfUI.api.CreateBackdrop(question.close)
question.close:SetSize(10, 10)
question.close.texture = question.close:CreateTexture("pfQuestionDialogCloseTex")
question.close.texture:SetTexture(pfUI.media["img:close"])
question.close.texture:ClearAllPoints()
question.close.texture:SetAllPoints(question.close)
question.close.texture:SetVertexColor(1,.25,.25,1)
question.close:SetScript("OnEnter", function ()
this.backdrop:SetBackdropBorderColor(1,.25,.25,1)
end)
question.close:SetScript("OnLeave", function ()
pfUI.api.CreateBackdrop(this)
end)
question.close:SetScript("OnClick", function()
this:GetParent():Hide()
end)
-- resize window
local textspace = question.text:GetHeight() + padding
local inputspace = 0
if question.input then inputspace = question.input:GetHeight() + padding end
local buttonspace = question.no:GetHeight() + padding
question:SetHeight(textspace + inputspace + buttonspace + padding)
local width = 200
-- delay the auto sizing, to make sure the font rendering happened
RunNextFrame(function()
if question.text:GetStringWidth() > width then width = question.text:GetStringWidth() end
question:SetWidth(width + 2*padding)
end)
end
-- [ Question Dialog ]
-- Creates a pfUI infobox popup window:
-- 'text' [string] text that will be displayed.
-- 'time' [number] time in seconds till the popup will be faded
-- 'parent' [frame] frame which will be used as parent for the dialog (defaults to UIParent)
-- 'height' [number] manual height of the popup (defaults to 100)
function pfUI.api.CreateInfoBox(text, time, parent, height)
if not text then return end
if not time then time = 5 end
if not parent then parent = UIParent end
if not height then height = 100 end
local infobox = pfInfoBox
if not infobox then
infobox = CreateFrame("Button", "pfInfoBox", UIParent)
infobox:Hide()
infobox:SetScript("OnUpdate", function()
local time = infobox.lastshow + infobox.duration - GetTime()
infobox.timeout:SetValue(time)
if GetTime() > infobox.lastshow + infobox.duration then
infobox:SetAlpha(infobox:GetAlpha()-0.05)
if infobox:GetAlpha() <= 0.1 then
infobox:Hide()
infobox:SetAlpha(1)
end
elseif MouseIsOver(this) then
this:SetAlpha(max(0.4, this:GetAlpha() - .1))
else
this:SetAlpha(min(1, this:GetAlpha() + .1))
end
end)
infobox:SetScript("OnClick", function()
this:Hide()
end)
infobox.text = infobox:CreateFontString("Status", "HIGH", "GameFontNormal")
infobox.text:ClearAllPoints()
infobox.text:SetFontObject(GameFontWhite)
infobox.timeout = CreateFrame("StatusBar", nil, infobox)
infobox.timeout:SetStatusBarTexture(pfUI.media["img:bar"])
infobox.timeout:SetStatusBarColor(.3,1,.8,1)
infobox:ClearAllPoints()
infobox.text:SetAllPoints(infobox)
infobox.text:SetFont(pfUI.font_default, 14, "OUTLINE")
pfUI.api.CreateBackdrop(infobox)
infobox:SetPoint("TOP", 0, -25)
infobox.timeout:ClearAllPoints()
infobox.timeout:SetPoint("TOPLEFT", infobox, "TOPLEFT", 3, -3)
infobox.timeout:SetPoint("TOPRIGHT", infobox, "TOPRIGHT", -3, 3)
infobox.timeout:SetHeight(2)
end
infobox.text:SetText(text)
infobox.timeout:SetMinMaxValues(0, time)
infobox.timeout:SetValue(time)
infobox.duration = time
infobox.lastshow = GetTime()
infobox:SetSize(infobox.text:GetStringWidth() + 50, height)
infobox:SetParent(parent)
infobox:SetFrameStrata("FULLSCREEN_DIALOG")
infobox:Show()
end
function pfUI.api.SkinMoneyInputFrame(frame)
local gold_editbox = _G[frame:GetName().."Gold"]
StripTextures(gold_editbox, true, "BACKGROUND")
CreateBackdrop(gold_editbox, nil, true)
local goldIcon = GetNoNameObject(gold_editbox, "Texture", nil, "MoneyIcons")
goldIcon:Show()
goldIcon:ClearAllPoints()
goldIcon:SetPoint("LEFT", gold_editbox, "RIGHT", 2, 0)
local silver_editbox = _G[frame:GetName().."Silver"]
StripTextures(silver_editbox, true, "BACKGROUND")
CreateBackdrop(silver_editbox, nil, true)
silver_editbox:ClearAllPoints()
silver_editbox:SetPoint("LEFT", goldIcon, "RIGHT", 2, 0)
local silverIcon = GetNoNameObject(silver_editbox, "Texture", nil, "MoneyIcons")
silverIcon:Show()
silverIcon:ClearAllPoints()
silverIcon:SetPoint("LEFT", silver_editbox, "RIGHT", 2, 0)
local copper_editbox = _G[frame:GetName().."Copper"]
StripTextures(copper_editbox, true, "BACKGROUND")
CreateBackdrop(copper_editbox, nil, true)
copper_editbox:ClearAllPoints()
copper_editbox:SetPoint("LEFT", silverIcon, "RIGHT", 2, 0)
local copperIcon = GetNoNameObject(copper_editbox, "Texture", nil, "MoneyIcons")
copperIcon:Show()
copperIcon:ClearAllPoints()
copperIcon:SetPoint("LEFT", copper_editbox, "RIGHT", 2, 0)
end