You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

991 lines
35 KiB

--========================================================--
-- Scorpio UnitFrame FrameWork --
-- --
-- Author : kurapica125@outlook.com --
-- Create Date : 2020/06/09 --
--========================================================--
--========================================================--
Scorpio "Scorpio.Secure.UnitFrame" "1.0.0"
--========================================================--
do
------------------------------------------------------
-- Hover Spell Helper --
------------------------------------------------------
local _UnitFrameHoverSpellGroup
_UpdateGroupQueue = Queue()
_ActionType = {
Spell = {
type = "spell",
parse = function (spell)
if (type(spell) == "string" or type(spell) == "number") then
-- Only keep spell id
local name, _, _, _, _, _, spellId = GetSpellInfo(spell)
if name then return spellId, IsHarmfulSpell(name) end
end
error("Invalid spell name|id - "..tostring(spell), 3)
end,
content = "spell",
tranMacro = function (spell, with)
if GetSpellInfo(spell) then
return ("/%s %%unit\n/cast %s"):format(with, GetSpellInfo(spell))
end
end
},
Macro = {
type = "macro",
parse = function (macro)
if type(macro) == "string" then
macro = GetMacroIndexByName(macro)
end
if type(macro) == "number" and macro > 0 and GetMacroInfo(macro) then
return macro
end
error("Invalid macro name|index", 3)
end,
content = "macro"
},
MacroText = {
type = "macro",
parse = function (macroText)
if type(macroText) == "string" and strtrim(macroText) ~= "" then
return strtrim(macroText)
end
error("Invalid macro text", 3)
end,
content = "macrotext"
},
Item = {
type = "item",
parse = function (item)
if (type(item) == "string" or type(item) == "number") and GetItemInfo(item) then
return tonumber(select(GetItemInfo(item), 2):match('item:(%d+)'))
end
error("Invalid item|id|link", 3)
end,
content = "item",
tranMacro = function (item, with)
if GetItemInfo(item) then
return ("/%s %%unit\n/use %s"):format(with, GetItemInfo(item))
end
end
},
Menu = { type = "menu" },
Target = { type = "target" },
Focus = { type = "focus" },
Assist = { type = "assist" },
}
_SetupTemplate = [[self:SetAttribute("%s", %q)]]
_ClearTemplate = [[self:SetAttribute("%s", nil)]]
_EnterTemplate = [[self:SetBindingClick(true, "%s", self, "%s")]]
_LeaveTemplate = [[self:ClearBinding("%s")]]
_Key2Name = setmetatable(
{
["1"] = "one",
["2"] = "two",
["3"] = "three",
["4"] = "four",
["5"] = "five",
["6"] = "six",
["7"] = "seven",
["8"] = "eight",
["9"] = "nine",
["0"] = "zero",
[","] = "comma",
["."] = "period",
["/"] = "slash",
["`"] = "backtick ",
["["] = "leftbracket",
["]"] = "rightbracket",
["\\"] = "backslash",
["-"] = "minus",
["="] = "equals",
[";"] = "semicolon",
["'"] = "singlequote",
["ESCAPE"] = false,
["PRINTSCREEN"] = false,
["LSHIFT"] = false,
["RSHIFT"] = false,
["LCTRL"] = false,
["RCTRL"] = false,
["LALT"] = false,
["RALT"] = false,
["UNKNOWN"] = false,
},{
__index = function (self, key)
if type(key) == "string" then
return key:lower()
end
end
}
)
function parseBindKey(key)
local ret
if type(key) == "string" and strtrim(key) ~= "" then
key = strtrim(key):upper()
-- Check the tail key is "-"
if key:sub(-1) == "-" then
ret = "-"
else
ret = key:match("[^-]+$")
end
if not ret or ret == "" or not _Key2Name[ret] then return end
-- Remap mouse key
if ret == "LEFTBUTTON" then
ret = "BUTTON1"
elseif ret == "RIGHTBUTTON" then
ret = "BUTTON2"
elseif ret == "MIDDLEBUTTON" then
ret = "BUTTON3"
end
-- Remap option key
if key:find("SHIFT-") then
ret = "SHIFT-" .. ret
end
if key:find("CTRL-") then
ret = "CTRL-" .. ret
end
if key:find("ALT-") then
ret = "ALT-" .. ret
end
end
if not ret then error("Invalid binding key - " .. key, 3) end
return ret
end
function getBindingDB(group, type, content)
if not (_UnitFrameHoverSpellGroup and _UnitFrameHoverSpellGroup[group]) then return end
for key, set in pairs(_UnitFrameHoverSpellGroup[group]) do
if set["HarmAction"] == type and set["HarmContent"] == content then
return key, set["HarmWith"], true
elseif set["HelpAction"] == type and set["HelpContent"] == content then
return key, set["HelpWith"], false
end
end
end
function getBindingDB4Key(group, key, harmful)
local db = _UnitFrameHoverSpellGroup and _UnitFrameHoverSpellGroup[group] and _UnitFrameHoverSpellGroup[group][key]
if db then
local prev = harmful and "Harm" or "Help"
return db[prev.."Action"], db[prev.."Content"], db[prev.."With"]
end
end
function clearBindingDB(group, type, content)
local key, with, harmful= getBindingDB(group, type, content)
if key then
local db = _UnitFrameHoverSpellGroup[group][key]
local prev = harmful and "Harm" or "Help"
db[prev.."Action"] = nil
db[prev.."Content"] = nil
db[prev.."With"] = nil
if not next(db) then
_UnitFrameHoverSpellGroup[group][key] = nil
end
return queueGroupUpdate(group)
end
end
function clearBindingDB4Key(group, key)
if not _UnitFrameHoverSpellGroup then return end
if not _UnitFrameHoverSpellGroup[group] then
return false
end
if not key then
wipe(_UnitFrameHoverSpellGroup[group])
return true
end
if not _UnitFrameHoverSpellGroup[group][key] then
return false
end
_UnitFrameHoverSpellGroup[group][key] = nil
return queueGroupUpdate(group)
end
function saveBindngDB(group, key, type, content, with, harmful)
if not _UnitFrameHoverSpellGroup then return end
if not key then throw("No binding key is set.") end
if not type or not _ActionType[type] then throw("No action type is set.") end
if _ActionType[type].content and not content then throw("No action content is set.") end
-- one spell in one group only match one key
clearBindingDB(group, type, content)
_UnitFrameHoverSpellGroup[group] = _UnitFrameHoverSpellGroup[group] or {}
_UnitFrameHoverSpellGroup[group][key] = _UnitFrameHoverSpellGroup[group][key] or {}
local db = _UnitFrameHoverSpellGroup[group][key]
local prev = harmful and "Harm" or "Help"
db[prev.."Action"] = type
db[prev.."Content"] = content
db[prev.."With"] = with
return queueGroupUpdate(group)
end
function mapKey(key)
key = key:lower()
local isClk = false
local prev
-- Check tail key
if key:sub(-1) == "-" then
prev, key = key:sub(1, -2), key:sub(-1)
else
prev, key = key:match("(.-)([^-]+)$")
end
if key:match("button%d+") then
isClk = true
key = key:match("button(%d+)")
else
key = prev:gsub("-", "") .. _Key2Name[key]
prev = ""
end
return isClk, prev, key
end
function mapAction(action, content, with)
local actionSet = _ActionType[action]
if not actionSet then return end
if with and actionSet.tranMacro then
return "MacroText", actionSet.tranMacro(content, with)
else
return action, content
end
end
function getSnippet(group)
if not (_UnitFrameHoverSpellGroup and _UnitFrameHoverSpellGroup[group]) then return end
local setup = List()
local clear = List()
local enter = List()
local leave = List()
local isMouseClk, prev, kname, virtualKey, useVirtual, connect
local actionSet, tranType, tranContent
for key, set in pairs(_UnitFrameHoverSpellGroup[group]) do
useVirtual = false
isMouseClk, prev, kname = mapKey(key)
if not isMouseClk then
enter:Insert(_EnterTemplate:format(key, kname))
leave:Insert(_LeaveTemplate:format(key))
end
connect = isMouseClk and "" or "-"
if set.HarmAction and set.HelpAction then
useVirtual = true
end
if set.HarmAction then
if useVirtual then
virtualKey = "enemy" .. kname
setup:Insert(_SetupTemplate:format("harmbutton" .. connect .. kname, virtualKey))
clear:Insert(_ClearTemplate:format("harmbutton" .. connect .. kname))
virtualKey = "-" .. virtualKey
else
virtualKey = connect .. kname
end
tranType, tranContent = mapAction(set.HarmAction, set.HarmContent, set.HarmWith)
actionSet = _ActionType[tranType]
if actionSet then
setup:Insert(_SetupTemplate:format(prev .. "type" .. virtualKey, actionSet.type))
clear:Insert(_ClearTemplate:format(prev .. "type" .. virtualKey))
if actionSet.content and tranContent then
setup:Insert(_SetupTemplate:format(prev .. actionSet.content .. virtualKey, tranContent))
clear:Insert(_ClearTemplate:format(prev .. actionSet.content .. virtualKey))
end
end
end
if set.HelpAction then
if useVirtual then
virtualKey = "friend" .. kname
setup:Insert(_SetupTemplate:format("helpbutton" .. connect .. kname, virtualKey))
clear:Insert(_ClearTemplate:format("helpbutton" .. connect .. kname))
virtualKey = "-" .. virtualKey
else
virtualKey = connect .. kname
end
tranType, tranContent = mapAction(set.HelpAction, set.HelpContent, set.HelpWith)
actionSet = _ActionType[tranType]
if actionSet then
setup:Insert(_SetupTemplate:format(prev .. "type" .. virtualKey, actionSet.type))
clear:Insert(_ClearTemplate:format(prev .. "type" .. virtualKey))
if actionSet.content and tranContent then
setup:Insert(_SetupTemplate:format(prev .. actionSet.content .. virtualKey, tranContent))
clear:Insert(_ClearTemplate:format(prev .. actionSet.content .. virtualKey))
end
end
end
end
return setup:Join("\n"), clear:Join("\n"), enter:Join("\n"), leave:Join("\n")
end
------------------------------------------------------
-- Hover Spell Manager --
------------------------------------------------------
-- Manager Frame
_ManagerFrame = SecureFrame("Scorpio_UnitFrame_HoverSpellManager")
_ManagerFrame:Hide()
-- Init manger frame's enviroment
_ManagerFrame:Execute[[
Manager = self
_HoverOnUnitFrame = nil
_HoverOnUnitFrameLeaveSnippet = nil
_GroupMap = newtable()
_UnitMap = newtable()
_SetupSnippet = newtable()
_ClearSnippet = newtable()
_EnterSnippet = newtable()
_LeaveSnippet = newtable()
]]
-- Global script sinppet, keep all run at global enviroment
-- Init Snippet
InitSnippet = [[
local group = "%s"
local initFrame = Manager:GetFrameRef("InitUnitFrame")
if _HoverOnUnitFrame == initFrame and _HoverOnUnitFrameLeaveSnippet then
_HoverOnUnitFrame:UnregisterAutoHide()
Manager:RunFor(_HoverOnUnitFrame, _HoverOnUnitFrameLeaveSnippet)
_HoverOnUnitFrame = nil
_HoverOnUnitFrameLeaveSnippet = nil
end
_GroupMap[initFrame] = group
]]
-- Dispose Snippet
DisposeSnippet = [[
local group = "%s"
local disposeFrame = Manager:GetFrameRef("DisposeUnitFrame")
_GroupMap[disposeFrame] = nil
if _HoverOnUnitFrame == disposeFrame then
if _HoverOnUnitFrameLeaveSnippet then
_HoverOnUnitFrame:UnregisterAutoHide()
end
_HoverOnUnitFrame = nil
_HoverOnUnitFrameLeaveSnippet = nil
end
if _LeaveSnippet[group] then
Manager:RunFor(disposeFrame, _LeaveSnippet[group])
end
if _ClearSnippet[group] then
Manager:RunFor(disposeFrame, _ClearSnippet[group])
end
]]
-- OnEnter Snippet
-- Also keep clear & leave snippet for update using
OnEnterSnippet = [[
local group = _GroupMap[self]
if not group then return end
local unit = self:GetAttribute("unit")
if _HoverOnUnitFrame and _HoverOnUnitFrameLeaveSnippet and _HoverOnUnitFrame ~= self then
_HoverOnUnitFrame:UnregisterAutoHide()
Manager:RunFor(_HoverOnUnitFrame, _HoverOnUnitFrameLeaveSnippet)
if _HoverOnUnitFrame:GetAttribute("unit") then
_HoverOnUnitFrame:Show()
end
end
if _SetupSnippet[group] and _UnitMap[self] ~= unit then
_UnitMap[self] = unit
Manager:RunFor(self, _SetupSnippet[group]:gsub("%%unit", unit or ""))
end
_HoverOnUnitFrame = self
_HoverOnUnitFrameLeaveSnippet = _LeaveSnippet[group]
if _EnterSnippet[group] then
Manager:RunFor(self, _EnterSnippet[group])
end
if _HoverOnUnitFrameLeaveSnippet then
_HoverOnUnitFrame:RegisterAutoHide(0.25)
end
]]
-- OnLeave Snippet
OnLeaveSnippet = [[
local group = _GroupMap[self]
if not group then return end
if _HoverOnUnitFrame == self then
if _HoverOnUnitFrameLeaveSnippet then
_HoverOnUnitFrame:UnregisterAutoHide()
if _HoverOnUnitFrame:GetAttribute("unit") then
_HoverOnUnitFrame:Show()
end
end
_HoverOnUnitFrame = nil
_HoverOnUnitFrameLeaveSnippet = nil
end
if _LeaveSnippet[group] then
Manager:RunFor(self, _LeaveSnippet[group])
end
]]
-- OnHide Snippet
OnHideSnippet = [[
local group = _GroupMap[self]
if not group then return end
if _HoverOnUnitFrame ~= self then
return
end
if _HoverOnUnitFrameLeaveSnippet then
self:UnregisterAutoHide()
if self:GetAttribute("unit") then
self:Show()
end
end
_HoverOnUnitFrame = nil
_HoverOnUnitFrameLeaveSnippet = nil
if _LeaveSnippet[group] then
Manager:RunFor(self, _LeaveSnippet[group])
end
]]
-- Build Snippet for group
SetupGroupSnippet = [[
local group = "%s"
if _HoverOnUnitFrame and _GroupMap[_HoverOnUnitFrame] == group then
if _HoverOnUnitFrameLeaveSnippet then
_HoverOnUnitFrame:UnregisterAutoHide()
Manager:RunFor(_HoverOnUnitFrame, _HoverOnUnitFrameLeaveSnippet)
end
_HoverOnUnitFrame = nil
_HoverOnUnitFrameLeaveSnippet = nil
end
for frm, grp in pairs(_GroupMap) do
if grp == group then
_UnitMap[frm] = nil
if _ClearSnippet[group] then
Manager:RunFor(frm, _ClearSnippet[group])
end
end
end
_SetupSnippet[group] = %q
_ClearSnippet[group] = %q
_EnterSnippet[group] = %q
_LeaveSnippet[group] = %q
if _SetupSnippet[group] == "" then
_SetupSnippet[group]= nil
end
if _ClearSnippet[group] == "" then
_ClearSnippet[group]= nil
end
if _EnterSnippet[group] == "" then
_EnterSnippet[group]= nil
end
if _LeaveSnippet[group] == "" then
_LeaveSnippet[group]= nil
end
]]
-- Initialize unit frame
__NoCombat__()
function initUnitFrame(self, group, old)
if old then
_ManagerFrame:SetFrameRef("DisposeUnitFrame", self)
_ManagerFrame:Execute(DisposeSnippet:format(old:upper()))
end
if group then
_ManagerFrame:SetFrameRef("InitUnitFrame", self)
_ManagerFrame:Execute(InitSnippet:format(group:upper()))
end
end
-- Dispose unit frame, but since we can't really dispose the frame
-- Just keep the code, no use
__NoCombat__()
function removeUnitFrame(self, group)
_ManagerFrame:UnwrapScript(self, "OnEnter")
_ManagerFrame:UnwrapScript(self, "OnLeave")
_ManagerFrame:UnwrapScript(self, "OnHide")
_ManagerFrame:SetFrameRef("DisposeUnitFrame", self)
_ManagerFrame:Execute(DisposeSnippet:format(group))
end
function queueGroupUpdate(group)
if _UpdateGroupQueue[group] then return end
if _UpdateGroupQueue.Count == 0 then FireSystemEvent("SCORPIO_UNITFRAME_HOVER_GROUP_UPDATE") end
_UpdateGroupQueue[group]= true
_UpdateGroupQueue:Enqueue(group)
end
__Service__(true)
function ProcessGroupUpdate()
while true do
local group = _UpdateGroupQueue:Dequeue()
while group do
Continue()
NoCombat()
if _UpdateGroupQueue[group] then
_UpdateGroupQueue[group] = nil
Debug("[UnitFrame]Setup the secure snippets for group: %s", group)
_ManagerFrame:Execute(SetupGroupSnippet:format(group, getSnippet(group)))
end
group = _UpdateGroupQueue:Dequeue()
end
NextEvent("SCORPIO_UNITFRAME_HOVER_GROUP_UPDATE")
end
end
------------------------------------------------------
-- Module Event --
------------------------------------------------------
if _G.GetSpecialization then
-- Save in Spec
function OnLoad(self)
_SVData.Char.Spec:SetDefault {
UnitFrameHoverSpellGroup= {}
}
end
function OnSpecChanged(self)
_UnitFrameHoverSpellGroup = _SVData.Char.Spec.UnitFrameHoverSpellGroup
for grp in pairs(_UnitFrameHoverSpellGroup) do
if InCombatLockdown() then
queueGroupUpdate(grp)
else
Debug("[UnitFrame]Setup the secure snippets for group: %s", grp)
_ManagerFrame:Execute(SetupGroupSnippet:format(grp, getSnippet(grp)))
end
end
end
function OnQuit(self)
if _UnitFrameHoverSpellGroup then
for grp, db in pairs(_UnitFrameHoverSpellGroup) do
if not next(db) then
_UnitFrameHoverSpellGroup[grp] = nil
end
end
end
end
else
-- Save in Char
function OnLoad(self)
_SVData.Char:SetDefault {
UnitFrameHoverSpellGroup= {}
}
_UnitFrameHoverSpellGroup = _SVData.Char.UnitFrameHoverSpellGroup
for grp in pairs(_UnitFrameHoverSpellGroup) do
if InCombatLockdown() then
queueGroupUpdate(grp)
else
Debug("[UnitFrame]Setup the secure snippets for group: %s", grp)
_ManagerFrame:Execute(SetupGroupSnippet:format(grp, getSnippet(grp)))
end
end
end
function OnQuit(self)
if _UnitFrameHoverSpellGroup then
for grp, db in pairs(_UnitFrameHoverSpellGroup) do
if not next(db) then
_UnitFrameHoverSpellGroup[grp] = nil
end
end
end
end
end
end
--- The root unit frame widget class with hover spell casting
-- We can bind short keys to the hover spell group, each unit frame can have a group
--
-- UnitFrame.HoverSpellGroups["Default"].Spell["Holy Light"].With["target"].Key = "ctrl-f"
-- UnitFrame.HoverSpellGroups["Default"].MacroText["/cast Holy Light"].Key = "ctrl-f"
--
__Sealed__() __SecureTemplate__"SecureUnitButtonTemplate, SecureHandlerAttributeTemplate"
class "UnitFrame" (function(_ENV)
inherit "SecureButton"
extend "IUnitFrame"
import "System.Reactive"
------------------------------------------------------
-- Helper --
------------------------------------------------------
-- The secure snippet for the unit attribute changes
local _onattributechanged = [[
if name == "unit" then
if self:GetAttribute("deactivated") then
if value then self:SetAttribute("unit", nil) end
return
end
if type(value) == "string" then
value = strlower(value)
else
value = nil
end
local nounitwatch = self:GetAttribute("nounitwatch")
if value == "player" then
if not nounitwatch then
UnregisterUnitWatch(self)
end
self:Show()
elseif value then
if not nounitwatch then
RegisterUnitWatch(self)
else
self:Show()
end
else
if not nounitwatch then
UnregisterUnitWatch(self)
end
self:Hide()
end
self:CallMethod("ProcessUnitChange", value)
elseif name == "nounitwatch" then
local unit = self:GetAttribute("unit")
if unit and unit ~= "player" then
if value then
UnregisterUnitWatch(self)
else
RegisterUnitWatch(self)
end
end
end
]]
local function OnEnter(self)
return self:UpdateTooltip()
end
local function OnLeave(self)
GameTooltip:FadeOut()
end
------------------------------------------------------
-- Hover Spell Group Accessor --
------------------------------------------------------
__Sealed__() class "HoverSpellGroupAccessor" (function(_ENV)
local accessor
------------------------------------------------------
-- method --
------------------------------------------------------
function Reset(self)
return self.Group and clearBindingDB4Key(self.Group)
end
------------------------------------------------------
-- Proeprty --
------------------------------------------------------
--- The hover spell group
property "Group" { type = String }
--- The action type accessor
for name, set in pairs(_ActionType) do
if set.content then
__Indexer__(String + Number)
property(name) {
get = function(self, content)
self.Data.Type = name
self.Data.Content = content
self.Data.With = nil
return self
end,
}
else
property(name) {
get = function(self)
self.Data.Type = name
self.Data.Content = nil
self.Data.With = nil
return self
end
}
end
end
--- Get the with settings from the binding
property "With" {
get = function(self)
local type, ct = self.Data.Type, self.Data.Content
if type then
return (select(2, getBindingDB(self.Group, type, ct)))
end
end
}
--- Whether combine a 'target' action
property "WithTarget" {
get = function(self)
self.Data.With = "target"
return self
end
}
--- Whether combine a 'focus' action
property "WithFocus" {
get = function(self)
self.Data.With = "focus"
return self
end
}
--- Whether combine a 'assist' action
property "WithAssist" {
get = function(self)
self.Data.With = "assist"
return self
end
}
--- Gets/Sets the binding key
property "Key" {
throwable = true,
get = function(self)
local type, ct = self.Data.Type, self.Data.Content
if type then
return getBindingDB(self.Group, type, ct)
end
end,
set = function(self, value)
local type, ct = self.Data.Type, self.Data.Content
local harmful
if not type then
throw("Usage: UnitFrame.HoverSpellGroups[group].Action[content].Key = value - the action type not specified")
end
local action = _ActionType[type]
if action.content and not ct then
throw("Usage: UnitFrame.HoverSpellGroups[group].Action[content].Key = value - the action content not specified")
end
if action.parse then
ct, harmful = action.parse(ct)
end
if value == nil then
return clearBindingDB(self.Group, type, ct)
else
value = parseBindKey(value)
if not value then
throw("Usage: UnitFrame.HoverSpellGroups[group].Action[content].Key = value - the key value not valid")
end
local otype, oct, owith = getBindingDB4Key(value)
if type == otype and ct == oct and self.Data.With == owith then
return
end
return saveBindngDB(self.Group, value, type, ct, self.Data.With, harmful)
end
end,
}
------------------------------------------------------
-- Constructor --
------------------------------------------------------
__Arguments__{ NEString }
function __ctor(self, group)
self.Group = group:upper()
self.Data = {}
accessor = self
end
__Arguments__{ NEString}
function __exist(cls, group)
if accessor then
accessor.Group = group:upper()
wipe(accessor.Data)
return accessor
end
end
end)
------------------------------------------------------
-- Static Proeprty --
------------------------------------------------------
--- The hover spell group accessor
__Static__() __Indexer__(NEString)
property "HoverSpellGroups" {
get = function(self, name)
return HoverSpellGroupAccessor(name)
end,
}
------------------------------------------------------
-- Proeprty --
------------------------------------------------------
--- The unit attached to the unit frame
property "Unit" {
type = String,
set = function(self, unit)
if unit ~= self:GetAttribute("unit") then
self:SetAttribute("unit", unit)
end
end,
get = function(self)
return self:GetAttribute("unit")
end,
}
--- Whether enable the unit watch
property "UnitWatchEnabled" {
type = Boolean,
set = function(self, enabled)
if self.UnitWatchEnabled == enabled then return end
NoCombat(function() self:SetAttribute("nounitwatch", not enabled) end)
end,
get = function(self)
return not self:GetAttribute("nounitwatch")
end,
}
--- The refresh interval for special unit like 'targettarget'
property "Interval" { type = PositiveNumber, default = 0.5 }
--- The hover spell group
property "HoverSpellGroup" { type = String, handler = initUnitFrame }
------------------------------------------------------
-- Method --
------------------------------------------------------
__SecureMethod__()
function ProcessUnitChange(self, unit)
return self:OnUnitRefresh(unit)
end
function UpdateTooltip(self)
local unit = self:GetAttribute("unit")
if unit then
GameTooltip_SetDefaultAnchor(GameTooltip, self)
GameTooltip:SetUnit(unit)
local r, g, b = GameTooltip_UnitColor(unit)
_G.GameTooltipTextLeft1:SetTextColor(r, g, b)
end
end
------------------------------------------------------
-- Constructor --
------------------------------------------------------
function __ctor(self, ...)
-- Use * so those are default actions that can be overridden
self:SetAttribute("*type1", "target")
self:SetAttribute("shift-type1", "focus")
self:SetAttribute("*type2", "togglemenu")
self:RegisterForClicks("AnyUp")
self.OnEnter = self.OnEnter + OnEnter
self.OnLeave = self.OnLeave + OnLeave
_ManagerFrame:WrapScript(self, "OnEnter", OnEnterSnippet)
_ManagerFrame:WrapScript(self, "OnLeave", OnLeaveSnippet)
_ManagerFrame:WrapScript(self, "OnHide", OnHideSnippet)
-- Prepare for secure handler
self:SetAttribute("_onattributechanged", _onattributechanged)
-- The group maybe set by child class
-- normally should be done by the style system
return self.HoverSpellGroup and initUnitFrame(self, self.HoverSpellGroup)
end
end)