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.
10313 lines
322 KiB
10313 lines
322 KiB
|
|
local DF = _G ["DetailsFramework"]
|
|
if (not DF or not DetailsFrameworkCanLoad) then
|
|
return
|
|
end
|
|
|
|
local _
|
|
--> lua locals
|
|
local _rawset = rawset --> lua local
|
|
local _rawget = rawget --> lua local
|
|
local _setmetatable = setmetatable --> lua local
|
|
local _unpack = unpack --> lua local
|
|
local _type = type --> lua local
|
|
local _math_floor = math.floor --> lua local
|
|
local loadstring = loadstring --> lua local
|
|
|
|
local IS_WOW_PROJECT_MAINLINE = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE
|
|
local IS_WOW_PROJECT_NOT_MAINLINE = WOW_PROJECT_ID ~= WOW_PROJECT_MAINLINE
|
|
|
|
local PixelUtil = PixelUtil or DFPixelUtil
|
|
|
|
local UnitGroupRolesAssigned = DetailsFramework.UnitGroupRolesAssigned
|
|
|
|
local cleanfunction = function() end
|
|
local APIFrameFunctions
|
|
|
|
do
|
|
local metaPrototype = {
|
|
WidgetType = "panel",
|
|
SetHook = DF.SetHook,
|
|
RunHooksForWidget = DF.RunHooksForWidget,
|
|
|
|
dversion = DF.dversion,
|
|
}
|
|
|
|
--check if there's a metaPrototype already existing
|
|
if (_G[DF.GlobalWidgetControlNames["panel"]]) then
|
|
--get the already existing metaPrototype
|
|
local oldMetaPrototype = _G[DF.GlobalWidgetControlNames ["panel"]]
|
|
--check if is older
|
|
if ( (not oldMetaPrototype.dversion) or (oldMetaPrototype.dversion < DF.dversion) ) then
|
|
--the version is older them the currently loading one
|
|
--copy the new values into the old metatable
|
|
for funcName, _ in pairs(metaPrototype) do
|
|
oldMetaPrototype[funcName] = metaPrototype[funcName]
|
|
end
|
|
end
|
|
else
|
|
--first time loading the framework
|
|
_G[DF.GlobalWidgetControlNames ["panel"]] = metaPrototype
|
|
end
|
|
end
|
|
|
|
local PanelMetaFunctions = _G[DF.GlobalWidgetControlNames ["panel"]]
|
|
|
|
--> mixin for options functions
|
|
DF.OptionsFunctions = {
|
|
SetOption = function (self, optionName, optionValue)
|
|
if (self.options) then
|
|
self.options [optionName] = optionValue
|
|
else
|
|
self.options = {}
|
|
self.options [optionName] = optionValue
|
|
end
|
|
|
|
if (self.OnOptionChanged) then
|
|
DF:Dispatch (self.OnOptionChanged, self, optionName, optionValue)
|
|
end
|
|
end,
|
|
|
|
GetOption = function (self, optionName)
|
|
return self.options and self.options [optionName]
|
|
end,
|
|
|
|
GetAllOptions = function (self)
|
|
if (self.options) then
|
|
local optionsTable = {}
|
|
for key, _ in pairs (self.options) do
|
|
optionsTable [#optionsTable + 1] = key
|
|
end
|
|
return optionsTable
|
|
else
|
|
return {}
|
|
end
|
|
end,
|
|
|
|
BuildOptionsTable = function (self, defaultOptions, userOptions)
|
|
self.options = self.options or {}
|
|
DF.table.deploy (self.options, userOptions or {})
|
|
DF.table.deploy (self.options, defaultOptions or {})
|
|
end
|
|
}
|
|
|
|
--> default options for the frame layout
|
|
local default_framelayout_options = {
|
|
amount_per_line = 4,
|
|
start_x = 2,
|
|
start_y = -2,
|
|
is_vertical = false,
|
|
grow_right = true, --on vertical (if not grow next line left)
|
|
grow_down = true, --on horizontal (if not grow next line up)
|
|
anchor_to_child = false, --if true set the point to the previous frame instead of coordinate
|
|
anchor_point = "topleft",
|
|
anchor_relative = "topleft",
|
|
offset_x = 100,
|
|
offset_y = 20,
|
|
width = 0, --if bigger than 0, it will set the value
|
|
height = 0,
|
|
break_if_hidden = true, --stop if encounters a hidden frame
|
|
}
|
|
|
|
--> mixin for frame layout
|
|
DF.LayoutFrame = {
|
|
AnchorTo = function (self, anchor, point, x, y)
|
|
if (point == "top") then
|
|
self:ClearAllPoints()
|
|
self:SetPoint ("bottom", anchor, "top", x or 0, y or 0)
|
|
|
|
elseif (point == "bottom") then
|
|
self:ClearAllPoints()
|
|
self:SetPoint ("top", anchor, "bottom", x or 0, y or 0)
|
|
|
|
elseif (point == "left") then
|
|
self:ClearAllPoints()
|
|
self:SetPoint ("right", anchor, "left", x or 0, y or 0)
|
|
|
|
elseif (point == "right") then
|
|
self:ClearAllPoints()
|
|
self:SetPoint ("left", anchor, "right", x or 0, y or 0)
|
|
end
|
|
end,
|
|
|
|
ArrangeFrames = function (self, frameList, options)
|
|
|
|
if (not frameList) then
|
|
frameList = {self:GetChildren()}
|
|
end
|
|
|
|
options = options or {}
|
|
DF.table.deploy (options, default_framelayout_options)
|
|
|
|
local breakLine = options.amount_per_line + 1
|
|
local currentX, currentY = options.start_x, options.start_y
|
|
local offsetX, offsetY = options.offset_x, options.offset_y
|
|
local anchorPoint = options.anchor_point
|
|
local anchorAt = options.anchor_relative
|
|
local latestFrame = self
|
|
local firstRowFrame = frameList [1]
|
|
|
|
if (options.is_vertical) then
|
|
for i = 1, #frameList do
|
|
local thisFrame = frameList [i]
|
|
if (options.break_if_hidden and not thisFrame:IsShown()) then
|
|
break
|
|
end
|
|
thisFrame:ClearAllPoints()
|
|
|
|
if (options.anchor_to_child) then
|
|
if (i == breakLine) then
|
|
if (options.grow_right) then
|
|
thisFrame:SetPoint ("topleft", firstRowFrame, "topright", offsetX, 0)
|
|
else
|
|
thisFrame:SetPoint ("topright", firstRowFrame, "topleft", -offsetX, 0)
|
|
end
|
|
firstRowFrame = thisFrame
|
|
latestFrame = thisFrame
|
|
breakLine = breakLine + options.amount_per_line
|
|
else
|
|
thisFrame:SetPoint (anchorPoint, latestFrame, i == 1 and "topleft" or anchorAt, offsetX, i == 1 and 0 or offsetY)
|
|
latestFrame = thisFrame
|
|
end
|
|
else
|
|
if (i == breakLine) then
|
|
if (options.grow_right) then
|
|
currentX = currentX + offsetX
|
|
else
|
|
currentX = currentX - offsetX
|
|
end
|
|
currentY = options.start_y
|
|
|
|
firstRowFrame = thisFrame
|
|
breakLine = breakLine + options.amount_per_line
|
|
end
|
|
|
|
thisFrame:SetPoint (anchorPoint, self, anchorAt, currentX, currentY)
|
|
currentY = currentY - offsetY
|
|
end
|
|
end
|
|
|
|
else
|
|
for i = 1, #frameList do
|
|
local thisFrame = frameList [i]
|
|
if (options.break_if_hidden and not thisFrame:IsShown()) then
|
|
break
|
|
end
|
|
thisFrame:ClearAllPoints()
|
|
|
|
if (options.anchor_to_child) then
|
|
if (i == breakLine) then
|
|
if (options.grow_down) then
|
|
thisFrame:SetPoint ("topleft", firstRowFrame, "bottomleft", 0, -offsetY)
|
|
else
|
|
thisFrame:SetPoint ("bottomleft", firstRowFrame, "topleft", 0, offsetY)
|
|
end
|
|
firstRowFrame = thisFrame
|
|
latestFrame = thisFrame
|
|
breakLine = breakLine + options.amount_per_line
|
|
else
|
|
thisFrame:SetPoint (anchorPoint, latestFrame, i == 1 and "topleft" or anchorAt, i == 1 and 0 or offsetX, offsetY)
|
|
latestFrame = thisFrame
|
|
end
|
|
else
|
|
if (i == breakLine) then
|
|
if (options.grow_down) then
|
|
currentY = currentY - offsetY
|
|
else
|
|
currentY = currentY + offsetY
|
|
end
|
|
currentX = options.start_x
|
|
|
|
firstRowFrame = thisFrame
|
|
breakLine = breakLine + options.amount_per_line
|
|
end
|
|
|
|
thisFrame:SetPoint (anchorPoint, self, anchorAt, currentX, currentY)
|
|
currentX = currentX + offsetX
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
}
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
--> metatables
|
|
|
|
PanelMetaFunctions.__call = function (_table, value)
|
|
--> nothing to do
|
|
return true
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
--> members
|
|
|
|
--> tooltip
|
|
local gmember_tooltip = function (_object)
|
|
return _object:GetTooltip()
|
|
end
|
|
--> shown
|
|
local gmember_shown = function (_object)
|
|
return _object:IsShown()
|
|
end
|
|
--> backdrop color
|
|
local gmember_color = function (_object)
|
|
return _object.frame:GetBackdropColor()
|
|
end
|
|
--> backdrop table
|
|
local gmember_backdrop = function (_object)
|
|
return _object.frame:GetBackdrop()
|
|
end
|
|
--> frame width
|
|
local gmember_width = function (_object)
|
|
return _object.frame:GetWidth()
|
|
end
|
|
--> frame height
|
|
local gmember_height = function (_object)
|
|
return _object.frame:GetHeight()
|
|
end
|
|
--> locked
|
|
local gmember_locked = function (_object)
|
|
return _rawget (_object, "is_locked")
|
|
end
|
|
|
|
PanelMetaFunctions.GetMembers = PanelMetaFunctions.GetMembers or {}
|
|
PanelMetaFunctions.GetMembers ["tooltip"] = gmember_tooltip
|
|
PanelMetaFunctions.GetMembers ["shown"] = gmember_shown
|
|
PanelMetaFunctions.GetMembers ["color"] = gmember_color
|
|
PanelMetaFunctions.GetMembers ["backdrop"] = gmember_backdrop
|
|
PanelMetaFunctions.GetMembers ["width"] = gmember_width
|
|
PanelMetaFunctions.GetMembers ["height"] = gmember_height
|
|
PanelMetaFunctions.GetMembers ["locked"] = gmember_locked
|
|
|
|
PanelMetaFunctions.__index = function (_table, _member_requested)
|
|
|
|
local func = PanelMetaFunctions.GetMembers [_member_requested]
|
|
if (func) then
|
|
return func (_table, _member_requested)
|
|
end
|
|
|
|
local fromMe = _rawget (_table, _member_requested)
|
|
if (fromMe) then
|
|
return fromMe
|
|
end
|
|
|
|
return PanelMetaFunctions [_member_requested]
|
|
end
|
|
|
|
|
|
--> tooltip
|
|
local smember_tooltip = function (_object, _value)
|
|
return _object:SetTooltip (_value)
|
|
end
|
|
--> show
|
|
local smember_show = function (_object, _value)
|
|
if (_value) then
|
|
return _object:Show()
|
|
else
|
|
return _object:Hide()
|
|
end
|
|
end
|
|
--> hide
|
|
local smember_hide = function (_object, _value)
|
|
if (not _value) then
|
|
return _object:Show()
|
|
else
|
|
return _object:Hide()
|
|
end
|
|
end
|
|
--> backdrop color
|
|
local smember_color = function (_object, _value)
|
|
local _value1, _value2, _value3, _value4 = DF:ParseColors (_value)
|
|
return _object:SetBackdropColor (_value1, _value2, _value3, _value4)
|
|
end
|
|
--> frame width
|
|
local smember_width = function (_object, _value)
|
|
return _object.frame:SetWidth (_value)
|
|
end
|
|
--> frame height
|
|
local smember_height = function (_object, _value)
|
|
return _object.frame:SetHeight (_value)
|
|
end
|
|
|
|
--> locked
|
|
local smember_locked = function (_object, _value)
|
|
if (_value) then
|
|
_object.frame:SetMovable (false)
|
|
return _rawset (_object, "is_locked", true)
|
|
else
|
|
_object.frame:SetMovable (true)
|
|
_rawset (_object, "is_locked", false)
|
|
return
|
|
end
|
|
end
|
|
|
|
--> backdrop
|
|
local smember_backdrop = function (_object, _value)
|
|
return _object.frame:SetBackdrop (_value)
|
|
end
|
|
|
|
--> close with right button
|
|
local smember_right_close = function (_object, _value)
|
|
return _rawset (_object, "rightButtonClose", _value)
|
|
end
|
|
|
|
PanelMetaFunctions.SetMembers = PanelMetaFunctions.SetMembers or {}
|
|
PanelMetaFunctions.SetMembers["tooltip"] = smember_tooltip
|
|
PanelMetaFunctions.SetMembers["show"] = smember_show
|
|
PanelMetaFunctions.SetMembers["hide"] = smember_hide
|
|
PanelMetaFunctions.SetMembers["color"] = smember_color
|
|
PanelMetaFunctions.SetMembers["backdrop"] = smember_backdrop
|
|
PanelMetaFunctions.SetMembers["width"] = smember_width
|
|
PanelMetaFunctions.SetMembers["height"] = smember_height
|
|
PanelMetaFunctions.SetMembers["locked"] = smember_locked
|
|
PanelMetaFunctions.SetMembers["close_with_right"] = smember_right_close
|
|
|
|
PanelMetaFunctions.__newindex = function (_table, _key, _value)
|
|
local func = PanelMetaFunctions.SetMembers [_key]
|
|
if (func) then
|
|
return func (_table, _value)
|
|
else
|
|
return _rawset (_table, _key, _value)
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
--> methods
|
|
|
|
--> right click to close
|
|
function PanelMetaFunctions:CreateRightClickLabel (textType, w, h, close_text)
|
|
local text
|
|
w = w or 20
|
|
h = h or 20
|
|
|
|
if (close_text) then
|
|
text = close_text
|
|
else
|
|
if (textType) then
|
|
textType = string.lower (textType)
|
|
if (textType == "short") then
|
|
text = "close window"
|
|
elseif (textType == "medium") then
|
|
text = "close window"
|
|
elseif (textType == "large") then
|
|
text = "close window"
|
|
end
|
|
else
|
|
text = "close window"
|
|
end
|
|
end
|
|
|
|
return DF:NewLabel (self, _, "$parentRightMouseToClose", nil, "|TInterface\\TUTORIALFRAME\\UI-TUTORIAL-FRAME:"..w..":"..h..":0:1:512:512:8:70:328:409|t " .. text)
|
|
end
|
|
|
|
--> show & hide
|
|
function PanelMetaFunctions:Show()
|
|
self.frame:Show()
|
|
|
|
end
|
|
function PanelMetaFunctions:Hide()
|
|
self.frame:Hide()
|
|
|
|
end
|
|
|
|
-- setpoint
|
|
function PanelMetaFunctions:SetPoint (v1, v2, v3, v4, v5)
|
|
v1, v2, v3, v4, v5 = DF:CheckPoints (v1, v2, v3, v4, v5, self)
|
|
if (not v1) then
|
|
print ("Invalid parameter for SetPoint")
|
|
return
|
|
end
|
|
return self.widget:SetPoint (v1, v2, v3, v4, v5)
|
|
end
|
|
|
|
-- sizes
|
|
function PanelMetaFunctions:SetSize (w, h)
|
|
if (w) then
|
|
self.frame:SetWidth (w)
|
|
end
|
|
if (h) then
|
|
self.frame:SetHeight (h)
|
|
end
|
|
end
|
|
|
|
-- clear
|
|
function PanelMetaFunctions:HideWidgets()
|
|
for widgetName, widgetSelf in pairs (self) do
|
|
if (type (widgetSelf) == "table" and widgetSelf.dframework) then
|
|
widgetSelf:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
-- backdrop
|
|
function PanelMetaFunctions:SetBackdrop (background, edge, tilesize, edgesize, tile, left, right, top, bottom)
|
|
|
|
if (_type (background) == "boolean" and not background) then
|
|
return self.frame:SetBackdrop (nil)
|
|
|
|
elseif (_type (background) == "table") then
|
|
self.frame:SetBackdrop (background)
|
|
|
|
else
|
|
local currentBackdrop = self.frame:GetBackdrop() or {edgeFile="Interface\\DialogFrame\\UI-DialogBox-Border", bgFile="Interface\\DialogFrame\\UI-DialogBox-Background", tile=true, tileSize=16, edgeSize=16, insets={left=1, right=0, top=0, bottom=0}}
|
|
currentBackdrop.bgFile = background or currentBackdrop.bgFile
|
|
currentBackdrop.edgeFile = edgeFile or currentBackdrop.edgeFile
|
|
currentBackdrop.tileSize = tilesize or currentBackdrop.tileSize
|
|
currentBackdrop.edgeSize = edgesize or currentBackdrop.edgeSize
|
|
currentBackdrop.tile = tile or currentBackdrop.tile
|
|
currentBackdrop.insets.left = left or currentBackdrop.insets.left
|
|
currentBackdrop.insets.right = left or currentBackdrop.insets.right
|
|
currentBackdrop.insets.top = left or currentBackdrop.insets.top
|
|
currentBackdrop.insets.bottom = left or currentBackdrop.insets.bottom
|
|
self.frame:SetBackdrop (currentBackdrop)
|
|
end
|
|
end
|
|
|
|
-- backdropcolor
|
|
function PanelMetaFunctions:SetBackdropColor (color, arg2, arg3, arg4)
|
|
if (arg2) then
|
|
self.frame:SetBackdropColor (color, arg2, arg3, arg4 or 1)
|
|
else
|
|
local _value1, _value2, _value3, _value4 = DF:ParseColors (color)
|
|
self.frame:SetBackdropColor (_value1, _value2, _value3, _value4)
|
|
end
|
|
end
|
|
|
|
-- border color
|
|
function PanelMetaFunctions:SetBackdropBorderColor (color, arg2, arg3, arg4)
|
|
if (arg2) then
|
|
return self.frame:SetBackdropBorderColor (color, arg2, arg3, arg4)
|
|
end
|
|
local _value1, _value2, _value3, _value4 = DF:ParseColors (color)
|
|
self.frame:SetBackdropBorderColor (_value1, _value2, _value3, _value4)
|
|
end
|
|
|
|
-- tooltip
|
|
function PanelMetaFunctions:SetTooltip (tooltip)
|
|
if (tooltip) then
|
|
return _rawset (self, "have_tooltip", tooltip)
|
|
else
|
|
return _rawset (self, "have_tooltip", nil)
|
|
end
|
|
end
|
|
function PanelMetaFunctions:GetTooltip()
|
|
return _rawget (self, "have_tooltip")
|
|
end
|
|
|
|
-- frame levels
|
|
function PanelMetaFunctions:GetFrameLevel()
|
|
return self.widget:GetFrameLevel()
|
|
end
|
|
function PanelMetaFunctions:SetFrameLevel (level, frame)
|
|
if (not frame) then
|
|
return self.widget:SetFrameLevel (level)
|
|
else
|
|
local framelevel = frame:GetFrameLevel (frame) + level
|
|
return self.widget:SetFrameLevel (framelevel)
|
|
end
|
|
end
|
|
|
|
-- frame stratas
|
|
function PanelMetaFunctions:SetFrameStrata()
|
|
return self.widget:GetFrameStrata()
|
|
end
|
|
function PanelMetaFunctions:SetFrameStrata (strata)
|
|
if (_type (strata) == "table") then
|
|
self.widget:SetFrameStrata (strata:GetFrameStrata())
|
|
else
|
|
self.widget:SetFrameStrata (strata)
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
--> scripts
|
|
|
|
local OnEnter = function (frame)
|
|
local capsule = frame.MyObject
|
|
local kill = capsule:RunHooksForWidget ("OnEnter", frame, capsule)
|
|
if (kill) then
|
|
return
|
|
end
|
|
|
|
if (frame.MyObject.have_tooltip) then
|
|
GameCooltip2:Reset()
|
|
GameCooltip2:SetType ("tooltip")
|
|
GameCooltip2:SetColor ("main", "transparent")
|
|
GameCooltip2:AddLine (frame.MyObject.have_tooltip)
|
|
GameCooltip2:SetOwner (frame)
|
|
GameCooltip2:ShowCooltip()
|
|
end
|
|
end
|
|
|
|
local OnLeave = function (frame)
|
|
local capsule = frame.MyObject
|
|
local kill = capsule:RunHooksForWidget ("OnLeave", frame, capsule)
|
|
if (kill) then
|
|
return
|
|
end
|
|
|
|
if (frame.MyObject.have_tooltip) then
|
|
GameCooltip2:ShowMe (false)
|
|
end
|
|
|
|
end
|
|
|
|
local OnHide = function (frame)
|
|
local capsule = frame.MyObject
|
|
local kill = capsule:RunHooksForWidget ("OnHide", frame, capsule)
|
|
if (kill) then
|
|
return
|
|
end
|
|
end
|
|
|
|
local OnShow = function (frame)
|
|
local capsule = frame.MyObject
|
|
local kill = capsule:RunHooksForWidget ("OnShow", frame, capsule)
|
|
if (kill) then
|
|
return
|
|
end
|
|
end
|
|
|
|
local OnMouseDown = function (frame, button)
|
|
local capsule = frame.MyObject
|
|
local kill = capsule:RunHooksForWidget ("OnMouseDown", frame, button, capsule)
|
|
if (kill) then
|
|
return
|
|
end
|
|
|
|
if (frame.MyObject.container == UIParent) then
|
|
if (not frame.isLocked and frame:IsMovable()) then
|
|
frame.isMoving = true
|
|
frame:StartMoving()
|
|
end
|
|
|
|
elseif (not frame.MyObject.container.isLocked and frame.MyObject.container:IsMovable()) then
|
|
if (not frame.isLocked and frame:IsMovable()) then
|
|
frame.MyObject.container.isMoving = true
|
|
frame.MyObject.container:StartMoving()
|
|
end
|
|
end
|
|
|
|
|
|
end
|
|
|
|
local OnMouseUp = function (frame, button)
|
|
local capsule = frame.MyObject
|
|
local kill = capsule:RunHooksForWidget ("OnMouseUp", frame, button, capsule)
|
|
if (kill) then
|
|
return
|
|
end
|
|
|
|
if (button == "RightButton" and frame.MyObject.rightButtonClose) then
|
|
frame.MyObject:Hide()
|
|
end
|
|
|
|
if (frame.MyObject.container == UIParent) then
|
|
if (frame.isMoving) then
|
|
frame:StopMovingOrSizing()
|
|
frame.isMoving = false
|
|
end
|
|
else
|
|
if (frame.MyObject.container.isMoving) then
|
|
frame.MyObject.container:StopMovingOrSizing()
|
|
frame.MyObject.container.isMoving = false
|
|
end
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------
|
|
--> object constructor
|
|
function DF:CreatePanel (parent, w, h, backdrop, backdropcolor, bordercolor, member, name)
|
|
return DF:NewPanel (parent, parent, name, member, w, h, backdrop, backdropcolor, bordercolor)
|
|
end
|
|
|
|
function DF:NewPanel (parent, container, name, member, w, h, backdrop, backdropcolor, bordercolor)
|
|
|
|
if (not name) then
|
|
name = "DetailsFrameworkPanelNumber" .. DF.PanelCounter
|
|
DF.PanelCounter = DF.PanelCounter + 1
|
|
|
|
elseif (not parent) then
|
|
parent = UIParent
|
|
end
|
|
if (not container) then
|
|
container = parent
|
|
end
|
|
|
|
if (name:find ("$parent")) then
|
|
name = name:gsub ("$parent", parent:GetName())
|
|
end
|
|
|
|
local PanelObject = {type = "panel", dframework = true}
|
|
|
|
if (member) then
|
|
parent [member] = PanelObject
|
|
end
|
|
|
|
if (parent.dframework) then
|
|
parent = parent.widget
|
|
end
|
|
if (container.dframework) then
|
|
container = container.widget
|
|
end
|
|
|
|
--> default members:
|
|
--> misc
|
|
PanelObject.is_locked = true
|
|
PanelObject.container = container
|
|
PanelObject.rightButtonClose = false
|
|
|
|
PanelObject.frame = CreateFrame ("frame", name, parent,"BackdropTemplate")
|
|
PanelObject.frame:SetSize (100, 100)
|
|
PanelObject.frame.Gradient = {
|
|
["OnEnter"] = {0.3, 0.3, 0.3, 0.5},
|
|
["OnLeave"] = {0.9, 0.7, 0.7, 1}
|
|
}
|
|
PanelObject.frame:SetBackdrop ({bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]], edgeFile = "Interface\\DialogFrame\\UI-DialogBox-Border", edgeSize = 10, tileSize = 64, tile = true})
|
|
|
|
PanelObject.widget = PanelObject.frame
|
|
|
|
if (not APIFrameFunctions) then
|
|
APIFrameFunctions = {}
|
|
local idx = getmetatable (PanelObject.frame).__index
|
|
for funcName, funcAddress in pairs (idx) do
|
|
if (not PanelMetaFunctions [funcName]) then
|
|
PanelMetaFunctions [funcName] = function (object, ...)
|
|
local x = loadstring ( "return _G['"..object.frame:GetName().."']:"..funcName.."(...)")
|
|
return x (...)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
PanelObject.frame:SetWidth (w or 100)
|
|
PanelObject.frame:SetHeight (h or 100)
|
|
|
|
PanelObject.frame.MyObject = PanelObject
|
|
|
|
PanelObject.HookList = {
|
|
OnEnter = {},
|
|
OnLeave = {},
|
|
OnHide = {},
|
|
OnShow = {},
|
|
OnMouseDown = {},
|
|
OnMouseUp = {},
|
|
}
|
|
|
|
--> hooks
|
|
PanelObject.frame:SetScript ("OnEnter", OnEnter)
|
|
PanelObject.frame:SetScript ("OnLeave", OnLeave)
|
|
PanelObject.frame:SetScript ("OnHide", OnHide)
|
|
PanelObject.frame:SetScript ("OnShow", OnShow)
|
|
PanelObject.frame:SetScript ("OnMouseDown", OnMouseDown)
|
|
PanelObject.frame:SetScript ("OnMouseUp", OnMouseUp)
|
|
|
|
_setmetatable (PanelObject, PanelMetaFunctions)
|
|
|
|
if (backdrop) then
|
|
PanelObject:SetBackdrop (backdrop)
|
|
elseif (_type (backdrop) == "boolean") then
|
|
PanelObject.frame:SetBackdrop (nil)
|
|
end
|
|
|
|
if (backdropcolor) then
|
|
PanelObject:SetBackdropColor (backdropcolor)
|
|
end
|
|
|
|
if (bordercolor) then
|
|
PanelObject:SetBackdropBorderColor (bordercolor)
|
|
end
|
|
|
|
return PanelObject
|
|
end
|
|
|
|
------------fill panel
|
|
|
|
local button_on_enter = function (self)
|
|
self.MyObject._icon:SetBlendMode ("ADD")
|
|
if (self.MyObject.onenter_func) then
|
|
pcall (self.MyObject.onenter_func, self.MyObject)
|
|
end
|
|
end
|
|
local button_on_leave = function (self)
|
|
self.MyObject._icon:SetBlendMode ("BLEND")
|
|
if (self.MyObject.onleave_func) then
|
|
pcall (self.MyObject.onleave_func, self.MyObject)
|
|
end
|
|
end
|
|
|
|
local add_row = function (self, t, need_update)
|
|
local index = #self.rows+1
|
|
|
|
local thisrow = DF:NewPanel (self, self, "$parentHeader_" .. self._name .. index, nil, 1, 20)
|
|
thisrow.backdrop = {bgFile = [[Interface\DialogFrame\UI-DialogBox-Gold-Background]]}
|
|
thisrow.color = "silver"
|
|
thisrow.type = t.type
|
|
thisrow.func = t.func
|
|
thisrow.name = t.name
|
|
thisrow.notext = t.notext
|
|
thisrow.icon = t.icon
|
|
thisrow.iconalign = t.iconalign
|
|
|
|
thisrow.hidden = t.hidden or false
|
|
|
|
thisrow.onenter = t.onenter
|
|
thisrow.onleave = t.onleave
|
|
|
|
local text = DF:NewLabel (thisrow, nil, self._name .. "$parentLabel" .. index, "text")
|
|
text:SetPoint ("left", thisrow, "left", 2, 0)
|
|
text:SetText (t.name)
|
|
|
|
tinsert (self._raw_rows, t)
|
|
tinsert (self.rows, thisrow)
|
|
|
|
if (need_update) then
|
|
self:AlignRows()
|
|
end
|
|
end
|
|
|
|
local align_rows = function (self)
|
|
|
|
local rows_shown = 0
|
|
for index, row in ipairs (self.rows) do
|
|
if (not row.hidden) then
|
|
rows_shown = rows_shown + 1
|
|
end
|
|
end
|
|
|
|
local cur_width = 0
|
|
local row_width = self._width / max (rows_shown, 0.0001)
|
|
|
|
|
|
local sindex = 1
|
|
|
|
wipe (self._anchors)
|
|
|
|
for index, row in ipairs (self.rows) do
|
|
if (not row.hidden) then
|
|
if (self._autowidth) then
|
|
if (self._raw_rows [index].width) then
|
|
row.width = self._raw_rows [index].width
|
|
else
|
|
row.width = row_width
|
|
end
|
|
row:SetPoint ("topleft", self, "topleft", cur_width, 0)
|
|
tinsert (self._anchors, cur_width)
|
|
cur_width = cur_width + row_width + 1
|
|
else
|
|
row:SetPoint ("topleft", self, "topleft", cur_width, 0)
|
|
row.width = self._raw_rows [index].width
|
|
tinsert (self._anchors, cur_width)
|
|
cur_width = cur_width + self._raw_rows [index].width + 1
|
|
end
|
|
|
|
row:Show()
|
|
|
|
local type = row.type
|
|
|
|
if (type == "text") then
|
|
for i = 1, #self.scrollframe.lines do
|
|
local line = self.scrollframe.lines [i]
|
|
local text = tremove (line.text_available)
|
|
if (not text) then
|
|
self:CreateRowText (line)
|
|
text = tremove (line.text_available)
|
|
end
|
|
tinsert (line.text_inuse, text)
|
|
text:SetPoint ("left", line, "left", self._anchors [#self._anchors], 0)
|
|
text:SetWidth (row.width)
|
|
|
|
DF:SetFontSize (text, row.textsize or 10)
|
|
text:SetJustifyH (row.textalign or "left")
|
|
end
|
|
elseif (type == "entry") then
|
|
for i = 1, #self.scrollframe.lines do
|
|
local line = self.scrollframe.lines [i]
|
|
local entry = tremove (line.entry_available)
|
|
if (not entry) then
|
|
self:CreateRowEntry (line)
|
|
entry = tremove (line.entry_available)
|
|
end
|
|
tinsert (line.entry_inuse, entry)
|
|
entry:SetPoint ("left", line, "left", self._anchors [#self._anchors], 0)
|
|
if (sindex == rows_shown) then
|
|
entry:SetWidth (row.width - 25)
|
|
else
|
|
entry:SetWidth (row.width)
|
|
end
|
|
entry.func = row.func
|
|
|
|
entry.onenter_func = nil
|
|
entry.onleave_func = nil
|
|
|
|
if (row.onenter) then
|
|
entry.onenter_func = row.onenter
|
|
end
|
|
if (row.onleave) then
|
|
entry.onleave_func = row.onleave
|
|
end
|
|
end
|
|
|
|
elseif (type == "checkbox") then
|
|
for i = 1, #self.scrollframe.lines do
|
|
local line = self.scrollframe.lines [i]
|
|
local checkbox = tremove (line.checkbox_available)
|
|
if (not checkbox) then
|
|
self:CreateCheckbox (line)
|
|
checkbox = tremove (line.checkbox_available)
|
|
end
|
|
|
|
tinsert (line.checkbox_inuse, checkbox)
|
|
|
|
checkbox:SetPoint ("left", line, "left", self._anchors [#self._anchors] + ((row.width - 20) / 2), 0)
|
|
if (sindex == rows_shown) then
|
|
checkbox:SetWidth (20)
|
|
--checkbox:SetWidth (row.width - 25)
|
|
else
|
|
checkbox:SetWidth (20)
|
|
end
|
|
|
|
checkbox.onenter_func = nil
|
|
checkbox.onleave_func = nil
|
|
end
|
|
|
|
elseif (type == "button") then
|
|
for i = 1, #self.scrollframe.lines do
|
|
local line = self.scrollframe.lines [i]
|
|
local button = tremove (line.button_available)
|
|
if (not button) then
|
|
self:CreateRowButton (line)
|
|
button = tremove (line.button_available)
|
|
end
|
|
tinsert (line.button_inuse, button)
|
|
button:SetPoint ("left", line, "left", self._anchors [#self._anchors], 0)
|
|
if (sindex == rows_shown) then
|
|
button:SetWidth (row.width - 25)
|
|
else
|
|
button:SetWidth (row.width)
|
|
end
|
|
|
|
if (row.icon) then
|
|
button._icon.texture = row.icon
|
|
button._icon:ClearAllPoints()
|
|
if (row.iconalign) then
|
|
if (row.iconalign == "center") then
|
|
button._icon:SetPoint ("center", button, "center")
|
|
elseif (row.iconalign == "right") then
|
|
button._icon:SetPoint ("right", button, "right")
|
|
end
|
|
else
|
|
button._icon:SetPoint ("left", button, "left")
|
|
end
|
|
end
|
|
|
|
if (row.name and not row.notext) then
|
|
button._text:SetPoint ("left", button._icon, "right", 2, 0)
|
|
button._text.text = row.name
|
|
end
|
|
|
|
button.onenter_func = nil
|
|
button.onleave_func = nil
|
|
|
|
if (row.onenter) then
|
|
button.onenter_func = row.onenter
|
|
end
|
|
if (row.onleave) then
|
|
button.onleave_func = row.onleave
|
|
end
|
|
|
|
end
|
|
elseif (type == "icon") then
|
|
for i = 1, #self.scrollframe.lines do
|
|
local line = self.scrollframe.lines [i]
|
|
local icon = tremove (line.icon_available)
|
|
if (not icon) then
|
|
self:CreateRowIcon (line)
|
|
icon = tremove (line.icon_available)
|
|
end
|
|
tinsert (line.icon_inuse, icon)
|
|
icon:SetPoint ("left", line, "left", self._anchors [#self._anchors] + ( ((row.width or 22) - 22) / 2), 0)
|
|
icon.func = row.func
|
|
end
|
|
|
|
elseif (type == "texture") then
|
|
for i = 1, #self.scrollframe.lines do
|
|
local line = self.scrollframe.lines [i]
|
|
local texture = tremove (line.texture_available)
|
|
if (not texture) then
|
|
self:CreateRowTexture (line)
|
|
texture = tremove (line.texture_available)
|
|
end
|
|
tinsert (line.texture_inuse, texture)
|
|
texture:SetPoint ("left", line, "left", self._anchors [#self._anchors] + ( ((row.width or 22) - 22) / 2), 0)
|
|
end
|
|
|
|
end
|
|
|
|
sindex = sindex + 1
|
|
else
|
|
row:Hide()
|
|
end
|
|
end
|
|
|
|
if (#self.rows > 0) then
|
|
if (self._autowidth) then
|
|
self.rows [#self.rows]:SetWidth (row_width - rows_shown + 1)
|
|
else
|
|
self.rows [#self.rows]:SetWidth (self._raw_rows [rows_shown].width - rows_shown + 1)
|
|
end
|
|
end
|
|
|
|
self.showing_amt = rows_shown
|
|
end
|
|
|
|
local update_rows = function (self, updated_rows)
|
|
|
|
for i = 1, #updated_rows do
|
|
local t = updated_rows [i]
|
|
local raw = self._raw_rows [i]
|
|
|
|
if (not raw) then
|
|
self:AddRow (t)
|
|
else
|
|
raw.name = t.name
|
|
raw.hidden = t.hidden or false
|
|
raw.textsize = t.textsize
|
|
raw.textalign = t.textalign
|
|
|
|
local widget = self.rows [i]
|
|
widget.name = t.name
|
|
widget.textsize = t.textsize
|
|
widget.textalign = t.textalign
|
|
widget.hidden = t.hidden or false
|
|
|
|
--
|
|
widget.onenter = t.onenter
|
|
widget.onleave = t.onleave
|
|
--
|
|
|
|
widget.text:SetText (t.name)
|
|
DF:SetFontSize (widget.text, raw.textsize or 10)
|
|
widget.text:SetJustifyH (raw.textalign or "left")
|
|
|
|
end
|
|
end
|
|
|
|
for i = #updated_rows+1, #self._raw_rows do
|
|
local raw = self._raw_rows [i]
|
|
local widget = self.rows [i]
|
|
raw.hidden = true
|
|
widget.hidden = true
|
|
end
|
|
|
|
for index, row in ipairs (self.scrollframe.lines) do
|
|
for i = #row.text_inuse, 1, -1 do
|
|
tinsert (row.text_available, tremove (row.text_inuse, i))
|
|
end
|
|
for i = 1, #row.text_available do
|
|
row.text_available[i]:Hide()
|
|
end
|
|
|
|
for i = #row.entry_inuse, 1, -1 do
|
|
tinsert (row.entry_available, tremove (row.entry_inuse, i))
|
|
end
|
|
for i = 1, #row.entry_available do
|
|
row.entry_available[i]:Hide()
|
|
end
|
|
|
|
for i = #row.button_inuse, 1, -1 do
|
|
tinsert (row.button_available, tremove (row.button_inuse, i))
|
|
end
|
|
for i = 1, #row.button_available do
|
|
row.button_available[i]:Hide()
|
|
end
|
|
|
|
for i = #row.checkbox_inuse, 1, -1 do
|
|
tinsert (row.checkbox_available, tremove (row.checkbox_inuse, i))
|
|
end
|
|
for i = 1, #row.checkbox_available do
|
|
row.checkbox_available[i]:Hide()
|
|
end
|
|
|
|
for i = #row.icon_inuse, 1, -1 do
|
|
tinsert (row.icon_available, tremove (row.icon_inuse, i))
|
|
end
|
|
for i = 1, #row.icon_available do
|
|
row.icon_available[i]:Hide()
|
|
end
|
|
|
|
for i = #row.texture_inuse, 1, -1 do
|
|
tinsert (row.texture_available, tremove (row.texture_inuse, i))
|
|
end
|
|
for i = 1, #row.texture_available do
|
|
row.texture_available[i]:Hide()
|
|
end
|
|
end
|
|
|
|
self.current_header = updated_rows
|
|
|
|
self:AlignRows()
|
|
|
|
end
|
|
|
|
local create_panel_text = function (self, row)
|
|
row.text_total = row.text_total + 1
|
|
local text = DF:NewLabel (row, nil, self._name .. "$parentLabel" .. row.text_total, "text" .. row.text_total)
|
|
tinsert (row.text_available, text)
|
|
end
|
|
|
|
local create_panel_entry = function (self, row)
|
|
row.entry_total = row.entry_total + 1
|
|
local editbox = DF:NewTextEntry (row, nil, "$parentEntry" .. row.entry_total, "entry", 120, 20)
|
|
editbox.align = "left"
|
|
|
|
editbox:SetHook ("OnEnterPressed", function()
|
|
editbox.widget.focuslost = true
|
|
editbox:ClearFocus()
|
|
editbox.func (editbox.index, editbox.text)
|
|
return true
|
|
end)
|
|
|
|
editbox:SetHook ("OnEnter", function()
|
|
if (editbox.onenter_func) then
|
|
pcall (editbox.onenter_func, editbox)
|
|
end
|
|
end)
|
|
editbox:SetHook ("OnLeave", function()
|
|
if (editbox.onleave_func) then
|
|
pcall (editbox.onleave_func, editbox)
|
|
end
|
|
end)
|
|
|
|
editbox.editbox.current_bordercolor = {1, 1, 1, 0.1}
|
|
|
|
editbox:SetTemplate (DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
|
editbox:SetBackdropColor (.2, .2, .2, 0.7)
|
|
|
|
tinsert (row.entry_available, editbox)
|
|
end
|
|
|
|
local create_panel_checkbox = function (self, row)
|
|
--row.checkbox_available
|
|
row.checkbox_total = row.checkbox_total + 1
|
|
|
|
local switch = DF:NewSwitch (row, nil, "$parentCheckBox" .. row.checkbox_total, nil, 20, 20, nil, nil, false)
|
|
switch:SetAsCheckBox()
|
|
switch:SetTemplate(DF:GetTemplate ("switch", "OPTIONS_CHECKBOX_TEMPLATE"))
|
|
|
|
tinsert (row.checkbox_available, switch)
|
|
end
|
|
|
|
local create_panel_button = function (self, row)
|
|
row.button_total = row.button_total + 1
|
|
local button = DF:NewButton (row, nil, "$parentButton" .. row.button_total, "button" .. row.button_total, 120, 20)
|
|
|
|
--> create icon and the text
|
|
local icon = DF:NewImage (button, nil, 20, 20)
|
|
local text = DF:NewLabel (button)
|
|
|
|
button._icon = icon
|
|
button._text = text
|
|
|
|
button:SetHook ("OnEnter", button_on_enter)
|
|
button:SetHook ("OnLeave", button_on_leave)
|
|
|
|
tinsert (row.button_available, button)
|
|
end
|
|
|
|
local icon_onclick = function (texture, iconbutton)
|
|
iconbutton._icon.texture = texture
|
|
iconbutton.func (iconbutton.index, texture)
|
|
end
|
|
|
|
local create_panel_icon = function (self, row)
|
|
row.icon_total = row.icon_total + 1
|
|
local iconbutton = DF:NewButton (row, nil, "$parentIconButton" .. row.icon_total, "iconbutton", 22, 20)
|
|
|
|
iconbutton:SetHook ("OnEnter", button_on_enter)
|
|
iconbutton:SetHook ("OnLeave", button_on_leave)
|
|
|
|
iconbutton:SetHook ("OnMouseUp", function()
|
|
DF:IconPick (icon_onclick, true, iconbutton)
|
|
return true
|
|
end)
|
|
|
|
local icon = DF:NewImage (iconbutton, nil, 20, 20, "artwork", nil, "_icon", "$parentIcon" .. row.icon_total)
|
|
iconbutton._icon = icon
|
|
|
|
icon:SetPoint ("center", iconbutton, "center", 0, 0)
|
|
|
|
tinsert (row.icon_available, iconbutton)
|
|
end
|
|
|
|
local create_panel_texture = function (self, row)
|
|
row.texture_total = row.texture_total + 1
|
|
local texture = DF:NewImage (row, nil, 20, 20, "artwork", nil, "_icon" .. row.texture_total, "$parentIcon" .. row.texture_total)
|
|
tinsert (row.texture_available, texture)
|
|
end
|
|
|
|
local set_fill_function = function (self, func)
|
|
self._fillfunc = func
|
|
end
|
|
local set_total_function = function (self, func)
|
|
self._totalfunc = func
|
|
end
|
|
local drop_header_function = function (self)
|
|
wipe (self.rows)
|
|
end
|
|
|
|
local fillpanel_update_size = function (self, elapsed)
|
|
local panel = self.MyObject
|
|
|
|
panel._width = panel:GetWidth()
|
|
panel._height = panel:GetHeight()
|
|
|
|
panel:UpdateRowAmount()
|
|
if (panel.current_header) then
|
|
update_rows (panel, panel.current_header)
|
|
end
|
|
panel:Refresh()
|
|
|
|
self:SetScript ("OnUpdate", nil)
|
|
end
|
|
|
|
-- ~fillpanel
|
|
--alias
|
|
function DF:CreateFillPanel (parent, rows, w, h, total_lines, fill_row, autowidth, options, member, name)
|
|
return DF:NewFillPanel (parent, rows, name, member, w, h, total_lines, fill_row, autowidth, options)
|
|
end
|
|
|
|
function DF:NewFillPanel (parent, rows, name, member, w, h, total_lines, fill_row, autowidth, options)
|
|
|
|
local panel = DF:NewPanel (parent, parent, name, member, w, h)
|
|
panel.backdrop = nil
|
|
|
|
options = options or {rowheight = 20}
|
|
panel.rows = {}
|
|
|
|
panel.AddRow = add_row
|
|
panel.AlignRows = align_rows
|
|
panel.UpdateRows = update_rows
|
|
panel.CreateRowText = create_panel_text
|
|
panel.CreateRowEntry = create_panel_entry
|
|
panel.CreateRowButton = create_panel_button
|
|
panel.CreateCheckbox = create_panel_checkbox
|
|
panel.CreateRowIcon = create_panel_icon
|
|
panel.CreateRowTexture = create_panel_texture
|
|
panel.SetFillFunction = set_fill_function
|
|
panel.SetTotalFunction = set_total_function
|
|
panel.DropHeader = drop_header_function
|
|
|
|
panel._name = name
|
|
panel._width = w
|
|
panel._height = h
|
|
panel._raw_rows = {}
|
|
panel._anchors = {}
|
|
panel._fillfunc = fill_row
|
|
panel._totalfunc = total_lines
|
|
panel._autowidth = autowidth
|
|
|
|
panel:SetScript ("OnSizeChanged", function()
|
|
panel:SetScript ("OnUpdate", fillpanel_update_size)
|
|
end)
|
|
|
|
for index, t in ipairs (rows) do
|
|
panel.AddRow (panel, t)
|
|
end
|
|
|
|
local refresh_fillbox = function (self)
|
|
|
|
local offset = FauxScrollFrame_GetOffset (self)
|
|
local filled_lines = panel._totalfunc (panel)
|
|
|
|
for index = 1, #self.lines do
|
|
|
|
local row = self.lines [index]
|
|
if (index <= filled_lines) then
|
|
|
|
local real_index = index + offset
|
|
local results = panel._fillfunc (real_index, panel)
|
|
|
|
if (results and results [1]) then
|
|
row:Show()
|
|
|
|
local text, entry, button, icon, texture, checkbox = 1, 1, 1, 1, 1, 1
|
|
|
|
for index, t in ipairs (panel.rows) do
|
|
if (not t.hidden) then
|
|
if (t.type == "text") then
|
|
local fontstring = row.text_inuse [text]
|
|
text = text + 1
|
|
fontstring:SetText (results [index])
|
|
fontstring.index = real_index
|
|
fontstring:Show()
|
|
|
|
elseif (t.type == "entry") then
|
|
local entrywidget = row.entry_inuse [entry]
|
|
entry = entry + 1
|
|
entrywidget.index = real_index
|
|
|
|
if (type (results [index]) == "table") then
|
|
entrywidget:SetText (results [index].text)
|
|
entrywidget.id = results [index].id
|
|
entrywidget.data1 = results [index].data1
|
|
entrywidget.data2 = results [index].data2
|
|
else
|
|
entrywidget:SetText (results [index])
|
|
end
|
|
|
|
entrywidget:SetCursorPosition(0)
|
|
|
|
entrywidget:Show()
|
|
|
|
elseif (t.type == "checkbox") then
|
|
local checkboxwidget = row.checkbox_inuse [button]
|
|
checkbox = checkbox + 1
|
|
checkboxwidget.index = real_index
|
|
checkboxwidget:SetValue(results [index])
|
|
|
|
local func = function()
|
|
t.func (real_index, index)
|
|
panel:Refresh()
|
|
end
|
|
checkboxwidget.OnSwitch = func
|
|
|
|
elseif (t.type == "button") then
|
|
local buttonwidget = row.button_inuse [button]
|
|
button = button + 1
|
|
buttonwidget.index = real_index
|
|
|
|
if (type (results [index]) == "table") then
|
|
if (results [index].text) then
|
|
buttonwidget:SetText (results [index].text)
|
|
end
|
|
|
|
if (results [index].icon) then
|
|
buttonwidget._icon:SetTexture (results [index].icon)
|
|
end
|
|
|
|
if (results [index].func) then
|
|
local func = function()
|
|
t.func (real_index, results [index].value)
|
|
panel:Refresh()
|
|
end
|
|
buttonwidget:SetClickFunction (func)
|
|
else
|
|
local func = function()
|
|
t.func (real_index, index)
|
|
panel:Refresh()
|
|
end
|
|
buttonwidget:SetClickFunction (func)
|
|
end
|
|
|
|
buttonwidget.id = results [index].id
|
|
buttonwidget.data1 = results [index].data1
|
|
buttonwidget.data2 = results [index].data2
|
|
|
|
else
|
|
local func = function()
|
|
t.func (real_index, index)
|
|
panel:Refresh()
|
|
end
|
|
buttonwidget:SetClickFunction (func)
|
|
buttonwidget:SetText (results [index])
|
|
end
|
|
|
|
buttonwidget:Show()
|
|
|
|
elseif (t.type == "icon") then
|
|
local iconwidget = row.icon_inuse [icon]
|
|
icon = icon + 1
|
|
|
|
iconwidget.line = index
|
|
iconwidget.index = real_index
|
|
|
|
if (type (results [index]) == "string") then
|
|
local result = results [index]:gsub (".-%\\", "")
|
|
iconwidget._icon.texture = results [index]
|
|
iconwidget._icon:SetTexCoord (0.1, .9, 0.1, .9)
|
|
|
|
elseif (type (results [index]) == "table") then
|
|
iconwidget._icon:SetTexture (results [index].texture)
|
|
|
|
local textCoord = results [index].texcoord
|
|
if (textCoord) then
|
|
iconwidget._icon:SetTexCoord (unpack(textCoord))
|
|
else
|
|
iconwidget._icon:SetTexCoord (0.1, .9, 0.1, .9)
|
|
end
|
|
|
|
local color = results [index].color
|
|
if (color) then
|
|
local r, g, b, a = DF:ParseColors(color)
|
|
iconwidget._icon:SetVertexColor(r, g, b, a)
|
|
else
|
|
iconwidget._icon:SetVertexColor(1, 1, 1, 1)
|
|
end
|
|
else
|
|
iconwidget._icon:SetTexture (results [index])
|
|
iconwidget._icon:SetTexCoord (0.1, .9, 0.1, .9)
|
|
end
|
|
|
|
iconwidget:Show()
|
|
|
|
elseif (t.type == "texture") then
|
|
local texturewidget = row.texture_inuse [texture]
|
|
texture = texture + 1
|
|
|
|
texturewidget.line = index
|
|
texturewidget.index = real_index
|
|
|
|
if (type (results [index]) == "string") then
|
|
local result = results [index]:gsub (".-%\\", "")
|
|
texturewidget.texture = results [index]
|
|
|
|
elseif (type (results [index]) == "table") then
|
|
texturewidget:SetTexture (results [index].texture)
|
|
|
|
local textCoord = results [index].texcoord
|
|
if (textCoord) then
|
|
texturewidget:SetTexCoord (unpack(textCoord))
|
|
else
|
|
texturewidget:SetTexCoord (0, 1, 0, 1)
|
|
end
|
|
|
|
local color = results [index].color
|
|
if (color) then
|
|
local r, g, b, a = DF:ParseColors(color)
|
|
texturewidget:SetVertexColor(r, g, b, a)
|
|
else
|
|
texturewidget:SetVertexColor(1, 1, 1, 1)
|
|
end
|
|
|
|
else
|
|
texturewidget:SetTexture (results [index])
|
|
end
|
|
|
|
texturewidget:Show()
|
|
end
|
|
end
|
|
end
|
|
|
|
else
|
|
row:Hide()
|
|
end
|
|
else
|
|
row:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
function panel:Refresh()
|
|
if (type (panel._totalfunc) == "boolean") then
|
|
--> not yet initialized
|
|
return
|
|
end
|
|
local filled_lines = panel._totalfunc (panel)
|
|
local scroll_total_lines = #panel.scrollframe.lines
|
|
local line_height = options.rowheight
|
|
refresh_fillbox (panel.scrollframe)
|
|
FauxScrollFrame_Update (panel.scrollframe, filled_lines, scroll_total_lines, line_height)
|
|
panel.scrollframe:Show()
|
|
end
|
|
|
|
local scrollframe = CreateFrame ("scrollframe", name .. "Scroll", panel.widget, "FauxScrollFrameTemplate", "BackdropTemplate")
|
|
scrollframe:SetScript ("OnVerticalScroll", function (self, offset) FauxScrollFrame_OnVerticalScroll (self, offset, 20, panel.Refresh) end)
|
|
scrollframe:SetPoint ("topleft", panel.widget, "topleft", 0, -21)
|
|
scrollframe:SetPoint ("topright", panel.widget, "topright", -23, -21)
|
|
scrollframe:SetPoint ("bottomleft", panel.widget, "bottomleft")
|
|
scrollframe:SetPoint ("bottomright", panel.widget, "bottomright", -23, 0)
|
|
scrollframe:SetSize (w, h)
|
|
panel.scrollframe = scrollframe
|
|
scrollframe.lines = {}
|
|
|
|
DF:ReskinSlider (scrollframe)
|
|
|
|
--create lines
|
|
function panel:UpdateRowAmount()
|
|
local size = options.rowheight
|
|
local amount = math.floor (((panel._height-21) / size))
|
|
|
|
for i = #scrollframe.lines+1, amount do
|
|
local row = CreateFrame ("frame", panel:GetName() .. "Row_" .. i, panel.widget,"BackdropTemplate")
|
|
row:SetSize (1, size)
|
|
row.color = {1, 1, 1, .2}
|
|
|
|
row:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]]})
|
|
|
|
if (i%2 == 0) then
|
|
row:SetBackdropColor (.5, .5, .5, 0.2)
|
|
else
|
|
row:SetBackdropColor (1, 1, 1, 0.00)
|
|
end
|
|
|
|
row:SetPoint ("topleft", scrollframe, "topleft", 0, (i-1) * size * -1)
|
|
row:SetPoint ("topright", scrollframe, "topright", 0, (i-1) * size * -1)
|
|
tinsert (scrollframe.lines, row)
|
|
|
|
row.text_available = {}
|
|
row.text_inuse = {}
|
|
row.text_total = 0
|
|
|
|
row.entry_available = {}
|
|
row.entry_inuse = {}
|
|
row.entry_total = 0
|
|
|
|
row.button_available = {}
|
|
row.button_inuse = {}
|
|
row.button_total = 0
|
|
|
|
row.checkbox_available = {}
|
|
row.checkbox_inuse = {}
|
|
row.checkbox_total = 0
|
|
|
|
row.icon_available = {}
|
|
row.icon_inuse = {}
|
|
row.icon_total = 0
|
|
|
|
row.texture_available = {}
|
|
row.texture_inuse = {}
|
|
row.texture_total = 0
|
|
end
|
|
end
|
|
panel:UpdateRowAmount()
|
|
|
|
panel.AlignRows (panel)
|
|
|
|
return panel
|
|
end
|
|
|
|
|
|
------------color pick
|
|
local color_pick_func = function()
|
|
local r, g, b = ColorPickerFrame:GetColorRGB()
|
|
local a = OpacitySliderFrame:GetValue()
|
|
ColorPickerFrame:dcallback (r, g, b, a, ColorPickerFrame.dframe)
|
|
end
|
|
local color_pick_func_cancel = function()
|
|
ColorPickerFrame:SetColorRGB (unpack (ColorPickerFrame.previousValues))
|
|
local r, g, b = ColorPickerFrame:GetColorRGB()
|
|
local a = OpacitySliderFrame:GetValue()
|
|
ColorPickerFrame:dcallback (r, g, b, a, ColorPickerFrame.dframe)
|
|
end
|
|
|
|
function DF:ColorPick (frame, r, g, b, alpha, callback)
|
|
|
|
ColorPickerFrame:ClearAllPoints()
|
|
ColorPickerFrame:SetPoint ("bottomleft", frame, "topright", 0, 0)
|
|
|
|
ColorPickerFrame.dcallback = callback
|
|
ColorPickerFrame.dframe = frame
|
|
|
|
ColorPickerFrame.func = color_pick_func
|
|
ColorPickerFrame.opacityFunc = color_pick_func
|
|
ColorPickerFrame.cancelFunc = color_pick_func_cancel
|
|
|
|
ColorPickerFrame.opacity = alpha
|
|
ColorPickerFrame.hasOpacity = alpha and true
|
|
|
|
ColorPickerFrame.previousValues = {r, g, b}
|
|
ColorPickerFrame:SetParent (UIParent)
|
|
ColorPickerFrame:SetFrameStrata ("tooltip")
|
|
ColorPickerFrame:SetColorRGB (r, g, b)
|
|
ColorPickerFrame:Show()
|
|
|
|
end
|
|
|
|
------------icon pick
|
|
function DF:IconPick (callback, close_when_select, param1, param2)
|
|
|
|
if (not DF.IconPickFrame) then
|
|
|
|
local string_lower = string.lower
|
|
|
|
DF.IconPickFrame = CreateFrame ("frame", "DetailsFrameworkIconPickFrame", UIParent, "BackdropTemplate")
|
|
tinsert (UISpecialFrames, "DetailsFrameworkIconPickFrame")
|
|
DF.IconPickFrame:SetFrameStrata ("TOOLTIP")
|
|
|
|
DF.IconPickFrame:SetPoint ("center", UIParent, "center")
|
|
DF.IconPickFrame:SetWidth (350)
|
|
DF.IconPickFrame:SetHeight (277)
|
|
DF.IconPickFrame:EnableMouse (true)
|
|
DF.IconPickFrame:SetMovable (true)
|
|
|
|
DF:CreateTitleBar (DF.IconPickFrame, "Icon Picker")
|
|
|
|
DF.IconPickFrame:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
|
|
DF.IconPickFrame:SetBackdropBorderColor (0, 0, 0)
|
|
DF.IconPickFrame:SetBackdropColor (24/255, 24/255, 24/255, .8)
|
|
DF.IconPickFrame:SetFrameLevel (5000)
|
|
|
|
DF.IconPickFrame:SetScript ("OnMouseDown", function (self)
|
|
if (not self.isMoving) then
|
|
DF.IconPickFrame:StartMoving()
|
|
self.isMoving = true
|
|
end
|
|
end)
|
|
|
|
DF.IconPickFrame:SetScript ("OnMouseUp", function (self)
|
|
if (self.isMoving) then
|
|
DF.IconPickFrame:StopMovingOrSizing()
|
|
self.isMoving = nil
|
|
end
|
|
end)
|
|
|
|
DF.IconPickFrame.emptyFunction = function() end
|
|
DF.IconPickFrame.callback = DF.IconPickFrame.emptyFunction
|
|
|
|
DF.IconPickFrame.preview = CreateFrame ("frame", nil, UIParent, "BackdropTemplate")
|
|
DF.IconPickFrame.preview:SetFrameStrata ("tooltip")
|
|
DF.IconPickFrame.preview:SetFrameLevel (6001)
|
|
DF.IconPickFrame.preview:SetSize (76, 76)
|
|
|
|
local preview_image_bg = DF:NewImage (DF.IconPickFrame.preview, nil, 76, 76)
|
|
preview_image_bg:SetDrawLayer ("background", 0)
|
|
preview_image_bg:SetAllPoints (DF.IconPickFrame.preview)
|
|
preview_image_bg:SetColorTexture (0, 0, 0)
|
|
|
|
local preview_image = DF:NewImage (DF.IconPickFrame.preview, nil, 76, 76)
|
|
preview_image:SetAllPoints (DF.IconPickFrame.preview)
|
|
|
|
DF.IconPickFrame.preview.icon = preview_image
|
|
DF.IconPickFrame.preview:Hide()
|
|
|
|
--serach
|
|
DF.IconPickFrame.searchLabel = DF:NewLabel (DF.IconPickFrame, nil, "$parentSearchBoxLabel", nil, "search:", font, size, color)
|
|
DF.IconPickFrame.searchLabel:SetPoint ("topleft", DF.IconPickFrame, "topleft", 12, -36)
|
|
DF.IconPickFrame.searchLabel:SetTemplate (DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
|
|
DF.IconPickFrame.search = DF:NewTextEntry (DF.IconPickFrame, nil, "$parentSearchBox", nil, 140, 20)
|
|
DF.IconPickFrame.search:SetPoint ("left", DF.IconPickFrame.searchLabel, "right", 2, 0)
|
|
DF.IconPickFrame.search:SetTemplate (DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
|
|
|
DF.IconPickFrame.search:SetHook ("OnTextChanged", function()
|
|
DF.IconPickFrame.searching = DF.IconPickFrame.search:GetText()
|
|
if (DF.IconPickFrame.searching == "") then
|
|
DF.IconPickFrameScroll:Show()
|
|
DF.IconPickFrame.searching = nil
|
|
DF.IconPickFrame.updateFunc()
|
|
else
|
|
DF.IconPickFrameScroll:Hide()
|
|
FauxScrollFrame_SetOffset (DF.IconPickFrame, 1)
|
|
DF.IconPickFrame.last_filter_index = 1
|
|
DF.IconPickFrame.updateFunc()
|
|
end
|
|
end)
|
|
|
|
--manually enter the icon path
|
|
DF.IconPickFrame.customIcon = DF:CreateLabel (DF.IconPickFrame, "Icon Path:", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
DF.IconPickFrame.customIcon:SetPoint ("bottomleft", DF.IconPickFrame, "bottomleft", 12, 16)
|
|
|
|
DF.IconPickFrame.customIconEntry = DF:CreateTextEntry (DF.IconPickFrame, function()end, 200, 20, "CustomIconEntry", _, _, DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
|
DF.IconPickFrame.customIconEntry:SetPoint ("left", DF.IconPickFrame.customIcon, "right", 2, 0)
|
|
|
|
DF.IconPickFrame.customIconEntry:SetHook ("OnTextChanged", function()
|
|
DF.IconPickFrame.preview:SetPoint ("bottom", DF.IconPickFrame.customIconEntry.widget, "top", 0, 2)
|
|
DF.IconPickFrame.preview.icon:SetTexture (DF.IconPickFrame.customIconEntry:GetText())
|
|
DF.IconPickFrame.preview:Show()
|
|
end)
|
|
|
|
DF.IconPickFrame.customIconEntry:SetHook ("OnEnter", function()
|
|
DF.IconPickFrame.preview:SetPoint ("bottom", DF.IconPickFrame.customIconEntry.widget, "top", 0, 2)
|
|
DF.IconPickFrame.preview.icon:SetTexture (DF.IconPickFrame.customIconEntry:GetText())
|
|
DF.IconPickFrame.preview:Show()
|
|
end)
|
|
|
|
--> close button
|
|
local close_button = CreateFrame ("button", nil, DF.IconPickFrame, "UIPanelCloseButton", "BackdropTemplate")
|
|
close_button:SetWidth (32)
|
|
close_button:SetHeight (32)
|
|
close_button:SetPoint ("TOPRIGHT", DF.IconPickFrame, "TOPRIGHT", -8, -7)
|
|
close_button:SetFrameLevel (close_button:GetFrameLevel()+2)
|
|
close_button:SetAlpha (0) --just hide, it is used below
|
|
|
|
--> accept custom icon button
|
|
local accept_custom_icon = function()
|
|
local path = DF.IconPickFrame.customIconEntry:GetText()
|
|
|
|
DF:QuickDispatch (DF.IconPickFrame.callback, path, DF.IconPickFrame.param1, DF.IconPickFrame.param2)
|
|
|
|
if (DF.IconPickFrame.click_close) then
|
|
close_button:Click()
|
|
end
|
|
end
|
|
|
|
DF.IconPickFrame.customIconAccept = DF:CreateButton (DF.IconPickFrame, accept_custom_icon, 82, 20, "Accept", nil, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
DF.IconPickFrame.customIconAccept:SetPoint ("left", DF.IconPickFrame.customIconEntry, "right", 2, 0)
|
|
|
|
--fill with icons
|
|
|
|
local MACRO_ICON_FILENAMES = {}
|
|
local SPELLNAMES_CACHE = {}
|
|
|
|
DF.IconPickFrame:SetScript ("OnShow", function()
|
|
|
|
MACRO_ICON_FILENAMES [1] = "INV_MISC_QUESTIONMARK"
|
|
local index = 2
|
|
|
|
for i = 1, GetNumSpellTabs() do
|
|
local tab, tabTex, offset, numSpells, _ = GetSpellTabInfo (i)
|
|
offset = offset + 1
|
|
local tabEnd = offset + numSpells
|
|
|
|
for j = offset, tabEnd - 1 do
|
|
--to get spell info by slot, you have to pass in a pet argument
|
|
local spellType, ID = GetSpellBookItemInfo (j, "player")
|
|
if (spellType ~= "FLYOUT") then
|
|
MACRO_ICON_FILENAMES [index] = GetSpellBookItemTexture (j, "player") or 0
|
|
SPELLNAMES_CACHE [index] = GetSpellInfo (ID)
|
|
index = index + 1
|
|
|
|
elseif (spellType == "FLYOUT") then
|
|
local _, _, numSlots, isKnown = GetFlyoutInfo (ID)
|
|
if (isKnown and numSlots > 0) then
|
|
for k = 1, numSlots do
|
|
local spellID, overrideSpellID, isKnown = GetFlyoutSlotInfo (ID, k)
|
|
if (isKnown) then
|
|
MACRO_ICON_FILENAMES [index] = GetSpellTexture (spellID) or 0
|
|
SPELLNAMES_CACHE [index] = GetSpellInfo (spellID)
|
|
index = index + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
GetLooseMacroItemIcons (MACRO_ICON_FILENAMES)
|
|
GetLooseMacroIcons (MACRO_ICON_FILENAMES)
|
|
GetMacroIcons (MACRO_ICON_FILENAMES)
|
|
GetMacroItemIcons (MACRO_ICON_FILENAMES)
|
|
|
|
--reset the custom icon text entry
|
|
DF.IconPickFrame.customIconEntry:SetText ("")
|
|
--reset the search text entry
|
|
DF.IconPickFrame.search:SetText ("")
|
|
end)
|
|
|
|
DF.IconPickFrame:SetScript ("OnHide", function()
|
|
wipe (MACRO_ICON_FILENAMES)
|
|
wipe (SPELLNAMES_CACHE)
|
|
DF.IconPickFrame.preview:Hide()
|
|
collectgarbage()
|
|
end)
|
|
|
|
DF.IconPickFrame.buttons = {}
|
|
|
|
local OnClickFunction = function (self)
|
|
|
|
DF:QuickDispatch (DF.IconPickFrame.callback, self.icon:GetTexture(), DF.IconPickFrame.param1, DF.IconPickFrame.param2)
|
|
|
|
if (DF.IconPickFrame.click_close) then
|
|
close_button:Click()
|
|
end
|
|
end
|
|
|
|
local onenter = function (self)
|
|
DF.IconPickFrame.preview:SetPoint ("bottom", self, "top", 0, 2)
|
|
DF.IconPickFrame.preview.icon:SetTexture (self.icon:GetTexture())
|
|
DF.IconPickFrame.preview:Show()
|
|
self.icon:SetBlendMode ("ADD")
|
|
end
|
|
local onleave = function (self)
|
|
DF.IconPickFrame.preview:Hide()
|
|
self.icon:SetBlendMode ("BLEND")
|
|
end
|
|
|
|
local backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tile = true, tileSize = 16,
|
|
insets = {left = 0, right = 0, top = 0, bottom = 0}, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1}
|
|
|
|
for i = 0, 9 do
|
|
local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..(i+1), DF.IconPickFrame, "BackdropTemplate")
|
|
local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..(i+1).."Icon", "overlay")
|
|
newcheck.icon = image
|
|
image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2)
|
|
newcheck:SetSize (30, 28)
|
|
newcheck:SetBackdrop (backdrop)
|
|
|
|
newcheck:SetScript ("OnClick", OnClickFunction)
|
|
newcheck.param1 = i+1
|
|
|
|
newcheck:SetPoint ("topleft", DF.IconPickFrame, "topleft", 12 + (i*30), -60)
|
|
newcheck:SetID (i+1)
|
|
DF.IconPickFrame.buttons [#DF.IconPickFrame.buttons+1] = newcheck
|
|
newcheck:SetScript ("OnEnter", onenter)
|
|
newcheck:SetScript ("OnLeave", onleave)
|
|
end
|
|
for i = 11, 20 do
|
|
local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame, "BackdropTemplate")
|
|
local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay")
|
|
newcheck.icon = image
|
|
image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2)
|
|
newcheck:SetSize (30, 28)
|
|
newcheck:SetBackdrop (backdrop)
|
|
|
|
newcheck:SetScript ("OnClick", OnClickFunction)
|
|
newcheck.param1 = i
|
|
|
|
newcheck:SetPoint ("topleft", "DetailsFrameworkIconPickFrameButton"..(i-10), "bottomleft", 0, -1)
|
|
newcheck:SetID (i)
|
|
DF.IconPickFrame.buttons [#DF.IconPickFrame.buttons+1] = newcheck
|
|
newcheck:SetScript ("OnEnter", onenter)
|
|
newcheck:SetScript ("OnLeave", onleave)
|
|
end
|
|
for i = 21, 30 do
|
|
local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame, "BackdropTemplate")
|
|
local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay")
|
|
newcheck.icon = image
|
|
image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2)
|
|
newcheck:SetSize (30, 28)
|
|
newcheck:SetBackdrop (backdrop)
|
|
|
|
newcheck:SetScript ("OnClick", OnClickFunction)
|
|
newcheck.param1 = i
|
|
|
|
newcheck:SetPoint ("topleft", "DetailsFrameworkIconPickFrameButton"..(i-10), "bottomleft", 0, -1)
|
|
newcheck:SetID (i)
|
|
DF.IconPickFrame.buttons [#DF.IconPickFrame.buttons+1] = newcheck
|
|
newcheck:SetScript ("OnEnter", onenter)
|
|
newcheck:SetScript ("OnLeave", onleave)
|
|
end
|
|
for i = 31, 40 do
|
|
local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame, "BackdropTemplate")
|
|
local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay")
|
|
newcheck.icon = image
|
|
image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2)
|
|
newcheck:SetSize (30, 28)
|
|
newcheck:SetBackdrop (backdrop)
|
|
|
|
newcheck:SetScript ("OnClick", OnClickFunction)
|
|
newcheck.param1 = i
|
|
|
|
newcheck:SetPoint ("topleft", "DetailsFrameworkIconPickFrameButton"..(i-10), "bottomleft", 0, -1)
|
|
newcheck:SetID (i)
|
|
DF.IconPickFrame.buttons [#DF.IconPickFrame.buttons+1] = newcheck
|
|
newcheck:SetScript ("OnEnter", onenter)
|
|
newcheck:SetScript ("OnLeave", onleave)
|
|
end
|
|
for i = 41, 50 do
|
|
local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame, "BackdropTemplate")
|
|
local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay")
|
|
newcheck.icon = image
|
|
image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2)
|
|
newcheck:SetSize (30, 28)
|
|
newcheck:SetBackdrop (backdrop)
|
|
|
|
newcheck:SetScript ("OnClick", OnClickFunction)
|
|
newcheck.param1 = i
|
|
|
|
newcheck:SetPoint ("topleft", "DetailsFrameworkIconPickFrameButton"..(i-10), "bottomleft", 0, -1)
|
|
newcheck:SetID (i)
|
|
DF.IconPickFrame.buttons [#DF.IconPickFrame.buttons+1] = newcheck
|
|
newcheck:SetScript ("OnEnter", onenter)
|
|
newcheck:SetScript ("OnLeave", onleave)
|
|
end
|
|
for i = 51, 60 do
|
|
local newcheck = CreateFrame ("Button", "DetailsFrameworkIconPickFrameButton"..i, DF.IconPickFrame, "BackdropTemplate")
|
|
local image = newcheck:CreateTexture ("DetailsFrameworkIconPickFrameButton"..i.."Icon", "overlay")
|
|
newcheck.icon = image
|
|
image:SetPoint ("topleft", newcheck, "topleft", 2, -2) image:SetPoint ("bottomright", newcheck, "bottomright", -2, 2)
|
|
newcheck:SetSize (30, 28)
|
|
newcheck:SetBackdrop (backdrop)
|
|
|
|
newcheck:SetScript ("OnClick", OnClickFunction)
|
|
newcheck.param1 = i
|
|
|
|
newcheck:SetPoint ("topleft", "DetailsFrameworkIconPickFrameButton"..(i-10), "bottomleft", 0, -1)
|
|
newcheck:SetID (i)
|
|
DF.IconPickFrame.buttons [#DF.IconPickFrame.buttons+1] = newcheck
|
|
newcheck:SetScript ("OnEnter", onenter)
|
|
newcheck:SetScript ("OnLeave", onleave)
|
|
end
|
|
|
|
local scroll = CreateFrame ("ScrollFrame", "DetailsFrameworkIconPickFrameScroll", DF.IconPickFrame, "ListScrollFrameTemplate", "BackdropTemplate")
|
|
DF:ReskinSlider (scroll)
|
|
|
|
local ChecksFrame_Update = function (self)
|
|
|
|
local numMacroIcons = #MACRO_ICON_FILENAMES
|
|
local macroPopupIcon, macroPopupButton
|
|
local macroPopupOffset = FauxScrollFrame_GetOffset (scroll)
|
|
local index
|
|
|
|
local texture
|
|
local filter
|
|
if (DF.IconPickFrame.searching) then
|
|
filter = string_lower (DF.IconPickFrame.searching)
|
|
end
|
|
|
|
local pool
|
|
local shown = 0
|
|
|
|
if (filter and filter ~= "") then
|
|
--do the filter
|
|
pool = {}
|
|
for i = 1, #SPELLNAMES_CACHE do
|
|
if (SPELLNAMES_CACHE [i] and SPELLNAMES_CACHE [i]:lower():find (filter)) then
|
|
pool [#pool+1] = MACRO_ICON_FILENAMES [i]
|
|
shown = shown + 1
|
|
end
|
|
end
|
|
else
|
|
shown = nil
|
|
end
|
|
|
|
if (not pool) then
|
|
pool = MACRO_ICON_FILENAMES
|
|
end
|
|
|
|
for i = 1, 60 do
|
|
macroPopupIcon = _G ["DetailsFrameworkIconPickFrameButton"..i.."Icon"]
|
|
macroPopupButton = _G ["DetailsFrameworkIconPickFrameButton"..i]
|
|
index = (macroPopupOffset * 10) + i
|
|
texture = pool [index]
|
|
if ( index <= numMacroIcons and texture ) then
|
|
|
|
if (type (texture) == "number") then
|
|
macroPopupIcon:SetTexture (texture)
|
|
else
|
|
macroPopupIcon:SetTexture ("INTERFACE\\ICONS\\" .. texture)
|
|
end
|
|
|
|
macroPopupIcon:SetTexCoord (4/64, 60/64, 4/64, 60/64)
|
|
macroPopupButton.IconID = index
|
|
macroPopupButton:Show()
|
|
else
|
|
macroPopupButton:Hide()
|
|
end
|
|
end
|
|
|
|
pool = nil
|
|
|
|
-- Scrollbar stuff
|
|
FauxScrollFrame_Update (scroll, ceil ((shown or numMacroIcons) / 10) , 5, 20 )
|
|
end
|
|
|
|
DF.IconPickFrame.updateFunc = ChecksFrame_Update
|
|
|
|
scroll:SetPoint ("topleft", DF.IconPickFrame, "topleft", -18, -58)
|
|
scroll:SetWidth (330)
|
|
scroll:SetHeight (178)
|
|
scroll:SetScript ("OnVerticalScroll", function (self, offset) FauxScrollFrame_OnVerticalScroll (scroll, offset, 20, ChecksFrame_Update) end)
|
|
scroll.update = ChecksFrame_Update
|
|
DF.IconPickFrameScroll = scroll
|
|
DF.IconPickFrame:Hide()
|
|
|
|
end
|
|
|
|
DF.IconPickFrame.param1, DF.IconPickFrame.param2 = param1, param2
|
|
|
|
DF.IconPickFrame:Show()
|
|
DF.IconPickFrameScroll.update (DF.IconPickFrameScroll)
|
|
DF.IconPickFrame.callback = callback or DF.IconPickFrame.emptyFunction
|
|
DF.IconPickFrame.click_close = close_when_select
|
|
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
function DF:ShowPanicWarning (text)
|
|
if (not DF.PanicWarningWindow) then
|
|
DF.PanicWarningWindow = CreateFrame ("frame", "DetailsFrameworkPanicWarningWindow", UIParent, "BackdropTemplate")
|
|
DF.PanicWarningWindow:SetHeight (80)
|
|
DF.PanicWarningWindow:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
DF.PanicWarningWindow:SetBackdropColor (1, 0, 0, 0.2)
|
|
DF.PanicWarningWindow:SetPoint ("topleft", UIParent, "topleft", 0, -250)
|
|
DF.PanicWarningWindow:SetPoint ("topright", UIParent, "topright", 0, -250)
|
|
|
|
DF.PanicWarningWindow.text = DF.PanicWarningWindow:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
DF.PanicWarningWindow.text:SetPoint ("center", DF.PanicWarningWindow, "center")
|
|
DF.PanicWarningWindow.text:SetTextColor (1, 0.6, 0)
|
|
end
|
|
|
|
DF.PanicWarningWindow.text:SetText (text)
|
|
DF.PanicWarningWindow:Show()
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
local simple_panel_mouse_down = function (self, button)
|
|
if (button == "RightButton") then
|
|
if (self.IsMoving) then
|
|
self.IsMoving = false
|
|
self:StopMovingOrSizing()
|
|
if (self.db and self.db.position) then
|
|
DF:SavePositionOnScreen (self)
|
|
end
|
|
end
|
|
if (not self.DontRightClickClose) then
|
|
self:Hide()
|
|
end
|
|
return
|
|
end
|
|
if (not self.IsMoving and not self.IsLocked) then
|
|
self.IsMoving = true
|
|
self:StartMoving()
|
|
end
|
|
end
|
|
local simple_panel_mouse_up = function (self, button)
|
|
if (self.IsMoving) then
|
|
self.IsMoving = false
|
|
self:StopMovingOrSizing()
|
|
if (self.db and self.db.position) then
|
|
DF:SavePositionOnScreen (self)
|
|
end
|
|
end
|
|
end
|
|
local simple_panel_settitle = function (self, title)
|
|
self.Title:SetText (title)
|
|
end
|
|
|
|
local simple_panel_close_click = function (self)
|
|
self:GetParent():GetParent():Hide()
|
|
end
|
|
|
|
local SimplePanel_frame_backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}
|
|
local SimplePanel_frame_backdrop_color = {0, 0, 0, 0.9}
|
|
local SimplePanel_frame_backdrop_border_color = {0, 0, 0, 1}
|
|
|
|
--with_label was making the frame stay in place while its parent moves
|
|
--the slider was anchoring to with_label and here here were anchoring the slider again
|
|
function DF:CreateScaleBar (frame, config)
|
|
local scaleBar, text = DF:CreateSlider (frame, 120, 14, 0.6, 1.6, 0.1, config.scale, true, "ScaleBar", nil, "Scale:", DF:GetTemplate ("slider", "OPTIONS_SLIDER_TEMPLATE"), DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
--scaleBar:SetPoint ("right", frame.Close, "left", -26, 0)
|
|
text:SetPoint ("topleft", frame, "topleft", 12, -7)
|
|
scaleBar:SetFrameLevel (DF.FRAMELEVEL_OVERLAY)
|
|
scaleBar.OnValueChanged = function (_, _, value)
|
|
config.scale = value
|
|
if (not scaleBar.IsValueChanging) then
|
|
frame:SetScale (config.scale)
|
|
end
|
|
end
|
|
scaleBar:SetHook ("OnMouseUp", function()
|
|
frame:SetScale (config.scale)
|
|
end)
|
|
|
|
scaleBar:SetAlpha (0.2)
|
|
|
|
return scaleBar
|
|
end
|
|
|
|
local no_options = {}
|
|
function DF:CreateSimplePanel (parent, w, h, title, name, panel_options, db)
|
|
|
|
if (db and name and not db [name]) then
|
|
db [name] = {scale = 1}
|
|
end
|
|
|
|
if (not name) then
|
|
name = "DetailsFrameworkSimplePanel" .. DF.SimplePanelCounter
|
|
DF.SimplePanelCounter = DF.SimplePanelCounter + 1
|
|
end
|
|
if (not parent) then
|
|
parent = UIParent
|
|
end
|
|
|
|
panel_options = panel_options or no_options
|
|
|
|
local f = CreateFrame ("frame", name, UIParent,"BackdropTemplate")
|
|
f:SetSize (w or 400, h or 250)
|
|
f:SetPoint ("center", UIParent, "center", 0, 0)
|
|
f:SetFrameStrata ("FULLSCREEN")
|
|
f:EnableMouse()
|
|
f:SetMovable (true)
|
|
f:SetBackdrop (SimplePanel_frame_backdrop)
|
|
f:SetBackdropColor (unpack (SimplePanel_frame_backdrop_color))
|
|
f:SetBackdropBorderColor (unpack (SimplePanel_frame_backdrop_border_color))
|
|
|
|
f.DontRightClickClose = panel_options.DontRightClickClose
|
|
|
|
if (not panel_options.NoTUISpecialFrame) then
|
|
tinsert (UISpecialFrames, name)
|
|
end
|
|
|
|
local title_bar = CreateFrame ("frame", name .. "TitleBar", f,"BackdropTemplate")
|
|
title_bar:SetPoint ("topleft", f, "topleft", 2, -3)
|
|
title_bar:SetPoint ("topright", f, "topright", -2, -3)
|
|
title_bar:SetHeight (20)
|
|
title_bar:SetBackdrop (SimplePanel_frame_backdrop)
|
|
title_bar:SetBackdropColor (.2, .2, .2, 1)
|
|
title_bar:SetBackdropBorderColor (0, 0, 0, 1)
|
|
f.TitleBar = title_bar
|
|
|
|
local close = CreateFrame ("button", name and name .. "CloseButton", title_bar)
|
|
close:SetFrameLevel (DF.FRAMELEVEL_OVERLAY)
|
|
close:SetSize (16, 16)
|
|
|
|
close:SetNormalTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
close:SetHighlightTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
close:SetPushedTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
close:GetNormalTexture():SetDesaturated(true)
|
|
close:GetHighlightTexture():SetDesaturated(true)
|
|
close:GetPushedTexture():SetDesaturated(true)
|
|
|
|
close:SetAlpha (0.7)
|
|
close:SetScript ("OnClick", simple_panel_close_click)
|
|
f.Close = close
|
|
|
|
local title_string = title_bar:CreateFontString (name and name .. "Title", "overlay", "GameFontNormal")
|
|
title_string:SetTextColor (.8, .8, .8, 1)
|
|
title_string:SetText (title or "")
|
|
f.Title = title_string
|
|
|
|
if (panel_options.UseScaleBar and db [name]) then
|
|
DF:CreateScaleBar (f, db [name])
|
|
f:SetScale (db [name].scale)
|
|
end
|
|
|
|
f.Title:SetPoint ("center", title_bar, "center")
|
|
f.Close:SetPoint ("right", title_bar, "right", -2, 0)
|
|
|
|
f:SetScript ("OnMouseDown", simple_panel_mouse_down)
|
|
f:SetScript ("OnMouseUp", simple_panel_mouse_up)
|
|
|
|
f.SetTitle = simple_panel_settitle
|
|
|
|
return f
|
|
end
|
|
|
|
local Panel1PxBackdrop = {bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 64,
|
|
edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, insets = {left = 2, right = 2, top = 3, bottom = 3}}
|
|
|
|
local Panel1PxOnClickClose = function (self)
|
|
self:GetParent():Hide()
|
|
end
|
|
local Panel1PxOnToggleLock = function (self)
|
|
if (self.IsLocked) then
|
|
self.IsLocked = false
|
|
self:SetMovable (true)
|
|
self:EnableMouse (true)
|
|
self.Lock:GetNormalTexture():SetTexCoord (16/64, 32/64, 0, 1)
|
|
self.Lock:GetHighlightTexture():SetTexCoord (16/32, 32/64, 0, 1)
|
|
self.Lock:GetPushedTexture():SetTexCoord (16/64, 32/64, 0, 1)
|
|
if (self.OnUnlock) then
|
|
self:OnUnlock()
|
|
end
|
|
if (self.db) then
|
|
self.db.IsLocked = self.IsLocked
|
|
end
|
|
else
|
|
self.IsLocked = true
|
|
self:SetMovable (false)
|
|
self:EnableMouse (false)
|
|
self.Lock:GetNormalTexture():SetTexCoord (0/64, 16/64, 0, 1)
|
|
self.Lock:GetHighlightTexture():SetTexCoord (0/64, 16/64, 0, 1)
|
|
self.Lock:GetPushedTexture():SetTexCoord (0/64, 16/64, 0, 1)
|
|
if (self.OnLock) then
|
|
self:OnLock()
|
|
end
|
|
if (self.db) then
|
|
self.db.IsLocked = self.IsLocked
|
|
end
|
|
end
|
|
end
|
|
local Panel1PxOnClickLock = function (self)
|
|
local f = self:GetParent()
|
|
Panel1PxOnToggleLock (f)
|
|
end
|
|
local Panel1PxSetTitle = function (self, text)
|
|
self.Title:SetText (text or "")
|
|
end
|
|
|
|
local Panel1PxSetLocked= function (self, lock_state)
|
|
if (type (lock_state) ~= "boolean") then
|
|
return
|
|
end
|
|
if (lock_state) then
|
|
-- lock it
|
|
self.IsLocked = false
|
|
Panel1PxOnClickLock (self.Lock)
|
|
else
|
|
-- unlockit
|
|
self.IsLocked = true
|
|
Panel1PxOnClickLock (self.Lock)
|
|
end
|
|
end
|
|
|
|
local Panel1PxReadConfig = function (self)
|
|
local db = self.db
|
|
if (db) then
|
|
db.IsLocked = db.IsLocked or false
|
|
self.IsLocked = db.IsLocked
|
|
db.position = db.position or {x = 0, y = 0}
|
|
db.position.x = db.position.x or 0
|
|
db.position.y = db.position.y or 0
|
|
DF:RestoreFramePosition (self)
|
|
end
|
|
end
|
|
|
|
function DF:SavePositionOnScreen (frame)
|
|
if (frame.db and frame.db.position) then
|
|
local x, y = DF:GetPositionOnScreen (frame)
|
|
--print ("saving...", x, y, frame:GetName())
|
|
if (x and y) then
|
|
frame.db.position.x, frame.db.position.y = x, y
|
|
end
|
|
end
|
|
end
|
|
|
|
function DF:GetPositionOnScreen (frame)
|
|
local xOfs, yOfs = frame:GetCenter()
|
|
if (not xOfs) then
|
|
return
|
|
end
|
|
local scale = frame:GetEffectiveScale()
|
|
local UIscale = UIParent:GetScale()
|
|
xOfs = xOfs*scale - GetScreenWidth()*UIscale/2
|
|
yOfs = yOfs*scale - GetScreenHeight()*UIscale/2
|
|
return xOfs/UIscale, yOfs/UIscale
|
|
end
|
|
|
|
function DF:RestoreFramePosition (frame)
|
|
if (frame.db and frame.db.position) then
|
|
local scale, UIscale = frame:GetEffectiveScale(), UIParent:GetScale()
|
|
frame:ClearAllPoints()
|
|
frame.db.position.x = frame.db.position.x or 0
|
|
frame.db.position.y = frame.db.position.y or 0
|
|
frame:SetPoint ("center", UIParent, "center", frame.db.position.x * UIscale / scale, frame.db.position.y * UIscale / scale)
|
|
end
|
|
end
|
|
|
|
local Panel1PxSavePosition= function (self)
|
|
DF:SavePositionOnScreen (self)
|
|
end
|
|
|
|
local Panel1PxHasPosition = function (self)
|
|
local db = self.db
|
|
if (db) then
|
|
if (db.position and db.position.x and (db.position.x ~= 0 or db.position.y ~= 0)) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
function DF:Create1PxPanel (parent, w, h, title, name, config, title_anchor, no_special_frame)
|
|
local f = CreateFrame ("frame", name, parent or UIParent, "BackdropTemplate")
|
|
f:SetSize (w or 100, h or 75)
|
|
f:SetPoint ("center", UIParent, "center")
|
|
|
|
if (name and not no_special_frame) then
|
|
tinsert (UISpecialFrames, name)
|
|
end
|
|
|
|
f:SetScript ("OnMouseDown", simple_panel_mouse_down)
|
|
f:SetScript ("OnMouseUp", simple_panel_mouse_up)
|
|
|
|
f:SetBackdrop (Panel1PxBackdrop)
|
|
f:SetBackdropColor (0, 0, 0, 0.5)
|
|
|
|
f.IsLocked = (config and config.IsLocked ~= nil and config.IsLocked) or false
|
|
f:SetMovable (true)
|
|
f:EnableMouse (true)
|
|
f:SetUserPlaced (true)
|
|
|
|
f.db = config
|
|
--print (config.position.x, config.position.x)
|
|
Panel1PxReadConfig (f)
|
|
|
|
local close = CreateFrame ("button", name and name .. "CloseButton", f, "BackdropTemplate")
|
|
close:SetSize (16, 16)
|
|
close:SetNormalTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
close:SetHighlightTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
close:SetPushedTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
close:GetNormalTexture():SetDesaturated(true)
|
|
close:GetHighlightTexture():SetDesaturated(true)
|
|
close:GetPushedTexture():SetDesaturated(true)
|
|
close:SetAlpha (0.7)
|
|
|
|
local lock = CreateFrame ("button", name and name .. "LockButton", f, "BackdropTemplate")
|
|
lock:SetSize (16, 16)
|
|
lock:SetNormalTexture ([[Interface\GLUES\CharacterSelect\Glues-AddOn-Icons]])
|
|
lock:SetHighlightTexture ([[Interface\GLUES\CharacterSelect\Glues-AddOn-Icons]])
|
|
lock:SetPushedTexture ([[Interface\GLUES\CharacterSelect\Glues-AddOn-Icons]])
|
|
lock:GetNormalTexture():SetDesaturated(true)
|
|
lock:GetHighlightTexture():SetDesaturated(true)
|
|
lock:GetPushedTexture():SetDesaturated(true)
|
|
--lock:GetNormalTexture():SetBlendMode("ADD")
|
|
--lock:GetHighlightTexture():SetBlendMode("ADD")
|
|
--lock:GetPushedTexture():SetBlendMode("ADD")
|
|
--lock:GetNormalTexture():SetTexCoord(73/256, 105/256, 64/128, 110/)
|
|
--lock:GetHighlightTexture():SetTexCoord(73/256, 105/256, 64/128, 110/)
|
|
--lock:GetPushedTexture():SetTexCoord(73/256, 105/256, 64/128, 110/)
|
|
lock:SetAlpha (0.7)
|
|
|
|
close:SetPoint ("topright", f, "topright", -3, -3)
|
|
lock:SetPoint ("right", close, "left", 3, 0)
|
|
|
|
close:SetScript ("OnClick", Panel1PxOnClickClose)
|
|
lock:SetScript ("OnClick", Panel1PxOnClickLock)
|
|
|
|
local title_string = f:CreateFontString (name and name .. "Title", "overlay", "GameFontNormal")
|
|
title_string:SetPoint ("topleft", f, "topleft", 5, -5)
|
|
title_string:SetText (title or "")
|
|
|
|
if (title_anchor) then
|
|
if (title_anchor == "top") then
|
|
title_string:ClearAllPoints()
|
|
title_string:SetPoint ("bottomleft", f, "topleft", 0, 0)
|
|
close:ClearAllPoints()
|
|
close:SetPoint ("bottomright", f, "topright", 0, 0)
|
|
end
|
|
f.title_anchor = title_anchor
|
|
end
|
|
|
|
f.SetTitle = Panel1PxSetTitle
|
|
f.Title = title_string
|
|
f.Lock = lock
|
|
f.Close = close
|
|
f.HasPosition = Panel1PxHasPosition
|
|
f.SavePosition = Panel1PxSavePosition
|
|
|
|
f.IsLocked = not f.IsLocked
|
|
f.SetLocked = Panel1PxSetLocked
|
|
Panel1PxOnToggleLock (f)
|
|
|
|
return f
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~prompt
|
|
function DF:ShowPromptPanel (message, func_true, func_false, no_repeated, width)
|
|
|
|
if (not DetailsFrameworkPromptSimple) then
|
|
local f = CreateFrame ("frame", "DetailsFrameworkPromptSimple", UIParent, "BackdropTemplate")
|
|
f:SetSize (400, 80)
|
|
f:SetFrameStrata ("DIALOG")
|
|
f:SetPoint ("center", UIParent, "center", 0, 300)
|
|
f:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
f:SetBackdropColor (0, 0, 0, 0.8)
|
|
f:SetBackdropBorderColor (0, 0, 0, 1)
|
|
tinsert (UISpecialFrames, "DetailsFrameworkPromptSimple")
|
|
|
|
DF:CreateTitleBar (f, "Prompt!")
|
|
DF:ApplyStandardBackdrop (f)
|
|
|
|
local prompt = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
prompt:SetPoint ("top", f, "top", 0, -28)
|
|
prompt:SetJustifyH ("center")
|
|
f.prompt = prompt
|
|
|
|
local button_text_template = DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")
|
|
local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
|
|
|
|
local button_true = DF:CreateButton (f, nil, 60, 20, "Yes", nil, nil, nil, nil, nil, nil, options_dropdown_template)
|
|
button_true:SetPoint ("bottomright", f, "bottomright", -5, 5)
|
|
f.button_true = button_true
|
|
|
|
local button_false = DF:CreateButton (f, nil, 60, 20, "No", nil, nil, nil, nil, nil, nil, options_dropdown_template)
|
|
button_false:SetPoint ("bottomleft", f, "bottomleft", 5, 5)
|
|
f.button_false = button_false
|
|
|
|
button_true:SetClickFunction (function()
|
|
local my_func = button_true.true_function
|
|
if (my_func) then
|
|
local okey, errormessage = pcall (my_func, true)
|
|
if (not okey) then
|
|
print ("error:", errormessage)
|
|
end
|
|
f:Hide()
|
|
end
|
|
end)
|
|
|
|
button_false:SetClickFunction (function()
|
|
local my_func = button_false.false_function
|
|
if (my_func) then
|
|
local okey, errormessage = pcall (my_func, true)
|
|
if (not okey) then
|
|
print ("error:", errormessage)
|
|
end
|
|
f:Hide()
|
|
end
|
|
end)
|
|
|
|
f.ShowAnimation = DF:CreateAnimationHub (f, function()
|
|
f:SetBackdropBorderColor (0, 0, 0, 0)
|
|
f.TitleBar:SetBackdropBorderColor (0, 0, 0, 0)
|
|
end, function()
|
|
f:SetBackdropBorderColor (0, 0, 0, 1)
|
|
f.TitleBar:SetBackdropBorderColor (0, 0, 0, 1)
|
|
end)
|
|
DF:CreateAnimation (f.ShowAnimation, "scale", 1, .075, .2, .2, 1.1, 1.1, "center", 0, 0)
|
|
DF:CreateAnimation (f.ShowAnimation, "scale", 2, .075, 1, 1, .90, .90, "center", 0, 0)
|
|
|
|
f.FlashTexture = f:CreateTexture (nil, "overlay")
|
|
f.FlashTexture:SetColorTexture (1, 1, 1, 1)
|
|
f.FlashTexture:SetAllPoints()
|
|
|
|
f.FlashAnimation = DF:CreateAnimationHub (f.FlashTexture, function() f.FlashTexture:Show() end, function() f.FlashTexture:Hide() end)
|
|
DF:CreateAnimation (f.FlashAnimation, "alpha", 1, .075, 0, .25)
|
|
DF:CreateAnimation (f.FlashAnimation, "alpha", 2, .075, .35, 0)
|
|
|
|
f:Hide()
|
|
DF.promtp_panel = f
|
|
end
|
|
|
|
assert (type (func_true) == "function" and type (func_false) == "function", "ShowPromptPanel expects two functions.")
|
|
|
|
if (no_repeated) then
|
|
if (DF.promtp_panel:IsShown()) then
|
|
return
|
|
end
|
|
end
|
|
|
|
if (width) then
|
|
DF.promtp_panel:SetWidth (width)
|
|
else
|
|
DF.promtp_panel:SetWidth (400)
|
|
end
|
|
|
|
DF.promtp_panel.prompt:SetText (message)
|
|
DF.promtp_panel.button_true.true_function = func_true
|
|
DF.promtp_panel.button_false.false_function = func_false
|
|
|
|
DF.promtp_panel:Show()
|
|
|
|
DF.promtp_panel.ShowAnimation:Play()
|
|
DF.promtp_panel.FlashAnimation:Play()
|
|
end
|
|
|
|
|
|
function DF:ShowTextPromptPanel (message, callback)
|
|
|
|
if (not DF.text_prompt_panel) then
|
|
|
|
local f = CreateFrame ("frame", "DetailsFrameworkPrompt", UIParent, "BackdropTemplate")
|
|
f:SetSize (400, 120)
|
|
f:SetFrameStrata ("FULLSCREEN")
|
|
f:SetPoint ("center", UIParent, "center", 0, 100)
|
|
f:EnableMouse (true)
|
|
f:SetMovable (true)
|
|
f:RegisterForDrag ("LeftButton")
|
|
f:SetScript ("OnDragStart", function() f:StartMoving() end)
|
|
f:SetScript ("OnDragStop", function() f:StopMovingOrSizing() end)
|
|
f:SetScript ("OnMouseDown", function (self, button) if (button == "RightButton") then f.EntryBox:ClearFocus() f:Hide() end end)
|
|
tinsert (UISpecialFrames, "DetailsFrameworkPrompt")
|
|
|
|
DF:CreateTitleBar (f, "Prompt!")
|
|
DF:ApplyStandardBackdrop (f)
|
|
|
|
local prompt = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
prompt:SetPoint ("top", f, "top", 0, -25)
|
|
prompt:SetJustifyH ("center")
|
|
prompt:SetSize (360, 36)
|
|
f.prompt = prompt
|
|
|
|
local button_text_template = DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")
|
|
local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
|
|
|
|
local textbox = DF:CreateTextEntry (f, function()end, 380, 20, "textbox", nil, nil, options_dropdown_template)
|
|
textbox:SetPoint ("topleft", f, "topleft", 10, -60)
|
|
f.EntryBox = textbox
|
|
|
|
local button_true = DF:CreateButton (f, nil, 60, 20, "Okey", nil, nil, nil, nil, nil, nil, options_dropdown_template)
|
|
button_true:SetPoint ("bottomright", f, "bottomright", -10, 5)
|
|
f.button_true = button_true
|
|
|
|
local button_false = DF:CreateButton (f, function() f.textbox:ClearFocus() f:Hide() end, 60, 20, "Cancel", nil, nil, nil, nil, nil, nil, options_dropdown_template)
|
|
button_false:SetPoint ("bottomleft", f, "bottomleft", 10, 5)
|
|
f.button_false = button_false
|
|
|
|
local executeCallback = function()
|
|
local my_func = button_true.true_function
|
|
if (my_func) then
|
|
local okey, errormessage = pcall (my_func, textbox:GetText())
|
|
textbox:ClearFocus()
|
|
if (not okey) then
|
|
print ("error:", errormessage)
|
|
end
|
|
f:Hide()
|
|
end
|
|
end
|
|
|
|
button_true:SetClickFunction (function()
|
|
executeCallback()
|
|
end)
|
|
|
|
textbox:SetHook ("OnEnterPressed", function()
|
|
executeCallback()
|
|
end)
|
|
|
|
f:Hide()
|
|
DF.text_prompt_panel = f
|
|
end
|
|
|
|
DF.text_prompt_panel:Show()
|
|
|
|
DetailsFrameworkPrompt.EntryBox:SetText ("")
|
|
DF.text_prompt_panel.prompt:SetText (message)
|
|
DF.text_prompt_panel.button_true.true_function = callback
|
|
DF.text_prompt_panel.textbox:SetFocus (true)
|
|
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> options button -- ~options
|
|
function DF:CreateOptionsButton (parent, callback, name)
|
|
|
|
local b = CreateFrame ("button", name, parent, "BackdropTemplate")
|
|
b:SetSize (14, 14)
|
|
b:SetNormalTexture ([[Interface\GossipFrame\BinderGossipIcon]])
|
|
b:SetHighlightTexture ([[Interface\GossipFrame\BinderGossipIcon]])
|
|
b:SetPushedTexture ([[Interface\GossipFrame\BinderGossipIcon]])
|
|
b:GetNormalTexture():SetDesaturated(true)
|
|
b:GetHighlightTexture():SetDesaturated(true)
|
|
b:GetPushedTexture():SetDesaturated(true)
|
|
b:SetAlpha (0.7)
|
|
|
|
b:SetScript ("OnClick", callback)
|
|
b:SetScript ("OnEnter", function (self)
|
|
GameCooltip2:Reset()
|
|
GameCooltip2:AddLine ("Options")
|
|
GameCooltip2:ShowCooltip (self, "tooltip")
|
|
end)
|
|
b:SetScript ("OnLeave", function (self)
|
|
GameCooltip2:Hide()
|
|
end)
|
|
|
|
return b
|
|
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> feedback panel -- ~feedback
|
|
|
|
function DF:CreateFeedbackButton (parent, callback, name)
|
|
local b = CreateFrame ("button", name, parent, "BackdropTemplate")
|
|
b:SetSize (12, 13)
|
|
b:SetScript ("OnClick", callback)
|
|
b:SetScript ("OnEnter", function (self)
|
|
GameCooltip2:Reset()
|
|
GameCooltip2:AddLine ("Send Feedback")
|
|
GameCooltip2:ShowCooltip (self, "tooltip")
|
|
end)
|
|
b:SetScript ("OnLeave", function (self)
|
|
GameCooltip2:Hide()
|
|
end)
|
|
|
|
print("Framework:CreateFeedbackButton() is deprecated.")
|
|
|
|
return b
|
|
end
|
|
|
|
local backdrop_fb_line = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1,
|
|
tile = true, tileSize = 64, insets = {left = 2, right = 2, top = 2, bottom = 2}}
|
|
|
|
local on_enter_feedback = function (self)
|
|
self:SetBackdropColor (1, 1, 0, 0.5)
|
|
end
|
|
local on_leave_feedback = function (self)
|
|
self:SetBackdropColor (0, 0, 0, 0.3)
|
|
end
|
|
|
|
local on_click_feedback = function (self)
|
|
|
|
local feedback_link_textbox = DF.feedback_link_textbox
|
|
|
|
if (not feedback_link_textbox) then
|
|
local editbox = DF:CreateTextEntry (AddonFeedbackPanel, _, 275, 34)
|
|
editbox:SetAutoFocus (false)
|
|
editbox:SetHook ("OnEditFocusGained", function()
|
|
editbox.text = editbox.link
|
|
editbox:HighlightText()
|
|
end)
|
|
editbox:SetHook ("OnEditFocusLost", function()
|
|
editbox:Hide()
|
|
end)
|
|
editbox:SetHook ("OnChar", function()
|
|
editbox.text = editbox.link
|
|
editbox:HighlightText()
|
|
end)
|
|
editbox.text = ""
|
|
|
|
DF.feedback_link_textbox = editbox
|
|
feedback_link_textbox = editbox
|
|
end
|
|
|
|
feedback_link_textbox.link = self.link
|
|
feedback_link_textbox.text = self.link
|
|
feedback_link_textbox:Show()
|
|
|
|
feedback_link_textbox:SetPoint ("topleft", self.icon, "topright", 3, 0)
|
|
|
|
feedback_link_textbox:HighlightText()
|
|
|
|
feedback_link_textbox:SetFocus()
|
|
feedback_link_textbox:SetFrameLevel (self:GetFrameLevel()+2)
|
|
end
|
|
|
|
local feedback_get_fb_line = function (self)
|
|
|
|
local line = self.feedback_lines [self.next_feedback]
|
|
if (not line) then
|
|
line = CreateFrame ("frame", "AddonFeedbackPanelFB" .. self.next_feedback, self, "BackdropTemplate")
|
|
line:SetBackdrop (backdrop_fb_line)
|
|
line:SetBackdropColor (0, 0, 0, 0.3)
|
|
line:SetSize (390, 42)
|
|
line:SetPoint ("topleft", self.feedback_anchor, "bottomleft", 0, -5 + ((self.next_feedback-1) * 46 * -1))
|
|
line:SetScript ("OnEnter", on_enter_feedback)
|
|
line:SetScript ("OnLeave", on_leave_feedback)
|
|
line:SetScript ("OnMouseUp", on_click_feedback)
|
|
|
|
line.icon = line:CreateTexture (nil, "overlay")
|
|
line.icon:SetSize (90, 36)
|
|
|
|
line.desc = line:CreateFontString (nil, "overlay", "GameFontHighlightSmall")
|
|
|
|
line.icon:SetPoint ("left", line, "left", 5, 0)
|
|
line.desc:SetPoint ("left", line.icon, "right", 5, 0)
|
|
|
|
local arrow = line:CreateTexture (nil, "overlay")
|
|
arrow:SetTexture ([[Interface\Buttons\JumpUpArrow]])
|
|
arrow:SetRotation (-1.55)
|
|
arrow:SetPoint ("right", line, "right", -5, 0)
|
|
|
|
self.feedback_lines [self.next_feedback] = line
|
|
end
|
|
|
|
self.next_feedback = self.next_feedback + 1
|
|
|
|
return line
|
|
end
|
|
|
|
local on_click_feedback = function (self)
|
|
|
|
local feedback_link_textbox = DF.feedback_link_textbox
|
|
|
|
if (not feedback_link_textbox) then
|
|
local editbox = DF:CreateTextEntry (AddonFeedbackPanel, _, 275, 34)
|
|
editbox:SetAutoFocus (false)
|
|
editbox:SetHook ("OnEditFocusGained", function()
|
|
editbox.text = editbox.link
|
|
editbox:HighlightText()
|
|
end)
|
|
editbox:SetHook ("OnEditFocusLost", function()
|
|
editbox:Hide()
|
|
end)
|
|
editbox:SetHook ("OnChar", function()
|
|
editbox.text = editbox.link
|
|
editbox:HighlightText()
|
|
end)
|
|
editbox.text = ""
|
|
|
|
DF.feedback_link_textbox = editbox
|
|
feedback_link_textbox = editbox
|
|
end
|
|
|
|
feedback_link_textbox.link = self.link
|
|
feedback_link_textbox.text = self.link
|
|
feedback_link_textbox:Show()
|
|
|
|
feedback_link_textbox:SetPoint ("topleft", self.icon, "topright", 3, 0)
|
|
|
|
feedback_link_textbox:HighlightText()
|
|
|
|
feedback_link_textbox:SetFocus()
|
|
feedback_link_textbox:SetFrameLevel (self:GetFrameLevel()+2)
|
|
end
|
|
|
|
local on_enter_addon = function (self)
|
|
if (self.tooltip) then
|
|
GameCooltip2:Preset (2)
|
|
GameCooltip2:AddLine ("|cFFFFFF00" .. self.name .. "|r")
|
|
GameCooltip2:AddLine ("")
|
|
GameCooltip2:AddLine (self.tooltip)
|
|
GameCooltip2:ShowCooltip (self, "tooltip")
|
|
end
|
|
self.icon:SetBlendMode ("ADD")
|
|
end
|
|
local on_leave_addon = function (self)
|
|
if (self.tooltip) then
|
|
GameCooltip2:Hide()
|
|
end
|
|
self.icon:SetBlendMode ("BLEND")
|
|
end
|
|
local on_click_addon = function (self)
|
|
local addon_link_textbox = DF.addon_link_textbox
|
|
|
|
if (not addon_link_textbox) then
|
|
local editbox = DF:CreateTextEntry (AddonFeedbackPanel, _, 128, 64)
|
|
editbox:SetAutoFocus (false)
|
|
editbox:SetHook ("OnEditFocusGained", function()
|
|
editbox.text = editbox.link
|
|
editbox:HighlightText()
|
|
end)
|
|
editbox:SetHook ("OnEditFocusLost", function()
|
|
editbox:Hide()
|
|
end)
|
|
editbox:SetHook ("OnChar", function()
|
|
editbox.text = editbox.link
|
|
editbox:HighlightText()
|
|
end)
|
|
editbox.text = ""
|
|
|
|
DF.addon_link_textbox = editbox
|
|
addon_link_textbox = editbox
|
|
end
|
|
|
|
addon_link_textbox.link = self.link
|
|
addon_link_textbox.text = self.link
|
|
addon_link_textbox:Show()
|
|
|
|
addon_link_textbox:SetPoint ("topleft", self.icon, "topleft", 0, 0)
|
|
|
|
addon_link_textbox:HighlightText()
|
|
|
|
addon_link_textbox:SetFocus()
|
|
addon_link_textbox:SetFrameLevel (self:GetFrameLevel()+2)
|
|
end
|
|
|
|
local feedback_get_addons_line = function (self)
|
|
local line = self.addons_lines [self.next_addons]
|
|
if (not line) then
|
|
|
|
line = CreateFrame ("frame", "AddonFeedbackPanelSA" .. self.next_addons, self, "BackdropTemplate")
|
|
line:SetSize (128, 64)
|
|
|
|
if (self.next_addons == 1) then
|
|
line:SetPoint ("topleft", self.addons_anchor, "bottomleft", 0, -5)
|
|
elseif (self.next_addons_line_break == self.next_addons) then
|
|
line:SetPoint ("topleft", self.addons_anchor, "bottomleft", 0, -5 + floor (self.next_addons_line_break/3) * 66 * -1)
|
|
self.next_addons_line_break = self.next_addons_line_break + 3
|
|
else
|
|
local previous = self.addons_lines [self.next_addons - 1]
|
|
line:SetPoint ("topleft", previous, "topright", 2, 0)
|
|
end
|
|
|
|
line:SetScript ("OnEnter", on_enter_addon)
|
|
line:SetScript ("OnLeave", on_leave_addon)
|
|
line:SetScript ("OnMouseUp", on_click_addon)
|
|
|
|
line.icon = line:CreateTexture (nil, "overlay")
|
|
line.icon:SetSize (128, 64)
|
|
|
|
line.icon:SetPoint ("topleft", line, "topleft", 0, 0)
|
|
|
|
self.addons_lines [self.next_addons] = line
|
|
end
|
|
|
|
self.next_addons = self.next_addons + 1
|
|
|
|
return line
|
|
end
|
|
|
|
local default_coords = {0, 1, 0, 1}
|
|
local feedback_add_fb = function (self, table)
|
|
local line = self:GetFeedbackLine()
|
|
line.icon:SetTexture (table.icon)
|
|
line.icon:SetTexCoord (unpack (table.coords or default_coords))
|
|
line.desc:SetText (table.desc)
|
|
line.link = table.link
|
|
line:Show()
|
|
end
|
|
|
|
local feedback_add_addon = function (self, table)
|
|
local block = self:GetAddonsLine()
|
|
block.icon:SetTexture (table.icon)
|
|
block.icon:SetTexCoord (unpack (table.coords or default_coords))
|
|
block.link = table.link
|
|
block.tooltip = table.desc
|
|
block.name = table.name
|
|
block:Show()
|
|
end
|
|
|
|
local feedback_hide_all = function (self)
|
|
self.next_feedback = 1
|
|
self.next_addons = 1
|
|
|
|
for index, line in ipairs (self.feedback_lines) do
|
|
line:Hide()
|
|
end
|
|
|
|
for index, line in ipairs (self.addons_lines) do
|
|
line:Hide()
|
|
end
|
|
end
|
|
|
|
-- feedback_methods = { { icon = icon path, desc = description, link = url}}
|
|
function DF:ShowFeedbackPanel (addon_name, version, feedback_methods, more_addons)
|
|
|
|
local f = _G.AddonFeedbackPanel
|
|
|
|
if (not f) then
|
|
f = DF:Create1PxPanel (UIParent, 400, 100, addon_name .. " Feedback", "AddonFeedbackPanel", nil)
|
|
f:SetFrameStrata ("FULLSCREEN")
|
|
f:SetPoint ("center", UIParent, "center")
|
|
f:SetBackdropColor (0, 0, 0, 0.8)
|
|
f.feedback_lines = {}
|
|
f.addons_lines = {}
|
|
f.next_feedback = 1
|
|
f.next_addons = 1
|
|
f.next_addons_line_break = 4
|
|
|
|
local feedback_anchor = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
feedback_anchor:SetText ("Feedback:")
|
|
feedback_anchor:SetPoint ("topleft", f, "topleft", 5, -30)
|
|
f.feedback_anchor = feedback_anchor
|
|
local excla_text = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
excla_text:SetText ("click and copy the link")
|
|
excla_text:SetPoint ("topright", f, "topright", -5, -30)
|
|
excla_text:SetTextColor (1, 0.8, 0.2, 0.6)
|
|
|
|
local addons_anchor = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
addons_anchor:SetText ("AddOns From the Same Author:")
|
|
f.addons_anchor = addons_anchor
|
|
local excla_text2 = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
excla_text2:SetText ("click and copy the link")
|
|
excla_text2:SetTextColor (1, 0.8, 0.2, 0.6)
|
|
f.excla_text2 = excla_text2
|
|
|
|
f.GetFeedbackLine = feedback_get_fb_line
|
|
f.GetAddonsLine = feedback_get_addons_line
|
|
f.AddFeedbackMethod = feedback_add_fb
|
|
f.AddOtherAddon = feedback_add_addon
|
|
f.HideAll = feedback_hide_all
|
|
|
|
DF:SetFontSize (f.Title, 14)
|
|
|
|
end
|
|
|
|
f:HideAll()
|
|
f:SetTitle (addon_name)
|
|
|
|
for index, feedback in ipairs (feedback_methods) do
|
|
f:AddFeedbackMethod (feedback)
|
|
end
|
|
|
|
f.addons_anchor:SetPoint ("topleft", f, "topleft", 5, f.next_feedback * 50 * -1)
|
|
f.excla_text2:SetPoint ("topright", f, "topright", -5, f.next_feedback * 50 * -1)
|
|
|
|
for index, addon in ipairs (more_addons) do
|
|
f:AddOtherAddon (addon)
|
|
end
|
|
|
|
f:SetHeight (80 + ((f.next_feedback-1) * 50) + (ceil ((f.next_addons-1)/3) * 66))
|
|
|
|
f:Show()
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> chart panel -- ~chart
|
|
|
|
local chart_panel_backdrop = {bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16,
|
|
edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border", edgeSize = 32, insets = {left = 5, right = 5, top = 5, bottom = 5}}
|
|
|
|
local chart_panel_align_timelabels = function (self, elapsed_time)
|
|
|
|
self.TimeScale = elapsed_time
|
|
|
|
local linha = self.TimeLabels [17]
|
|
local minutos, segundos = math.floor (elapsed_time / 60), math.floor (elapsed_time % 60)
|
|
if (segundos < 10) then
|
|
segundos = "0" .. segundos
|
|
end
|
|
|
|
if (minutos > 0) then
|
|
if (minutos < 10) then
|
|
minutos = "0" .. minutos
|
|
end
|
|
linha:SetText (minutos .. ":" .. segundos)
|
|
else
|
|
linha:SetText ("00:" .. segundos)
|
|
end
|
|
|
|
local time_div = elapsed_time / 16 --786 -- 49.125
|
|
|
|
for i = 2, 16 do
|
|
|
|
local linha = self.TimeLabels [i]
|
|
|
|
local this_time = time_div * (i-1)
|
|
local minutos, segundos = math.floor (this_time / 60), math.floor (this_time % 60)
|
|
|
|
if (segundos < 10) then
|
|
segundos = "0" .. segundos
|
|
end
|
|
|
|
if (minutos > 0) then
|
|
if (minutos < 10) then
|
|
minutos = "0" .. minutos
|
|
end
|
|
linha:SetText (minutos .. ":" .. segundos)
|
|
else
|
|
linha:SetText ("00:" .. segundos)
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
local chart_panel_set_scale = function (self, amt, func, text)
|
|
if (type (amt) ~= "number") then
|
|
return
|
|
end
|
|
|
|
--each line amount, then multiply the line index by this number
|
|
local piece = amt / 8
|
|
|
|
for i = 1, 8 do
|
|
if (func) then
|
|
self ["dpsamt" .. math.abs (i-9)]:SetText (func (piece*i))
|
|
else
|
|
if (piece*i > 1) then
|
|
self ["dpsamt" .. math.abs (i-9)]:SetText (DF.FormatNumber (piece*i))
|
|
else
|
|
self ["dpsamt" .. math.abs (i-9)]:SetText (format ("%.3f", piece*i))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local chart_panel_can_move = function (self, can)
|
|
self.can_move = can
|
|
end
|
|
|
|
local chart_panel_overlay_reset = function (self)
|
|
self.OverlaysAmount = 1
|
|
for index, pack in ipairs (self.Overlays) do
|
|
for index2, texture in ipairs (pack) do
|
|
texture:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
local chart_panel_reset = function (self)
|
|
|
|
self.Graphic:ResetData()
|
|
self.Graphic.max_value = 0
|
|
|
|
self.TimeScale = nil
|
|
self.BoxLabelsAmount = 1
|
|
table.wipe (self.GData)
|
|
table.wipe (self.OData)
|
|
|
|
for index, box in ipairs (self.BoxLabels) do
|
|
box.check:Hide()
|
|
box.button:Hide()
|
|
box.box:Hide()
|
|
box.text:Hide()
|
|
box.border:Hide()
|
|
box.showing = false
|
|
end
|
|
|
|
chart_panel_overlay_reset (self)
|
|
end
|
|
|
|
local chart_panel_enable_line = function (f, thisbox)
|
|
|
|
local index = thisbox.index
|
|
local type = thisbox.type
|
|
|
|
if (thisbox.enabled) then
|
|
--disable
|
|
thisbox.check:Hide()
|
|
thisbox.enabled = false
|
|
else
|
|
--enable
|
|
thisbox.check:Show()
|
|
thisbox.enabled = true
|
|
end
|
|
|
|
if (type == "graphic") then
|
|
|
|
f.Graphic:ResetData()
|
|
f.Graphic.max_value = 0
|
|
|
|
local max = 0
|
|
local max_time = 0
|
|
|
|
for index, box in ipairs (f.BoxLabels) do
|
|
if (box.type == type and box.showing and box.enabled) then
|
|
local data = f.GData [index]
|
|
|
|
f.Graphic:AddDataSeries (data[1], data[2], nil, data[3])
|
|
|
|
if (data[4] > max) then
|
|
max = data[4]
|
|
end
|
|
if (data [5] > max_time) then
|
|
max_time = data [5]
|
|
end
|
|
end
|
|
end
|
|
|
|
f:SetScale (max)
|
|
f:SetTime (max_time)
|
|
|
|
elseif (type == "overlay") then
|
|
|
|
chart_panel_overlay_reset (f)
|
|
|
|
for index, box in ipairs (f.BoxLabels) do
|
|
if (box.type == type and box.showing and box.enabled) then
|
|
|
|
f:AddOverlay (box.index)
|
|
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
local create_box = function (self, next_box)
|
|
|
|
local thisbox = {}
|
|
self.BoxLabels [next_box] = thisbox
|
|
|
|
local box = DF:NewImage (self.Graphic, nil, 16, 16, "border")
|
|
local text = DF:NewLabel (self.Graphic)
|
|
|
|
local border = DF:NewImage (self.Graphic, [[Interface\DialogFrame\UI-DialogBox-Gold-Corner]], 30, 30, "artwork")
|
|
border:SetPoint ("center", box, "center", -3, -4)
|
|
border:SetTexture ([[Interface\DialogFrame\UI-DialogBox-Gold-Corner]])
|
|
|
|
local checktexture = DF:NewImage (self.Graphic, [[Interface\Buttons\UI-CheckBox-Check]], 18, 18, "overlay")
|
|
checktexture:SetPoint ("center", box, "center", 0, -1)
|
|
checktexture:SetTexture ([[Interface\Buttons\UI-CheckBox-Check]])
|
|
|
|
thisbox.box = box
|
|
thisbox.text = text
|
|
thisbox.border = border
|
|
thisbox.check = checktexture
|
|
thisbox.enabled = true
|
|
|
|
local button = CreateFrame ("button", nil, self.Graphic, "BackdropTemplate")
|
|
button:SetSize (20, 20)
|
|
button:SetScript ("OnClick", function()
|
|
chart_panel_enable_line (self, thisbox)
|
|
end)
|
|
button:SetPoint ("topleft", box.widget or box, "topleft", 0, 0)
|
|
button:SetPoint ("bottomright", box.widget or box, "bottomright", 0, 0)
|
|
|
|
button:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
button:SetBackdropColor (0, 0, 0, 0.0)
|
|
button:SetBackdropBorderColor (0, 0, 0, 1)
|
|
|
|
thisbox.button = button
|
|
|
|
thisbox.box:SetPoint ("right", text, "left", -4, 0)
|
|
|
|
if (next_box == 1) then
|
|
thisbox.text:SetPoint ("topright", self, "topright", -35, -16)
|
|
else
|
|
thisbox.text:SetPoint ("right", self.BoxLabels [next_box-1].box, "left", -17, 0)
|
|
end
|
|
|
|
return thisbox
|
|
|
|
end
|
|
|
|
local realign_labels = function (self)
|
|
|
|
if (not self.ShowHeader) then
|
|
for _, box in ipairs (self.BoxLabels) do
|
|
box.check:Hide()
|
|
box.button:Hide()
|
|
box.border:Hide()
|
|
box.box:Hide()
|
|
box.text:Hide()
|
|
end
|
|
return
|
|
end
|
|
|
|
local width = self:GetWidth() - 108
|
|
|
|
local first_box = self.BoxLabels [1]
|
|
first_box.text:SetPoint ("topright", self, "topright", -35, -16)
|
|
|
|
local line_width = first_box.text:GetStringWidth() + 26
|
|
|
|
for i = 2, #self.BoxLabels do
|
|
|
|
local box = self.BoxLabels [i]
|
|
|
|
if (box.box:IsShown()) then
|
|
|
|
line_width = line_width + box.text:GetStringWidth() + 26
|
|
|
|
if (line_width > width) then
|
|
line_width = box.text:GetStringWidth() + 26
|
|
box.text:SetPoint ("topright", self, "topright", -35, -40)
|
|
else
|
|
box.text:SetPoint ("right", self.BoxLabels [i-1].box, "left", -27, 0)
|
|
end
|
|
else
|
|
break
|
|
end
|
|
end
|
|
|
|
if (self.HeaderOnlyIndicator) then
|
|
for _, box in ipairs (self.BoxLabels) do
|
|
box.check:Hide()
|
|
box.button:Hide()
|
|
end
|
|
return
|
|
end
|
|
|
|
end
|
|
|
|
local chart_panel_add_label = function (self, color, name, type, number)
|
|
|
|
local next_box = self.BoxLabelsAmount
|
|
local thisbox = self.BoxLabels [next_box]
|
|
|
|
if (not thisbox) then
|
|
thisbox = create_box (self, next_box)
|
|
end
|
|
|
|
self.BoxLabelsAmount = self.BoxLabelsAmount + 1
|
|
|
|
thisbox.type = type
|
|
thisbox.index = number
|
|
|
|
thisbox.box:SetColorTexture (unpack (color))
|
|
thisbox.text:SetText (name)
|
|
|
|
thisbox.check:Show()
|
|
thisbox.button:Show()
|
|
thisbox.border:Hide()
|
|
thisbox.box:Show()
|
|
thisbox.text:Show()
|
|
|
|
thisbox.showing = true
|
|
thisbox.enabled = true
|
|
|
|
realign_labels (self)
|
|
|
|
end
|
|
|
|
local line_default_color = {1, 1, 1}
|
|
local draw_overlay = function (self, this_overlay, overlayData, color)
|
|
|
|
local pixel = self.Graphic:GetWidth() / self.TimeScale
|
|
local index = 1
|
|
local r, g, b, a = unpack (color or line_default_color)
|
|
|
|
for i = 1, #overlayData, 2 do
|
|
local aura_start = overlayData [i]
|
|
local aura_end = overlayData [i+1]
|
|
|
|
local this_block = this_overlay [index]
|
|
if (not this_block) then
|
|
this_block = self.Graphic:CreateTexture (nil, "border")
|
|
tinsert (this_overlay, this_block)
|
|
end
|
|
this_block:SetHeight (self.Graphic:GetHeight())
|
|
|
|
this_block:SetPoint ("left", self.Graphic, "left", pixel * aura_start, 0)
|
|
if (aura_end) then
|
|
this_block:SetWidth ((aura_end-aura_start)*pixel)
|
|
else
|
|
--malformed table
|
|
this_block:SetWidth (pixel*5)
|
|
end
|
|
|
|
this_block:SetColorTexture (r, g, b, a or 0.25)
|
|
this_block:Show()
|
|
|
|
index = index + 1
|
|
end
|
|
|
|
end
|
|
|
|
local chart_panel_add_overlay = function (self, overlayData, color, name, icon)
|
|
|
|
if (not self.TimeScale) then
|
|
error ("Use SetTime (time) before adding an overlay.")
|
|
end
|
|
|
|
if (type (overlayData) == "number") then
|
|
local overlay_index = overlayData
|
|
draw_overlay (self, self.Overlays [self.OverlaysAmount], self.OData [overlay_index][1], self.OData [overlay_index][2])
|
|
else
|
|
local this_overlay = self.Overlays [self.OverlaysAmount]
|
|
if (not this_overlay) then
|
|
this_overlay = {}
|
|
tinsert (self.Overlays, this_overlay)
|
|
end
|
|
|
|
draw_overlay (self, this_overlay, overlayData, color)
|
|
|
|
tinsert (self.OData, {overlayData, color or line_default_color})
|
|
if (name and self.HeaderShowOverlays) then
|
|
self:AddLabel (color or line_default_color, name, "overlay", #self.OData)
|
|
end
|
|
end
|
|
|
|
self.OverlaysAmount = self.OverlaysAmount + 1
|
|
end
|
|
|
|
-- Define the tricube weight function
|
|
function calc_cubeweight (i, j, d)
|
|
local w = ( 1 - math.abs ((j-i)/d)^3)^3
|
|
if w < 0 then
|
|
w = 0
|
|
end
|
|
return w
|
|
end
|
|
|
|
local calc_lowess_smoothing = function (self, data, bandwidth)
|
|
local length = #data
|
|
local newData = {}
|
|
|
|
for i = 1, length do
|
|
local A = 0
|
|
local B = 0
|
|
local C = 0
|
|
local D = 0
|
|
local E = 0
|
|
|
|
-- Calculate span of values to be included in the regression
|
|
local jmin = floor (i-bandwidth/2)
|
|
local jmax = ceil (i+bandwidth/2)
|
|
if jmin < 1 then
|
|
jmin = 1
|
|
end
|
|
if jmax > length then
|
|
jmax = length
|
|
end
|
|
|
|
-- For all the values in the span, compute the weight and then the linear fit
|
|
|
|
for j = jmin, jmax do
|
|
w = calc_cubeweight (i, j, bandwidth/2)
|
|
x = j
|
|
y = data [j]
|
|
|
|
A = A + w*x
|
|
B = B + w*y
|
|
C = C + w*x^2
|
|
D = D + w*x*y
|
|
E = E + w
|
|
end
|
|
|
|
-- Calculate a (slope) and b (offset) for the linear fit
|
|
local a = (A*B-D*E)/(A^2 - C*E)
|
|
local b = (A*D-B*C)/(A^2 - C*E)
|
|
|
|
-- Calculate the smoothed value by the formula y=a*x+b (x <- i)
|
|
newData [i] = a*i+b
|
|
|
|
end
|
|
|
|
return newData
|
|
end
|
|
|
|
local calc_stddev = function (self, data)
|
|
local total = 0
|
|
for i = 1, #data do
|
|
total = total + data[i]
|
|
end
|
|
local mean = total / #data
|
|
|
|
local totalDistance = 0
|
|
for i = 1, #data do
|
|
totalDistance = totalDistance + ((data[i] - mean) ^ 2)
|
|
end
|
|
|
|
local deviation = math.sqrt (totalDistance / #data)
|
|
return deviation
|
|
end
|
|
|
|
|
|
|
|
local SMA_table = {}
|
|
local SMA_max = 0
|
|
local reset_SMA = function()
|
|
table.wipe (SMA_table)
|
|
SMA_max = 0
|
|
end
|
|
|
|
local calc_SMA
|
|
calc_SMA = function (a, b, ...)
|
|
if (b) then
|
|
return calc_SMA (a + b, ...)
|
|
else
|
|
return a
|
|
end
|
|
end
|
|
|
|
local do_SMA = function (value, max_value)
|
|
|
|
if (#SMA_table == 10) then
|
|
tremove (SMA_table, 1)
|
|
end
|
|
|
|
SMA_table [#SMA_table + 1] = value
|
|
|
|
local new_value = calc_SMA (unpack (SMA_table)) / #SMA_table
|
|
|
|
if (new_value > SMA_max) then
|
|
SMA_max = new_value
|
|
return new_value, SMA_max
|
|
else
|
|
return new_value
|
|
end
|
|
|
|
end
|
|
|
|
local chart_panel_onresize = function (self)
|
|
local width, height = self:GetSize()
|
|
local spacement = width - 78 - 60
|
|
spacement = spacement / 16
|
|
|
|
for i = 1, 17 do
|
|
local label = self.TimeLabels [i]
|
|
label:SetPoint ("bottomleft", self, "bottomleft", 78 + ((i-1)*spacement), self.TimeLabelsHeight)
|
|
label.line:SetHeight (height - 45)
|
|
end
|
|
|
|
local spacement = (self.Graphic:GetHeight()) / 8
|
|
for i = 1, 8 do
|
|
self ["dpsamt"..i]:SetPoint ("TOPLEFT", self, "TOPLEFT", 27, -25 + (-(spacement* (i-1))) )
|
|
self ["dpsamt"..i].line:SetWidth (width-20)
|
|
end
|
|
|
|
self.Graphic:SetSize (width - 135, height - 67)
|
|
self.Graphic:SetPoint ("topleft", self, "topleft", 108, -35)
|
|
end
|
|
|
|
local chart_panel_add_data = function (self, graphicData, color, name, elapsed_time, lineTexture, smoothLevel, firstIndex)
|
|
|
|
local f = self
|
|
self = self.Graphic
|
|
|
|
local _data = {}
|
|
local max_value = graphicData.max_value
|
|
local amount = #graphicData
|
|
|
|
local scaleW = 1/self:GetWidth()
|
|
|
|
local content = graphicData
|
|
tinsert (content, 1, 0)
|
|
tinsert (content, 1, 0)
|
|
tinsert (content, #content+1, 0)
|
|
tinsert (content, #content+1, 0)
|
|
|
|
local _i = 3
|
|
|
|
local graphMaxDps = math.max (self.max_value, max_value)
|
|
|
|
if (not smoothLevel) then
|
|
while (_i <= #content-2) do
|
|
local v = (content[_i-2]+content[_i-1]+content[_i]+content[_i+1]+content[_i+2])/5 --> normalize
|
|
_data [#_data+1] = {scaleW*(_i-2), v/graphMaxDps} --> x and y coords
|
|
_i = _i + 1
|
|
end
|
|
|
|
elseif (smoothLevel == "SHORT") then
|
|
while (_i <= #content-2) do
|
|
local value = (content[_i] + content[_i+1]) / 2
|
|
_data [#_data+1] = {scaleW*(_i-2), value}
|
|
_data [#_data+1] = {scaleW*(_i-2), value}
|
|
_i = _i + 2
|
|
end
|
|
|
|
elseif (smoothLevel == "SMA") then
|
|
reset_SMA()
|
|
while (_i <= #content-2) do
|
|
local value, is_new_max_value = do_SMA (content[_i], max_value)
|
|
if (is_new_max_value) then
|
|
max_value = is_new_max_value
|
|
end
|
|
_data [#_data+1] = {scaleW*(_i-2), value} --> x and y coords
|
|
_i = _i + 1
|
|
end
|
|
|
|
elseif (smoothLevel == -1) then
|
|
while (_i <= #content-2) do
|
|
local current = content[_i]
|
|
|
|
local minus_2 = content[_i-2] * 0.6
|
|
local minus_1 = content[_i-1] * 0.8
|
|
local plus_1 = content[_i+1] * 0.8
|
|
local plus_2 = content[_i+2] * 0.6
|
|
|
|
local v = (current + minus_2 + minus_1 + plus_1 + plus_2)/5 --> normalize
|
|
_data [#_data+1] = {scaleW*(_i-2), v/graphMaxDps} --> x and y coords
|
|
_i = _i + 1
|
|
end
|
|
|
|
elseif (smoothLevel == 1) then
|
|
_i = 2
|
|
while (_i <= #content-1) do
|
|
local v = (content[_i-1]+content[_i]+content[_i+1])/3 --> normalize
|
|
_data [#_data+1] = {scaleW*(_i-1), v/graphMaxDps} --> x and y coords
|
|
_i = _i + 1
|
|
end
|
|
|
|
elseif (smoothLevel == 2) then
|
|
_i = 1
|
|
while (_i <= #content) do
|
|
local v = content[_i] --> do not normalize
|
|
_data [#_data+1] = {scaleW*(_i), v/graphMaxDps} --> x and y coords
|
|
_i = _i + 1
|
|
end
|
|
|
|
end
|
|
|
|
tremove (content, 1)
|
|
tremove (content, 1)
|
|
tremove (content, #graphicData)
|
|
tremove (content, #graphicData)
|
|
|
|
if (max_value > self.max_value) then
|
|
--> normalize previous data
|
|
if (self.max_value > 0) then
|
|
local normalizePercent = self.max_value / max_value
|
|
for dataIndex, Data in ipairs (self.Data) do
|
|
local Points = Data.Points
|
|
for i = 1, #Points do
|
|
Points[i][2] = Points[i][2]*normalizePercent
|
|
end
|
|
end
|
|
end
|
|
|
|
self.max_value = max_value
|
|
f:SetScale (max_value)
|
|
|
|
end
|
|
|
|
tinsert (f.GData, {_data, color or line_default_color, lineTexture, max_value, elapsed_time})
|
|
if (name) then
|
|
f:AddLabel (color or line_default_color, name, "graphic", #f.GData)
|
|
end
|
|
|
|
if (firstIndex) then
|
|
if (lineTexture) then
|
|
if (not lineTexture:find ("\\") and not lineTexture:find ("//")) then
|
|
local path = string.match (debugstack (1, 1, 0), "AddOns\\(.+)LibGraph%-2%.0%.lua")
|
|
if path then
|
|
lineTexture = "Interface\\AddOns\\" .. path .. lineTexture
|
|
else
|
|
lineTexture = nil
|
|
end
|
|
end
|
|
end
|
|
|
|
table.insert (self.Data, 1, {Points = _data, Color = color or line_default_color, lineTexture = lineTexture, ElapsedTime = elapsed_time})
|
|
self.NeedsUpdate = true
|
|
else
|
|
self:AddDataSeries (_data, color or line_default_color, nil, lineTexture)
|
|
self.Data [#self.Data].ElapsedTime = elapsed_time
|
|
end
|
|
|
|
local max_time = 0
|
|
for _, data in ipairs (self.Data) do
|
|
if (data.ElapsedTime > max_time) then
|
|
max_time = data.ElapsedTime
|
|
end
|
|
end
|
|
|
|
f:SetTime (max_time)
|
|
|
|
chart_panel_onresize (f)
|
|
end
|
|
|
|
|
|
|
|
|
|
local chart_panel_vlines_on = function (self)
|
|
for i = 1, 17 do
|
|
local label = self.TimeLabels [i]
|
|
label.line:Show()
|
|
end
|
|
end
|
|
|
|
local chart_panel_vlines_off = function (self)
|
|
for i = 1, 17 do
|
|
local label = self.TimeLabels [i]
|
|
label.line:Hide()
|
|
end
|
|
end
|
|
|
|
local chart_panel_set_title = function (self, title)
|
|
self.chart_title.text = title
|
|
end
|
|
|
|
local chart_panel_mousedown = function (self, button)
|
|
if (button == "LeftButton" and self.can_move) then
|
|
if (not self.isMoving) then
|
|
self:StartMoving()
|
|
self.isMoving = true
|
|
end
|
|
elseif (button == "RightButton" and not self.no_right_click_close) then
|
|
if (not self.isMoving) then
|
|
self:Hide()
|
|
end
|
|
end
|
|
end
|
|
local chart_panel_mouseup = function (self, button)
|
|
if (button == "LeftButton" and self.isMoving) then
|
|
self:StopMovingOrSizing()
|
|
self.isMoving = nil
|
|
end
|
|
end
|
|
|
|
local chart_panel_hide_close_button = function (self)
|
|
self.CloseButton:Hide()
|
|
end
|
|
|
|
local chart_panel_right_click_close = function (self, value)
|
|
if (type (value) == "boolean") then
|
|
if (value) then
|
|
self.no_right_click_close = nil
|
|
else
|
|
self.no_right_click_close = true
|
|
end
|
|
end
|
|
end
|
|
|
|
function DF:CreateChartPanel (parent, w, h, name)
|
|
|
|
if (not name) then
|
|
name = "DFPanel" .. DF.PanelCounter
|
|
DF.PanelCounter = DF.PanelCounter + 1
|
|
end
|
|
|
|
parent = parent or UIParent
|
|
w = w or 800
|
|
h = h or 500
|
|
|
|
local f = CreateFrame ("frame", name, parent, "BackdropTemplate")
|
|
f:SetSize (w or 500, h or 400)
|
|
f:EnableMouse (true)
|
|
f:SetMovable (true)
|
|
|
|
f:SetScript ("OnMouseDown", chart_panel_mousedown)
|
|
f:SetScript ("OnMouseUp", chart_panel_mouseup)
|
|
|
|
f:SetBackdrop (chart_panel_backdrop)
|
|
f:SetBackdropColor (.3, .3, .3, .3)
|
|
|
|
local c = CreateFrame ("Button", nil, f, "UIPanelCloseButton", "BackdropTemplate")
|
|
c:SetWidth (32)
|
|
c:SetHeight (32)
|
|
c:SetPoint ("TOPRIGHT", f, "TOPRIGHT", -3, -7)
|
|
c:SetFrameLevel (f:GetFrameLevel()+1)
|
|
c:SetAlpha (0.9)
|
|
f.CloseButton = c
|
|
|
|
local title = DF:NewLabel (f, nil, "$parentTitle", "chart_title", "Chart!", nil, 20, {1, 1, 0})
|
|
title:SetPoint ("topleft", f, "topleft", 110, -13)
|
|
|
|
f.Overlays = {}
|
|
f.OverlaysAmount = 1
|
|
|
|
f.BoxLabels = {}
|
|
f.BoxLabelsAmount = 1
|
|
|
|
f.ShowHeader = true
|
|
f.HeaderOnlyIndicator = false
|
|
f.HeaderShowOverlays = true
|
|
|
|
--graphic
|
|
local g = LibStub:GetLibrary("LibGraph-2.0"):CreateGraphLine (name .. "Graphic", f, "topleft","topleft", 108, -35, w - 120, h - 67)
|
|
g:SetXAxis (-1,1)
|
|
g:SetYAxis (-1,1)
|
|
g:SetGridSpacing (false, false)
|
|
g:SetGridColor ({0.5,0.5,0.5,0.3})
|
|
g:SetAxisDrawing (false,false)
|
|
g:SetAxisColor({1.0,1.0,1.0,1.0})
|
|
g:SetAutoScale (true)
|
|
g:SetLineTexture ("smallline")
|
|
g:SetBorderSize ("right", 0.001)
|
|
g:SetBorderSize ("left", 0.000)
|
|
g:SetBorderSize ("top", 0.002)
|
|
g:SetBorderSize ("bottom", 0.001)
|
|
g.VerticalLines = {}
|
|
g.max_value = 0
|
|
|
|
g:SetLineTexture ("line")
|
|
|
|
f.Graphic = g
|
|
f.GData = {}
|
|
f.OData = {}
|
|
f.ChartFrames = {}
|
|
|
|
--div lines
|
|
for i = 1, 8, 1 do
|
|
local line = g:CreateTexture (nil, "overlay")
|
|
line:SetColorTexture (1, 1, 1, .05)
|
|
line:SetWidth (670)
|
|
line:SetHeight (1.1)
|
|
|
|
local s = f:CreateFontString (nil, "overlay", "GameFontHighlightSmall")
|
|
f ["dpsamt"..i] = s
|
|
s:SetText ("100k")
|
|
s:SetPoint ("topleft", f, "topleft", 27, -61 + (-(24.6*i)))
|
|
|
|
line:SetPoint ("topleft", s, "bottom", -27, 0)
|
|
line:SetPoint ("topright", g, "right", 0, 0)
|
|
s.line = line
|
|
end
|
|
|
|
--create time labels and the bottom texture to use as a background to these labels
|
|
f.TimeLabels = {}
|
|
f.TimeLabelsHeight = 16
|
|
|
|
for i = 1, 17 do
|
|
local time = f:CreateFontString (nil, "overlay", "GameFontHighlightSmall")
|
|
time:SetText ("00:00")
|
|
time:SetPoint ("bottomleft", f, "bottomleft", 78 + ((i-1)*36), f.TimeLabelsHeight)
|
|
f.TimeLabels [i] = time
|
|
|
|
local line = f:CreateTexture (nil, "border")
|
|
line:SetSize (1, h-45)
|
|
line:SetColorTexture (1, 1, 1, .1)
|
|
line:SetPoint ("bottomleft", time, "topright", 0, -10)
|
|
line:Hide()
|
|
time.line = line
|
|
end
|
|
|
|
local bottom_texture = DF:NewImage (f, nil, 702, 25, "background", nil, nil, "$parentBottomTexture")
|
|
bottom_texture:SetColorTexture (.1, .1, .1, .7)
|
|
bottom_texture:SetPoint ("topright", g, "bottomright", 0, 0)
|
|
bottom_texture:SetPoint ("bottomleft", f, "bottomleft", 8, 12)
|
|
|
|
|
|
|
|
f.SetTime = chart_panel_align_timelabels
|
|
f.EnableVerticalLines = chart_panel_vlines_on
|
|
f.DisableVerticalLines = chart_panel_vlines_off
|
|
f.SetTitle = chart_panel_set_title
|
|
f.SetScale = chart_panel_set_scale
|
|
f.Reset = chart_panel_reset
|
|
f.AddLine = chart_panel_add_data
|
|
f.CanMove = chart_panel_can_move
|
|
f.AddLabel = chart_panel_add_label
|
|
f.AddOverlay = chart_panel_add_overlay
|
|
f.HideCloseButton = chart_panel_hide_close_button
|
|
f.RightClickClose = chart_panel_right_click_close
|
|
f.CalcStdDev = calc_stddev
|
|
f.CalcLowessSmoothing = calc_lowess_smoothing
|
|
|
|
f:SetScript ("OnSizeChanged", chart_panel_onresize)
|
|
chart_panel_onresize (f)
|
|
|
|
return f
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~gframe
|
|
local gframe_on_enter_line = function (self)
|
|
self:SetBackdropColor (0, 0, 0, 0)
|
|
|
|
local parent = self:GetParent()
|
|
local ball = self.ball
|
|
ball:SetBlendMode ("ADD")
|
|
|
|
local on_enter = parent._onenter_line
|
|
if (on_enter) then
|
|
return on_enter (self, parent)
|
|
end
|
|
end
|
|
|
|
local gframe_on_leave_line = function (self)
|
|
self:SetBackdropColor (0, 0, 0, .6)
|
|
|
|
local parent = self:GetParent()
|
|
local ball = self.ball
|
|
ball:SetBlendMode ("BLEND")
|
|
|
|
local on_leave = parent._onleave_line
|
|
if (on_leave) then
|
|
return on_leave (self, parent)
|
|
end
|
|
end
|
|
|
|
local gframe_create_line = function (self)
|
|
local index = #self._lines+1
|
|
|
|
local f = CreateFrame ("frame", nil, self, "BackdropTemplate")
|
|
self._lines [index] = f
|
|
f.id = index
|
|
f:SetScript ("OnEnter", gframe_on_enter_line)
|
|
f:SetScript ("OnLeave", gframe_on_leave_line)
|
|
|
|
f:SetWidth (self._linewidth)
|
|
|
|
if (index == 1) then
|
|
f:SetPoint ("topleft", self, "topleft")
|
|
f:SetPoint ("bottomleft", self, "bottomleft")
|
|
else
|
|
local previous_line = self._lines [index-1]
|
|
f:SetPoint ("topleft", previous_line, "topright")
|
|
f:SetPoint ("bottomleft", previous_line, "bottomright")
|
|
end
|
|
|
|
local t = f:CreateTexture (nil, "background")
|
|
t:SetWidth (1)
|
|
t:SetPoint ("topright", f, "topright")
|
|
t:SetPoint ("bottomright", f, "bottomright")
|
|
t:SetColorTexture (1, 1, 1, .1)
|
|
f.grid = t
|
|
|
|
local b = f:CreateTexture (nil, "overlay")
|
|
b:SetTexture ([[Interface\COMMON\Indicator-Yellow]])
|
|
b:SetSize (16, 16)
|
|
f.ball = b
|
|
local anchor = CreateFrame ("frame", nil, f, "BackdropTemplate")
|
|
anchor:SetAllPoints (b)
|
|
b.tooltip_anchor = anchor
|
|
|
|
local spellicon = f:CreateTexture (nil, "artwork")
|
|
spellicon:SetPoint ("bottom", b, "bottom", 0, 10)
|
|
spellicon:SetSize (16, 16)
|
|
f.spellicon = spellicon
|
|
|
|
local text = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
local textBackground = f:CreateTexture (nil, "artwork")
|
|
textBackground:SetSize (30, 16)
|
|
textBackground:SetColorTexture (0, 0, 0, 0.5)
|
|
textBackground:SetPoint ("bottom", f.ball, "top", 0, -6)
|
|
text:SetPoint ("center", textBackground, "center")
|
|
DF:SetFontSize (text, 10)
|
|
f.text = text
|
|
f.textBackground = textBackground
|
|
|
|
local timeline = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
timeline:SetPoint ("bottomright", f, "bottomright", -2, 0)
|
|
DF:SetFontSize (timeline, 8)
|
|
f.timeline = timeline
|
|
|
|
return f
|
|
end
|
|
|
|
local gframe_getline = function (self, index)
|
|
local line = self._lines [index]
|
|
if (not line) then
|
|
line = gframe_create_line (self)
|
|
end
|
|
return line
|
|
end
|
|
|
|
local gframe_reset = function (self)
|
|
for i, line in ipairs (self._lines) do
|
|
line:Hide()
|
|
end
|
|
if (self.GraphLib_Lines_Used) then
|
|
for i = #self.GraphLib_Lines_Used, 1, -1 do
|
|
local line = tremove (self.GraphLib_Lines_Used)
|
|
tinsert (self.GraphLib_Lines, line)
|
|
line:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
local gframe_update = function (self, lines)
|
|
|
|
local g = LibStub:GetLibrary ("LibGraph-2.0")
|
|
local h = self:GetHeight()/100
|
|
local amtlines = #lines
|
|
local linewidth = self._linewidth
|
|
|
|
local max_value = 0
|
|
for i = 1, amtlines do
|
|
if (lines [i].value > max_value) then
|
|
max_value = lines [i].value
|
|
end
|
|
end
|
|
|
|
self.MaxValue = max_value
|
|
|
|
local o = 1
|
|
local lastvalue = self:GetHeight()/2
|
|
max_value = math.max (max_value, 0.0000001)
|
|
|
|
for i = 1, min (amtlines, self._maxlines) do
|
|
|
|
local data = lines [i]
|
|
|
|
local pvalue = data.value / max_value * 100
|
|
if (pvalue > 98) then
|
|
pvalue = 98
|
|
end
|
|
pvalue = pvalue * h
|
|
|
|
g:DrawLine (self, (o-1)*linewidth, lastvalue, o*linewidth, pvalue, linewidth, {1, 1, 1, 1}, "overlay")
|
|
lastvalue = pvalue
|
|
|
|
local line = self:GetLine (i)
|
|
line:Show()
|
|
line.ball:Show()
|
|
|
|
line.ball:SetPoint ("bottomleft", self, "bottomleft", (o*linewidth)-8, pvalue-8)
|
|
line.spellicon:SetTexture (nil)
|
|
line.timeline:SetText (data.text)
|
|
line.timeline:Show()
|
|
|
|
if (data.utext) then
|
|
line.text:Show()
|
|
line.textBackground:Show()
|
|
line.text:SetText (data.utext)
|
|
else
|
|
line.text:Hide()
|
|
line.textBackground:Hide()
|
|
end
|
|
|
|
line.data = data
|
|
|
|
o = o + 1
|
|
end
|
|
|
|
end
|
|
|
|
function DF:CreateGFrame (parent, w, h, linewidth, onenter, onleave, member, name)
|
|
local f = CreateFrame ("frame", name, parent, "BackdropTemplate")
|
|
f:SetSize (w or 450, h or 150)
|
|
--f.CustomLine = [[Interface\AddOns\Details\Libs\LibGraph-2.0\line]]
|
|
|
|
if (member) then
|
|
parent [member] = f
|
|
end
|
|
|
|
f.CreateLine = gframe_create_line
|
|
f.GetLine = gframe_getline
|
|
f.Reset = gframe_reset
|
|
f.UpdateLines = gframe_update
|
|
|
|
f.MaxValue = 0
|
|
|
|
f._lines = {}
|
|
|
|
f._onenter_line = onenter
|
|
f._onleave_line = onleave
|
|
|
|
f._linewidth = linewidth or 50
|
|
f._maxlines = floor (f:GetWidth() / f._linewidth)
|
|
|
|
return f
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~buttoncontainer
|
|
|
|
function DF:CreateButtonContainer (parent, name)
|
|
local f = CreateFrame ("frame", name, parent, "BackdropTemplate")
|
|
-- f.
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> options tabs and buttons -dot
|
|
|
|
function DF:FindHighestParent (self)
|
|
local f
|
|
if (self:GetParent() == UIParent) then
|
|
f = self
|
|
end
|
|
if (not f) then
|
|
f = self
|
|
for i = 1, 6 do
|
|
local parent = f:GetParent()
|
|
if (parent == UIParent) then
|
|
break
|
|
else
|
|
f = parent
|
|
end
|
|
end
|
|
end
|
|
|
|
return f
|
|
end
|
|
|
|
DF.TabContainerFunctions = {}
|
|
|
|
local button_tab_template = DF.table.copy ({}, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
button_tab_template.backdropbordercolor = nil
|
|
|
|
DF.TabContainerFunctions.CreateUnderlineGlow = function (button)
|
|
local selectedGlow = button:CreateTexture (nil, "background", -4)
|
|
selectedGlow:SetPoint ("topleft", button.widget, "bottomleft", -7, 0)
|
|
selectedGlow:SetPoint ("topright", button.widget, "bottomright", 7, 0)
|
|
selectedGlow:SetTexture ([[Interface\BUTTONS\UI-Panel-Button-Glow]])
|
|
selectedGlow:SetTexCoord (0, 95/128, 30/64, 38/64)
|
|
selectedGlow:SetBlendMode ("ADD")
|
|
selectedGlow:SetHeight (8)
|
|
selectedGlow:SetAlpha (.75)
|
|
selectedGlow:Hide()
|
|
button.selectedUnderlineGlow = selectedGlow
|
|
end
|
|
|
|
DF.TabContainerFunctions.OnMouseDown = function (self, button)
|
|
--> search for UIParent
|
|
local f = DF:FindHighestParent (self)
|
|
local container = self:GetParent()
|
|
|
|
if (button == "LeftButton") then
|
|
if (not f.IsMoving and f:IsMovable()) then
|
|
f:StartMoving()
|
|
f.IsMoving = true
|
|
end
|
|
elseif (button == "RightButton") then
|
|
if (not f.IsMoving and container.IsContainer) then
|
|
if (self.IsFrontPage) then
|
|
if (container.CanCloseWithRightClick) then
|
|
if (f.CloseFunction) then
|
|
f:CloseFunction()
|
|
else
|
|
f:Hide()
|
|
end
|
|
end
|
|
else
|
|
--goes back to front page
|
|
DF.TabContainerFunctions.SelectIndex (self, _, 1)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
DF.TabContainerFunctions.OnMouseUp = function (self, button)
|
|
local f = DF:FindHighestParent (self)
|
|
if (f.IsMoving) then
|
|
f:StopMovingOrSizing()
|
|
f.IsMoving = false
|
|
end
|
|
end
|
|
|
|
DF.TabContainerFunctions.SelectIndex = function (self, fixedParam, menuIndex)
|
|
local mainFrame = self.AllFrames and self or self.mainFrame or self:GetParent()
|
|
|
|
for i = 1, #mainFrame.AllFrames do
|
|
mainFrame.AllFrames[i]:Hide()
|
|
if (mainFrame.ButtonNotSelectedBorderColor) then
|
|
mainFrame.AllButtons[i]:SetBackdropBorderColor (unpack (mainFrame.ButtonNotSelectedBorderColor))
|
|
end
|
|
if (mainFrame.AllButtons[i].selectedUnderlineGlow) then
|
|
mainFrame.AllButtons[i].selectedUnderlineGlow:Hide()
|
|
end
|
|
end
|
|
|
|
mainFrame.AllFrames[menuIndex]:Show()
|
|
if mainFrame.AllFrames[menuIndex].RefreshOptions then
|
|
mainFrame.AllFrames[menuIndex]:RefreshOptions()
|
|
end
|
|
if (mainFrame.ButtonSelectedBorderColor) then
|
|
mainFrame.AllButtons[menuIndex]:SetBackdropBorderColor (unpack (mainFrame.ButtonSelectedBorderColor))
|
|
end
|
|
if (mainFrame.AllButtons[menuIndex].selectedUnderlineGlow) then
|
|
mainFrame.AllButtons[menuIndex].selectedUnderlineGlow:Show()
|
|
end
|
|
mainFrame.CurrentIndex = menuIndex
|
|
end
|
|
|
|
DF.TabContainerFunctions.SetIndex = function (self, index)
|
|
self.CurrentIndex = index
|
|
end
|
|
|
|
local tab_container_on_show = function (self)
|
|
local index = self.CurrentIndex
|
|
self.SelectIndex (self.AllButtons[index], nil, index)
|
|
end
|
|
|
|
function DF:CreateTabContainer (parent, title, frame_name, frame_list, options_table)
|
|
|
|
local options_text_template = DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")
|
|
local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
|
|
local options_switch_template = DF:GetTemplate ("switch", "OPTIONS_CHECKBOX_TEMPLATE")
|
|
local options_slider_template = DF:GetTemplate ("slider", "OPTIONS_SLIDER_TEMPLATE")
|
|
local options_button_template = DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE")
|
|
|
|
options_table = options_table or {}
|
|
local frame_width = parent:GetWidth()
|
|
local frame_height = parent:GetHeight()
|
|
local y_offset = options_table.y_offset or 0
|
|
local button_width = options_table.button_width or 160
|
|
local button_height = options_table.button_height or 20
|
|
local button_anchor_x = options_table.button_x or 230
|
|
local button_anchor_y = options_table.button_y or -32
|
|
local button_text_size = options_table.button_text_size or 10
|
|
|
|
local mainFrame = CreateFrame ("frame", frame_name, parent.widget or parent, "BackdropTemplate")
|
|
mainFrame:SetAllPoints()
|
|
DF:Mixin (mainFrame, DF.TabContainerFunctions)
|
|
|
|
local mainTitle = DF:CreateLabel (mainFrame, title, 24, "white")
|
|
mainTitle:SetPoint ("topleft", mainFrame, "topleft", 10, -30 + y_offset)
|
|
|
|
mainFrame:SetFrameLevel (200)
|
|
|
|
mainFrame.AllFrames = {}
|
|
mainFrame.AllButtons = {}
|
|
mainFrame.CurrentIndex = 1
|
|
mainFrame.IsContainer = true
|
|
mainFrame.ButtonSelectedBorderColor = options_table.button_selected_border_color or {1, 1, 0, 1}
|
|
mainFrame.ButtonNotSelectedBorderColor = options_table.button_border_color or {0, 0, 0, 0}
|
|
|
|
if (options_table.right_click_interact ~= nil) then
|
|
mainFrame.CanCloseWithRightClick = options_table.right_click_interact
|
|
else
|
|
mainFrame.CanCloseWithRightClick = true
|
|
end
|
|
|
|
for i, frame in ipairs (frame_list) do
|
|
local f = CreateFrame ("frame", "$parent" .. frame.name, mainFrame, "BackdropTemplate")
|
|
f:SetAllPoints()
|
|
f:SetFrameLevel (210)
|
|
f:Hide()
|
|
|
|
local title = DF:CreateLabel (f, frame.title, 16, "silver")
|
|
title:SetPoint ("topleft", mainTitle, "bottomleft", 0, 0)
|
|
|
|
local tabButton = DF:CreateButton (mainFrame, DF.TabContainerFunctions.SelectIndex, button_width, button_height, frame.title, i, nil, nil, nil, nil, false, button_tab_template)
|
|
PixelUtil.SetSize (tabButton, button_width, button_height)
|
|
tabButton:SetFrameLevel (220)
|
|
tabButton.textsize = button_text_size
|
|
tabButton.mainFrame = mainFrame
|
|
DF.TabContainerFunctions.CreateUnderlineGlow (tabButton)
|
|
|
|
local right_click_to_back
|
|
if (i == 1 or options_table.rightbutton_always_close) then
|
|
right_click_to_back = DF:CreateLabel (f, "right click to close", 10, "gray")
|
|
right_click_to_back:SetPoint ("bottomright", f, "bottomright", -1, options_table.right_click_y or 0)
|
|
if (options_table.close_text_alpha) then
|
|
right_click_to_back:SetAlpha (options_table.close_text_alpha)
|
|
end
|
|
f.IsFrontPage = true
|
|
else
|
|
right_click_to_back = DF:CreateLabel (f, "right click to go back to main menu", 10, "gray")
|
|
right_click_to_back:SetPoint ("bottomright", f, "bottomright", -1, options_table.right_click_y or 0)
|
|
if (options_table.close_text_alpha) then
|
|
right_click_to_back:SetAlpha (options_table.close_text_alpha)
|
|
end
|
|
end
|
|
|
|
if (options_table.hide_click_label) then
|
|
right_click_to_back:Hide()
|
|
end
|
|
|
|
f:SetScript ("OnMouseDown", DF.TabContainerFunctions.OnMouseDown)
|
|
f:SetScript ("OnMouseUp", DF.TabContainerFunctions.OnMouseUp)
|
|
|
|
tinsert (mainFrame.AllFrames, f)
|
|
tinsert (mainFrame.AllButtons, tabButton)
|
|
end
|
|
|
|
--order buttons
|
|
local x = button_anchor_x
|
|
local y = button_anchor_y
|
|
local space_for_buttons = frame_width - (#frame_list*3) - button_anchor_x
|
|
local amount_buttons_per_row = floor (space_for_buttons / button_width)
|
|
local last_button = mainFrame.AllButtons[1]
|
|
|
|
mainFrame.AllButtons[1]:SetPoint ("topleft", mainTitle, "topleft", x, y)
|
|
x = x + button_width + 2
|
|
|
|
for i = 2, #mainFrame.AllButtons do
|
|
local button = mainFrame.AllButtons [i]
|
|
PixelUtil.SetPoint (button, "topleft", mainTitle, "topleft", x, y)
|
|
x = x + button_width + 2
|
|
|
|
if (i % amount_buttons_per_row == 0) then
|
|
x = button_anchor_x
|
|
y = y - button_height - 1
|
|
end
|
|
end
|
|
|
|
--> when show the frame, reset to the current internal index
|
|
mainFrame:SetScript ("OnShow", tab_container_on_show)
|
|
--> select the first frame
|
|
mainFrame.SelectIndex (mainFrame.AllButtons[1], nil, 1)
|
|
|
|
return mainFrame
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~listbox
|
|
|
|
local simple_list_box_ResetWidgets = function (self)
|
|
for _, widget in ipairs (self.widgets) do
|
|
widget:Hide()
|
|
end
|
|
self.nextWidget = 1
|
|
end
|
|
|
|
local simple_list_box_onenter = function (self, capsule)
|
|
self:GetParent().options.onenter (self, capsule, capsule.value)
|
|
end
|
|
|
|
local simple_list_box_onleave = function (self, capsule)
|
|
self:GetParent().options.onleave (self, capsule, capsule.value)
|
|
GameTooltip:Hide()
|
|
end
|
|
|
|
local simple_list_box_GetOrCreateWidget = function (self)
|
|
local index = self.nextWidget
|
|
local widget = self.widgets [index]
|
|
if (not widget) then
|
|
widget = DF:CreateButton (self, function()end, self.options.width, self.options.row_height, "", nil, nil, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"))
|
|
widget:SetHook ("OnEnter", simple_list_box_onenter)
|
|
widget:SetHook ("OnLeave", simple_list_box_onleave)
|
|
widget.textcolor = self.options.textcolor
|
|
widget.textsize = self.options.text_size
|
|
widget.onleave_backdrop = self.options.backdrop_color
|
|
|
|
widget.XButton = DF:CreateButton (widget, function()end, 16, 16)
|
|
widget.XButton:SetPoint ("topright", widget.widget, "topright")
|
|
widget.XButton:SetIcon ([[Interface\BUTTONS\UI-Panel-MinimizeButton-Up]], 16, 16, "overlay", nil, nil, 0, -4, 0, false)
|
|
widget.XButton.icon:SetDesaturated (true)
|
|
|
|
if (not self.options.show_x_button) then
|
|
widget.XButton:Hide()
|
|
end
|
|
|
|
tinsert (self.widgets, widget)
|
|
end
|
|
self.nextWidget = self.nextWidget + 1
|
|
return widget
|
|
end
|
|
|
|
local simple_list_box_RefreshWidgets = function (self)
|
|
self:ResetWidgets()
|
|
local amt = 0
|
|
for value, _ in pairs (self.list_table) do
|
|
local widget = self:GetOrCreateWidget()
|
|
widget:SetPoint ("topleft", self, "topleft", 1, -self.options.row_height * (self.nextWidget-2) - 4)
|
|
widget:SetPoint ("topright", self, "topright", -1, -self.options.row_height * (self.nextWidget-2) - 4)
|
|
|
|
widget:SetClickFunction (self.func, value)
|
|
|
|
if (self.options.show_x_button) then
|
|
widget.XButton:SetClickFunction (self.options.x_button_func, value)
|
|
widget.XButton.value = value
|
|
widget.XButton:Show()
|
|
else
|
|
widget.XButton:Hide()
|
|
end
|
|
|
|
widget.value = value
|
|
|
|
if (self.options.icon) then
|
|
if (type (self.options.icon) == "string" or type (self.options.icon) == "number") then
|
|
local coords = type (self.options.iconcoords) == "table" and self.options.iconcoords or {0, 1, 0, 1}
|
|
widget:SetIcon (self.options.icon, self.options.row_height - 2, self.options.row_height - 2, "overlay", coords)
|
|
|
|
elseif (type (self.options.icon) == "function") then
|
|
local icon = self.options.icon (value)
|
|
if (icon) then
|
|
local coords = type (self.options.iconcoords) == "table" and self.options.iconcoords or {0, 1, 0, 1}
|
|
widget:SetIcon (icon, self.options.row_height - 2, self.options.row_height - 2, "overlay", coords)
|
|
end
|
|
end
|
|
else
|
|
widget:SetIcon ("", self.options.row_height, self.options.row_height)
|
|
end
|
|
|
|
if (self.options.text) then
|
|
if (type (self.options.text) == "function") then
|
|
local text = self.options.text (value)
|
|
if (text) then
|
|
widget:SetText (text)
|
|
else
|
|
widget:SetText ("")
|
|
end
|
|
else
|
|
widget:SetText (self.options.text or "")
|
|
end
|
|
else
|
|
widget:SetText ("")
|
|
end
|
|
|
|
widget.value = value
|
|
|
|
local r, g, b, a = DF:ParseColors (self.options.backdrop_color)
|
|
widget:SetBackdropColor (r, g, b, a)
|
|
|
|
widget:Show()
|
|
amt = amt + 1
|
|
end
|
|
if (amt == 0) then
|
|
self.EmptyLabel:Show()
|
|
else
|
|
self.EmptyLabel:Hide()
|
|
end
|
|
end
|
|
|
|
local backdrop = {bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1}
|
|
local default_options = {
|
|
height = 400,
|
|
row_height = 16,
|
|
width = 230,
|
|
icon = false,
|
|
text = "",
|
|
text_size = 10,
|
|
textcolor = "wheat",
|
|
|
|
backdrop_color = {1, 1, 1, .5},
|
|
panel_border_color = {0, 0, 0, 0.5},
|
|
|
|
onenter = function (self, capsule)
|
|
if (capsule) then
|
|
capsule.textcolor = "white"
|
|
end
|
|
end,
|
|
onleave = function (self, capsule)
|
|
if (capsule) then
|
|
capsule.textcolor = self:GetParent().options.textcolor
|
|
end
|
|
GameTooltip:Hide()
|
|
end,
|
|
}
|
|
|
|
local simple_list_box_SetData = function (self, t)
|
|
self.list_table = t
|
|
end
|
|
|
|
function DF:CreateSimpleListBox (parent, name, title, empty_text, list_table, onclick, options)
|
|
local f = CreateFrame ("frame", name, parent, "BackdropTemplate")
|
|
|
|
f.ResetWidgets = simple_list_box_ResetWidgets
|
|
f.GetOrCreateWidget = simple_list_box_GetOrCreateWidget
|
|
f.Refresh = simple_list_box_RefreshWidgets
|
|
f.SetData = simple_list_box_SetData
|
|
f.nextWidget = 1
|
|
f.list_table = list_table
|
|
f.func = function (self, button, value)
|
|
--onclick (value)
|
|
DF:QuickDispatch (onclick, value)
|
|
f:Refresh()
|
|
end
|
|
f.widgets = {}
|
|
|
|
DF:ApplyStandardBackdrop (f)
|
|
|
|
f.options = options or {}
|
|
self.table.deploy (f.options, default_options)
|
|
|
|
if (f.options.x_button_func) then
|
|
local original_X_function = f.options.x_button_func
|
|
f.options.x_button_func = function (self, button, value)
|
|
DF:QuickDispatch (original_X_function, value)
|
|
f:Refresh()
|
|
end
|
|
end
|
|
|
|
f:SetBackdropBorderColor (unpack (f.options.panel_border_color))
|
|
|
|
f:SetSize (f.options.width + 2, f.options.height)
|
|
|
|
local name = DF:CreateLabel (f, title, 12, "silver")
|
|
name:SetTemplate (DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE"))
|
|
name:SetPoint ("bottomleft", f, "topleft", 0, 2)
|
|
f.Title = name
|
|
|
|
local emptyLabel = DF:CreateLabel (f, empty_text, 12, "gray")
|
|
emptyLabel:SetAlpha (.6)
|
|
emptyLabel:SetSize (f.options.width-10, f.options.height)
|
|
emptyLabel:SetPoint ("center", 0, 0)
|
|
emptyLabel:Hide()
|
|
emptyLabel.align = "center"
|
|
f.EmptyLabel = emptyLabel
|
|
|
|
return f
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~scrollbox
|
|
|
|
DF.SortFunctions = {}
|
|
|
|
local SortMember = ""
|
|
local SortByMember = function (t1, t2)
|
|
return t1[SortMember] > t2[SortMember]
|
|
end
|
|
local SortByMemberReverse = function (t1, t2)
|
|
return t1[SortMember] < t2[SortMember]
|
|
end
|
|
|
|
DF.SortFunctions.Sort = function (self, t, by, is_reverse)
|
|
SortMember = by
|
|
if (not is_reverse) then
|
|
table.sort (t, SortByMember)
|
|
else
|
|
table.sort (t, SortByMemberReverse)
|
|
end
|
|
end
|
|
|
|
|
|
DF.ScrollBoxFunctions = {}
|
|
|
|
DF.ScrollBoxFunctions.Refresh = function (self)
|
|
for _, frame in ipairs (self.Frames) do
|
|
frame:Hide()
|
|
frame._InUse = nil
|
|
end
|
|
|
|
local offset = 0
|
|
if (self.IsFauxScroll) then
|
|
FauxScrollFrame_Update (self, #self.data, self.LineAmount, self.LineHeight)
|
|
offset = FauxScrollFrame_GetOffset (self)
|
|
end
|
|
|
|
DF:CoreDispatch ((self:GetName() or "ScrollBox") .. ":Refresh()", self.refresh_func, self, self.data, offset, self.LineAmount)
|
|
|
|
for _, frame in ipairs (self.Frames) do
|
|
if (not frame._InUse) then
|
|
frame:Hide()
|
|
else
|
|
frame:Show()
|
|
end
|
|
end
|
|
|
|
self:Show()
|
|
|
|
if (self.HideScrollBar) then
|
|
local frameName = self:GetName()
|
|
if (frameName) then
|
|
local scrollBar = _G [frameName .. "ScrollBar"]
|
|
if (scrollBar) then
|
|
scrollBar:Hide()
|
|
end
|
|
else
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return self.Frames
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.OnVerticalScroll = function (self, offset)
|
|
FauxScrollFrame_OnVerticalScroll (self, offset, self.LineHeight, self.Refresh)
|
|
return true
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.CreateLine = function (self, func)
|
|
if (not func) then
|
|
func = self.CreateLineFunc
|
|
end
|
|
local okay, newLine = pcall (func, self, #self.Frames+1)
|
|
if (okay) then
|
|
tinsert (self.Frames, newLine)
|
|
newLine.Index = #self.Frames
|
|
return newLine
|
|
else
|
|
error ("Details! FrameWork: CreateLine(): " .. newLine)
|
|
end
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.GetLine = function (self, line_index)
|
|
local line = self.Frames [line_index]
|
|
if (line) then
|
|
line._InUse = true
|
|
end
|
|
return line
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.SetData = function (self, data)
|
|
self.data = data
|
|
end
|
|
DF.ScrollBoxFunctions.GetData = function (self)
|
|
return self.data
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.GetFrames = function (self)
|
|
return self.Frames
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.GetNumFramesCreated = function (self)
|
|
return #self.Frames
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.GetNumFramesShown = function (self)
|
|
return self.LineAmount
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.SetNumFramesShown = function (self, new_amount)
|
|
--> hide frames which won't be used
|
|
if (new_amount < #self.Frames) then
|
|
for i = new_amount+1, #self.Frames do
|
|
self.Frames [i]:Hide()
|
|
end
|
|
end
|
|
|
|
--> set the new amount
|
|
self.LineAmount = new_amount
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.SetFramesHeight = function (self, new_height)
|
|
self.LineHeight = new_height
|
|
self:OnSizeChanged()
|
|
self:Refresh()
|
|
end
|
|
|
|
DF.ScrollBoxFunctions.OnSizeChanged = function (self)
|
|
if (self.ReajustNumFrames) then
|
|
--> how many lines the scroll can show
|
|
local amountOfFramesToShow = floor (self:GetHeight() / self.LineHeight)
|
|
|
|
--> how many lines the scroll already have
|
|
local totalFramesCreated = self:GetNumFramesCreated()
|
|
|
|
--> how many lines are current shown
|
|
local totalFramesShown = self:GetNumFramesShown()
|
|
|
|
--> the amount of frames increased
|
|
if (amountOfFramesToShow > totalFramesShown) then
|
|
for i = totalFramesShown+1, amountOfFramesToShow do
|
|
--> check if need to create a new line
|
|
if (i > totalFramesCreated) then
|
|
self:CreateLine (self.CreateLineFunc)
|
|
end
|
|
end
|
|
|
|
--> the amount of frames decreased
|
|
elseif (amountOfFramesToShow < totalFramesShown) then
|
|
--> hide all frames above the new amount to show
|
|
for i = totalFramesCreated, amountOfFramesToShow, -1 do
|
|
if (self.Frames [i]) then
|
|
self.Frames [i]:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
--> set the new amount of frames
|
|
self:SetNumFramesShown (amountOfFramesToShow)
|
|
|
|
--> refresh lines
|
|
self:Refresh()
|
|
end
|
|
end
|
|
|
|
function DF:CreateScrollBox (parent, name, refresh_func, data, width, height, line_amount, line_height, create_line_func, auto_amount, no_scroll)
|
|
local scroll = CreateFrame ("scrollframe", name, parent, "FauxScrollFrameTemplate,BackdropTemplate")
|
|
|
|
DF:ApplyStandardBackdrop (scroll)
|
|
|
|
scroll:SetSize (width, height)
|
|
scroll.LineAmount = line_amount
|
|
scroll.LineHeight = line_height
|
|
scroll.IsFauxScroll = true
|
|
scroll.HideScrollBar = no_scroll
|
|
scroll.Frames = {}
|
|
scroll.ReajustNumFrames = auto_amount
|
|
scroll.CreateLineFunc = create_line_func
|
|
|
|
DF:Mixin (scroll, DF.SortFunctions)
|
|
DF:Mixin (scroll, DF.ScrollBoxFunctions)
|
|
|
|
scroll.refresh_func = refresh_func
|
|
scroll.data = data
|
|
|
|
scroll:SetScript ("OnVerticalScroll", scroll.OnVerticalScroll)
|
|
scroll:SetScript ("OnSizeChanged", DF.ScrollBoxFunctions.OnSizeChanged)
|
|
|
|
return scroll
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~resizers
|
|
|
|
function DF:CreateResizeGrips (parent)
|
|
if (parent) then
|
|
local parentName = parent:GetName()
|
|
|
|
local leftResizer = CreateFrame ("button", parentName and parentName .. "LeftResizer" or nil, parent, "BackdropTemplate")
|
|
local rightResizer = CreateFrame ("button", parentName and parentName .. "RightResizer" or nil, parent, "BackdropTemplate")
|
|
|
|
leftResizer:SetPoint ("bottomleft", parent, "bottomleft")
|
|
rightResizer:SetPoint ("bottomright", parent, "bottomright")
|
|
leftResizer:SetSize (16, 16)
|
|
rightResizer:SetSize (16, 16)
|
|
|
|
rightResizer:SetNormalTexture ([[Interface\CHATFRAME\UI-ChatIM-SizeGrabber-Up]])
|
|
rightResizer:SetHighlightTexture ([[Interface\CHATFRAME\UI-ChatIM-SizeGrabber-Highlight]])
|
|
rightResizer:SetPushedTexture ([[Interface\CHATFRAME\UI-ChatIM-SizeGrabber-Down]])
|
|
leftResizer:SetNormalTexture ([[Interface\CHATFRAME\UI-ChatIM-SizeGrabber-Up]])
|
|
leftResizer:SetHighlightTexture ([[Interface\CHATFRAME\UI-ChatIM-SizeGrabber-Highlight]])
|
|
leftResizer:SetPushedTexture ([[Interface\CHATFRAME\UI-ChatIM-SizeGrabber-Down]])
|
|
|
|
leftResizer:GetNormalTexture():SetTexCoord (1, 0, 0, 1)
|
|
leftResizer:GetHighlightTexture():SetTexCoord (1, 0, 0, 1)
|
|
leftResizer:GetPushedTexture():SetTexCoord (1, 0, 0, 1)
|
|
|
|
return leftResizer, rightResizer
|
|
end
|
|
end
|
|
|
|
|
|
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~keybind
|
|
|
|
|
|
--------------------------------
|
|
--> keybind frame ~key
|
|
|
|
|
|
local ignoredKeys = {
|
|
["LSHIFT"] = true,
|
|
["RSHIFT"] = true,
|
|
["LCTRL"] = true,
|
|
["RCTRL"] = true,
|
|
["LALT"] = true,
|
|
["RALT"] = true,
|
|
["UNKNOWN"] = true,
|
|
}
|
|
|
|
local mouseKeys = {
|
|
["LeftButton"] = "type1",
|
|
["RightButton"] = "type2",
|
|
["MiddleButton"] = "type3",
|
|
["Button4"] = "type4",
|
|
["Button5"] = "type5",
|
|
["Button6"] = "type6",
|
|
["Button7"] = "type7",
|
|
["Button8"] = "type8",
|
|
["Button9"] = "type9",
|
|
["Button10"] = "type10",
|
|
["Button11"] = "type11",
|
|
["Button12"] = "type12",
|
|
["Button13"] = "type13",
|
|
["Button14"] = "type14",
|
|
["Button15"] = "type15",
|
|
["Button16"] = "type16",
|
|
}
|
|
|
|
local keysToMouse = {
|
|
["type1"] = "LeftButton",
|
|
["type2"] = "RightButton",
|
|
["type3"] = "MiddleButton",
|
|
["type4"] = "Button4",
|
|
["type5"] = "Button5",
|
|
["type6"] = "Button6",
|
|
["type7"] = "Button7",
|
|
["type8"] = "Button8",
|
|
["type9"] = "Button9",
|
|
["type10"] = "Button10",
|
|
["type11"] = "Button11",
|
|
["type12"] = "Button12",
|
|
["type13"] = "Button13",
|
|
["type14"] = "Button14",
|
|
["type15"] = "Button15",
|
|
["type16"] = "Button16",
|
|
}
|
|
|
|
local keybind_set_data = function (self, new_data_table)
|
|
self.Data = new_data_table
|
|
self.keybindScroll:UpdateScroll()
|
|
end
|
|
|
|
function DF:CreateKeybindBox (parent, name, data, callback, width, height, line_amount, line_height)
|
|
|
|
local options_text_template = DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")
|
|
local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
|
|
local options_switch_template = DF:GetTemplate ("switch", "OPTIONS_CHECKBOX_TEMPLATE")
|
|
local options_slider_template = DF:GetTemplate ("slider", "OPTIONS_SLIDER_TEMPLATE")
|
|
local options_button_template = DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE")
|
|
|
|
local SCROLL_ROLL_AMOUNT = line_amount
|
|
|
|
--keybind set frame
|
|
local new_keybind_frame = CreateFrame ("frame", name, parent, "BackdropTemplate")
|
|
new_keybind_frame:SetSize (width, height)
|
|
|
|
-- keybind scrollframe
|
|
local keybindScroll = CreateFrame ("scrollframe", "$parentScrollFrame", new_keybind_frame, "FauxScrollFrameTemplate, BackdropTemplate")
|
|
keybindScroll:SetSize (1019, 348)
|
|
keybindScroll.Frames = {}
|
|
new_keybind_frame.keybindScroll = keybindScroll
|
|
|
|
--waiting the player to press a key
|
|
new_keybind_frame.IsListening = false
|
|
|
|
--check for valid data table
|
|
if (type (data) ~= "table") then
|
|
print ("error: data must be a table. DF > CreateKeybindBox()")
|
|
return
|
|
end
|
|
|
|
if (not next (data)) then
|
|
--> build data table for the character class
|
|
local _, unitClass = UnitClass ("player")
|
|
if (unitClass) then
|
|
local specIds = DF:GetClassSpecIDs (unitClass)
|
|
if (specIds) then
|
|
for _, specId in ipairs (specIds) do
|
|
data [specId] = {}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
new_keybind_frame.Data = data
|
|
new_keybind_frame.SetData = keybind_set_data
|
|
|
|
new_keybind_frame.EditingSpec = DF:GetCurrentSpec()
|
|
new_keybind_frame.CurrentKeybindEditingSet = new_keybind_frame.Data [new_keybind_frame.EditingSpec]
|
|
|
|
local allSpecButtons = {}
|
|
local switch_spec = function (self, button, specID)
|
|
new_keybind_frame.EditingSpec = specID
|
|
new_keybind_frame.CurrentKeybindEditingSet = new_keybind_frame.Data [specID]
|
|
|
|
for _, button in ipairs (allSpecButtons) do
|
|
button.selectedTexture:Hide()
|
|
end
|
|
self.MyObject.selectedTexture:Show()
|
|
|
|
--feedback ao jogador uma vez que as keybinds podem ter o mesmo valor
|
|
C_Timer.After (.04, function() new_keybind_frame:Hide() end)
|
|
C_Timer.After (.06, function() new_keybind_frame:Show() end)
|
|
|
|
--atualiza a scroll
|
|
keybindScroll:UpdateScroll()
|
|
end
|
|
|
|
--choose which spec to use
|
|
local spec1 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec1 Placeholder Text", 1, _, _, "SpecButton1", _, 0, options_button_template, options_text_template)
|
|
local spec2 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec2 Placeholder Text", 1, _, _, "SpecButton2", _, 0, options_button_template, options_text_template)
|
|
local spec3 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec3 Placeholder Text", 1, _, _, "SpecButton3", _, 0, options_button_template, options_text_template)
|
|
local spec4 = DF:CreateButton (new_keybind_frame, switch_spec, 160, 20, "Spec4 Placeholder Text", 1, _, _, "SpecButton4", _, 0, options_button_template, options_text_template)
|
|
|
|
--format the button label and icon with the spec information
|
|
local className, class = UnitClass ("player")
|
|
local i = 1
|
|
local specIds = DF:GetClassSpecIDs (class)
|
|
|
|
for index, specId in ipairs (specIds) do
|
|
local button = new_keybind_frame ["SpecButton" .. index]
|
|
local spec_id, spec_name, spec_description, spec_icon, spec_background, spec_role, spec_class = DetailsFramework.GetSpecializationInfoByID (specId)
|
|
button.text = spec_name
|
|
button:SetClickFunction (switch_spec, specId)
|
|
button:SetIcon (spec_icon)
|
|
button.specID = specId
|
|
|
|
local selectedTexture = button:CreateTexture (nil, "background")
|
|
selectedTexture:SetAllPoints()
|
|
selectedTexture:SetColorTexture (1, 1, 1, 0.5)
|
|
if (specId ~= new_keybind_frame.EditingSpec) then
|
|
selectedTexture:Hide()
|
|
end
|
|
button.selectedTexture = selectedTexture
|
|
|
|
tinsert (allSpecButtons, button)
|
|
i = i + 1
|
|
end
|
|
|
|
local specsTitle = DF:CreateLabel (new_keybind_frame, "Config keys for spec:", 12, "silver")
|
|
specsTitle:SetPoint ("topleft", new_keybind_frame, "topleft", 10, mainStartY)
|
|
|
|
keybindScroll:SetPoint ("topleft", specsTitle.widget, "bottomleft", 0, -120)
|
|
|
|
spec1:SetPoint ("topleft", specsTitle, "bottomleft", 0, -10)
|
|
spec2:SetPoint ("topleft", specsTitle, "bottomleft", 0, -30)
|
|
spec3:SetPoint ("topleft", specsTitle, "bottomleft", 0, -50)
|
|
if (class == "DRUID") then
|
|
spec4:SetPoint ("topleft", specsTitle, "bottomleft", 0, -70)
|
|
end
|
|
|
|
local enter_the_key = CreateFrame ("frame", nil, new_keybind_frame, "BackdropTemplate")
|
|
enter_the_key:SetFrameStrata ("tooltip")
|
|
enter_the_key:SetSize (200, 60)
|
|
enter_the_key:SetBackdrop ({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
|
|
enter_the_key:SetBackdropColor (0, 0, 0, 1)
|
|
enter_the_key:SetBackdropBorderColor (1, 1, 1, 1)
|
|
enter_the_key.text = DF:CreateLabel (enter_the_key, "- Press a keyboard key to bind.\n- Click to bind a mouse button.\n- Press escape to cancel.", 11, "orange")
|
|
enter_the_key.text:SetPoint ("center", enter_the_key, "center")
|
|
enter_the_key:Hide()
|
|
|
|
local registerKeybind = function (self, key)
|
|
if (ignoredKeys [key]) then
|
|
return
|
|
end
|
|
if (key == "ESCAPE") then
|
|
enter_the_key:Hide()
|
|
new_keybind_frame.IsListening = false
|
|
new_keybind_frame:SetScript ("OnKeyDown", nil)
|
|
return
|
|
end
|
|
|
|
local bind = (IsShiftKeyDown() and "SHIFT-" or "") .. (IsControlKeyDown() and "CTRL-" or "") .. (IsAltKeyDown() and "ALT-" or "")
|
|
bind = bind .. key
|
|
|
|
--adiciona para a tabela de keybinds
|
|
local keybind = new_keybind_frame.CurrentKeybindEditingSet [self.keybindIndex]
|
|
keybind.key = bind
|
|
|
|
new_keybind_frame.IsListening = false
|
|
new_keybind_frame:SetScript ("OnKeyDown", nil)
|
|
|
|
enter_the_key:Hide()
|
|
new_keybind_frame.keybindScroll:UpdateScroll()
|
|
|
|
DF:QuickDispatch (callback)
|
|
end
|
|
|
|
local set_keybind_key = function (self, button, keybindIndex)
|
|
if (new_keybind_frame.IsListening) then
|
|
key = mouseKeys [button] or button
|
|
return registerKeybind (new_keybind_frame, key)
|
|
end
|
|
new_keybind_frame.IsListening = true
|
|
new_keybind_frame.keybindIndex = keybindIndex
|
|
new_keybind_frame:SetScript ("OnKeyDown", registerKeybind)
|
|
|
|
enter_the_key:Show()
|
|
enter_the_key:SetPoint ("bottom", self, "top")
|
|
end
|
|
|
|
local new_key_bind = function (self, button, specID)
|
|
tinsert (new_keybind_frame.CurrentKeybindEditingSet, {key = "-none-", action = "_target", actiontext = ""})
|
|
FauxScrollFrame_SetOffset (new_keybind_frame.keybindScroll, max (#new_keybind_frame.CurrentKeybindEditingSet-SCROLL_ROLL_AMOUNT, 0))
|
|
new_keybind_frame.keybindScroll:UpdateScroll()
|
|
end
|
|
|
|
local set_action_text = function (keybindIndex, _, text)
|
|
local keybind = new_keybind_frame.CurrentKeybindEditingSet [keybindIndex]
|
|
keybind.actiontext = text
|
|
DF:QuickDispatch (callback)
|
|
end
|
|
|
|
local set_action_on_espace_press = function (textentry, capsule)
|
|
capsule = capsule or textentry.MyObject
|
|
local keybind = new_keybind_frame.CurrentKeybindEditingSet [capsule.CurIndex]
|
|
textentry:SetText (keybind.actiontext)
|
|
DF:QuickDispatch (callback)
|
|
end
|
|
|
|
local lock_textentry = {
|
|
["_target"] = true,
|
|
["_taunt"] = true,
|
|
["_interrupt"] = true,
|
|
["_dispel"] = true,
|
|
["_spell"] = false,
|
|
["_macro"] = false,
|
|
}
|
|
|
|
local change_key_action = function (self, keybindIndex, value)
|
|
local keybind = new_keybind_frame.CurrentKeybindEditingSet [keybindIndex]
|
|
keybind.action = value
|
|
new_keybind_frame.keybindScroll:UpdateScroll()
|
|
DF:QuickDispatch (callback)
|
|
end
|
|
local fill_action_dropdown = function()
|
|
|
|
local locClass, class = UnitClass ("player")
|
|
|
|
local taunt = ""
|
|
local interrupt = ""
|
|
local dispel = ""
|
|
|
|
if (type (dispel) == "table") then
|
|
local dispelString = "\n"
|
|
for specID, spellid in pairs (dispel) do
|
|
local specid, specName = DetailsFramework.GetSpecializationInfoByID (specID)
|
|
local spellName = GetSpellInfo (spellid)
|
|
dispelString = dispelString .. "|cFFE5E5E5" .. (specName or "") .. "|r: |cFFFFFFFF" .. spellName .. "\n"
|
|
end
|
|
dispel = dispelString
|
|
else
|
|
dispel = ""
|
|
end
|
|
|
|
return {
|
|
--{value = "_target", label = "Target", onclick = change_key_action, desc = "Target the unit"},
|
|
--{value = "_taunt", label = "Taunt", onclick = change_key_action, desc = "Cast the taunt spell for your class\n\n|cFFFFFFFFSpell: " .. taunt},
|
|
--{value = "_interrupt", label = "Interrupt", onclick = change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. interrupt},
|
|
--{value = "_dispel", label = "Dispel", onclick = change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. dispel},
|
|
{value = "_spell", label = "Cast Spell", onclick = change_key_action, desc = "Type the spell name in the text box"},
|
|
{value = "_macro", label = "Run Macro", onclick = change_key_action, desc = "Type your macro in the text box"},
|
|
}
|
|
end
|
|
|
|
local copy_keybind = function (self, button, keybindIndex)
|
|
local keybind = new_keybind_frame.CurrentKeybindEditingSet [keybindIndex]
|
|
for specID, t in pairs (new_keybind_frame.Data) do
|
|
if (specID ~= new_keybind_frame.EditingSpec) then
|
|
local key = CopyTable (keybind)
|
|
local specid, specName = DetailsFramework.GetSpecializationInfoByID (specID)
|
|
tinsert (new_keybind_frame.Data [specID], key)
|
|
DF:Msg ("Keybind copied to " .. (specName or ""))
|
|
end
|
|
end
|
|
DF:QuickDispatch (callback)
|
|
end
|
|
|
|
local delete_keybind = function (self, button, keybindIndex)
|
|
tremove (new_keybind_frame.CurrentKeybindEditingSet, keybindIndex)
|
|
new_keybind_frame.keybindScroll:UpdateScroll()
|
|
DF:QuickDispatch (callback)
|
|
end
|
|
|
|
local newTitle = DF:CreateLabel (new_keybind_frame, "Create a new Keybind:", 12, "silver")
|
|
newTitle:SetPoint ("topleft", new_keybind_frame, "topleft", 200, mainStartY)
|
|
local createNewKeybind = DF:CreateButton (new_keybind_frame, new_key_bind, 160, 20, "New Key Bind", 1, _, _, "NewKeybindButton", _, 0, options_button_template, options_text_template)
|
|
createNewKeybind:SetPoint ("topleft", newTitle, "bottomleft", 0, -10)
|
|
--createNewKeybind:SetIcon ([[Interface\Buttons\UI-GuildButton-PublicNote-Up]])
|
|
|
|
local update_keybind_list = function (self)
|
|
|
|
local keybinds = new_keybind_frame.CurrentKeybindEditingSet
|
|
FauxScrollFrame_Update (self, #keybinds, SCROLL_ROLL_AMOUNT, 21)
|
|
local offset = FauxScrollFrame_GetOffset (self)
|
|
|
|
for i = 1, SCROLL_ROLL_AMOUNT do
|
|
local index = i + offset
|
|
local f = self.Frames [i]
|
|
local data = keybinds [index]
|
|
|
|
if (data) then
|
|
--index
|
|
f.Index.text = index
|
|
--keybind
|
|
local keyBindText = keysToMouse [data.key] or data.key
|
|
|
|
keyBindText = keyBindText:gsub ("type1", "LeftButton")
|
|
keyBindText = keyBindText:gsub ("type2", "RightButton")
|
|
keyBindText = keyBindText:gsub ("type3", "MiddleButton")
|
|
|
|
f.KeyBind.text = keyBindText
|
|
f.KeyBind:SetClickFunction (set_keybind_key, index, nil, "left")
|
|
f.KeyBind:SetClickFunction (set_keybind_key, index, nil, "right")
|
|
--action
|
|
f.ActionDrop:SetFixedParameter (index)
|
|
f.ActionDrop:Select (data.action)
|
|
--action text
|
|
f.ActionText.text = data.actiontext
|
|
f.ActionText:SetEnterFunction (set_action_text, index)
|
|
f.ActionText.CurIndex = index
|
|
|
|
if (lock_textentry [data.action]) then
|
|
f.ActionText:Disable()
|
|
else
|
|
f.ActionText:Enable()
|
|
end
|
|
|
|
--copy
|
|
f.Copy:SetClickFunction (copy_keybind, index)
|
|
--delete
|
|
f.Delete:SetClickFunction (delete_keybind, index)
|
|
|
|
f:Show()
|
|
else
|
|
f:Hide()
|
|
end
|
|
end
|
|
|
|
self:Show()
|
|
end
|
|
|
|
|
|
|
|
keybindScroll:SetScript ("OnVerticalScroll", function (self, offset)
|
|
FauxScrollFrame_OnVerticalScroll (self, offset, 21, update_keybind_list)
|
|
end)
|
|
keybindScroll.UpdateScroll = update_keybind_list
|
|
|
|
local backdropColor = {.3, .3, .3, .3}
|
|
local backdropColorOnEnter = {.6, .6, .6, .6}
|
|
local on_enter = function (self)
|
|
self:SetBackdropColor (unpack (backdropColorOnEnter))
|
|
end
|
|
local on_leave = function (self)
|
|
self:SetBackdropColor (unpack (backdropColor))
|
|
end
|
|
|
|
local font = "GameFontHighlightSmall"
|
|
|
|
for i = 1, SCROLL_ROLL_AMOUNT do
|
|
local f = CreateFrame ("frame", "$KeyBindFrame" .. i, keybindScroll, "BackdropTemplate")
|
|
f:SetSize (1009, 20)
|
|
f:SetPoint ("topleft", keybindScroll, "topleft", 0, -(i-1)*29)
|
|
f:SetBackdrop ({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
f:SetBackdropColor (unpack (backdropColor))
|
|
f:SetScript ("OnEnter", on_enter)
|
|
f:SetScript ("OnLeave", on_leave)
|
|
tinsert (keybindScroll.Frames, f)
|
|
|
|
f.Index = DF:CreateLabel (f, "1")
|
|
f.KeyBind = DF:CreateButton (f, set_key_bind, 100, 20, "", _, _, _, "SetNewKeybindButton", _, 0, options_button_template, options_text_template)
|
|
f.ActionDrop = DF:CreateDropDown (f, fill_action_dropdown, 0, 120, 20, "ActionDropdown", _, options_dropdown_template)
|
|
f.ActionText = DF:CreateTextEntry (f, function()end, 660, 20, "TextBox", _, _, options_dropdown_template)
|
|
f.Copy = DF:CreateButton (f, copy_keybind, 20, 20, "", _, _, _, "CopyKeybindButton", _, 0, options_button_template, options_text_template)
|
|
f.Delete = DF:CreateButton (f, delete_keybind, 16, 20, "", _, _, _, "DeleteKeybindButton", _, 2, options_button_template, options_text_template)
|
|
|
|
f.Index:SetPoint ("left", f, "left", 10, 0)
|
|
f.KeyBind:SetPoint ("left", f, "left", 43, 0)
|
|
f.ActionDrop:SetPoint ("left", f, "left", 150, 0)
|
|
f.ActionText:SetPoint ("left", f, "left", 276, 0)
|
|
f.Copy:SetPoint ("left", f, "left", 950, 0)
|
|
f.Delete:SetPoint ("left", f, "left", 990, 0)
|
|
|
|
f.Copy:SetIcon ([[Interface\Buttons\UI-GuildButton-PublicNote-Up]], nil, nil, nil, nil, nil, nil, 4)
|
|
f.Delete:SetIcon ([[Interface\Buttons\UI-StopButton]], nil, nil, nil, nil, nil, nil, 4)
|
|
|
|
f.Copy.tooltip = "copy this keybind to other specs"
|
|
f.Delete.tooltip = "erase this keybind"
|
|
|
|
--editbox
|
|
f.ActionText:SetJustifyH ("left")
|
|
f.ActionText:SetHook ("OnEscapePressed", set_action_on_espace_press)
|
|
f.ActionText:SetHook ("OnEditFocusGained", function()
|
|
local playerSpells = {}
|
|
local tab, tabTex, offset, numSpells = GetSpellTabInfo (2)
|
|
for i = 1, numSpells do
|
|
local index = offset + i
|
|
local spellType, spellId = GetSpellBookItemInfo (index, "player")
|
|
if (spellType == "SPELL") then
|
|
local spellName = GetSpellInfo (spellId)
|
|
tinsert (playerSpells, spellName)
|
|
end
|
|
end
|
|
f.ActionText.WordList = playerSpells
|
|
end)
|
|
|
|
f.ActionText:SetAsAutoComplete ("WordList")
|
|
end
|
|
|
|
local header = CreateFrame ("frame", "$parentOptionsPanelFrameHeader", keybindScroll, "BackdropTemplate")
|
|
header:SetPoint ("bottomleft", keybindScroll, "topleft", 0, 2)
|
|
header:SetPoint ("bottomright", keybindScroll, "topright", 0, 2)
|
|
header:SetHeight (16)
|
|
|
|
header.Index = DF:CreateLabel (header, "Index", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE"))
|
|
header.Key = DF:CreateLabel (header, "Key", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE"))
|
|
header.Action = DF:CreateLabel (header, "Action", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE"))
|
|
header.Macro = DF:CreateLabel (header, "Spell Name / Macro", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE"))
|
|
header.Copy = DF:CreateLabel (header, "Copy", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE"))
|
|
header.Delete = DF:CreateLabel (header, "Delete", DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE"))
|
|
|
|
header.Index:SetPoint ("left", header, "left", 10, 0)
|
|
header.Key:SetPoint ("left", header, "left", 43, 0)
|
|
header.Action:SetPoint ("left", header, "left", 150, 0)
|
|
header.Macro:SetPoint ("left", header, "left", 276, 0)
|
|
header.Copy:SetPoint ("left", header, "left", 950, 0)
|
|
header.Delete:SetPoint ("left", header, "left", 990, 0)
|
|
|
|
new_keybind_frame:SetScript ("OnShow", function()
|
|
|
|
--new_keybind_frame.EditingSpec = EnemyGrid.CurrentSpec
|
|
--new_keybind_frame.CurrentKeybindEditingSet = EnemyGrid.CurrentKeybindSet
|
|
|
|
for _, button in ipairs (allSpecButtons) do
|
|
if (new_keybind_frame.EditingSpec ~= button.specID) then
|
|
button.selectedTexture:Hide()
|
|
else
|
|
button.selectedTexture:Show()
|
|
end
|
|
end
|
|
|
|
keybindScroll:UpdateScroll()
|
|
end)
|
|
|
|
new_keybind_frame:SetScript ("OnHide", function()
|
|
if (new_keybind_frame.IsListening) then
|
|
new_keybind_frame.IsListening = false
|
|
new_keybind_frame:SetScript ("OnKeyDown", nil)
|
|
end
|
|
end)
|
|
|
|
return new_keybind_frame
|
|
end
|
|
|
|
function DF:BuildKeybindFunctions (data, prefix)
|
|
|
|
--~keybind
|
|
local classLoc, class = UnitClass ("player")
|
|
local bindingList = data
|
|
|
|
local bindString = "self:ClearBindings()"
|
|
local bindKeyBindTypeFunc = [[local unitFrame = ...]]
|
|
local bindMacroTextFunc = [[local unitFrame = ...]]
|
|
local isMouseBinding
|
|
|
|
for i = 1, #bindingList do
|
|
local bind = bindingList [i]
|
|
local bindType
|
|
|
|
--which button to press
|
|
if (bind.key:find ("type")) then
|
|
local keyNumber = tonumber (bind.key:match ("%d"))
|
|
bindType = keyNumber
|
|
isMouseBinding = true
|
|
else
|
|
bindType = prefix .. "" .. i
|
|
bindString = bindString .. "self:SetBindingClick (0, '" .. bind.key .. "', self:GetName(), '" .. bindType .. "')"
|
|
bindType = "-" .. prefix .. "" .. i
|
|
isMouseBinding = nil
|
|
end
|
|
|
|
--keybind type
|
|
local shift, alt, ctrl = bind.key:match ("SHIFT"), bind.key:match ("ALT"), bind.key:match ("CTRL")
|
|
local CommandKeys = alt and alt .. "-" or ""
|
|
CommandKeys = ctrl and CommandKeys .. ctrl .. "-" or CommandKeys
|
|
CommandKeys = shift and CommandKeys .. shift .. "-" or CommandKeys
|
|
|
|
local keyBindType
|
|
if (isMouseBinding) then
|
|
keyBindType = [[unitFrame:SetAttribute ("@COMMANDtype@BINDTYPE", "macro")]]
|
|
else
|
|
keyBindType = [[unitFrame:SetAttribute ("type@BINDTYPE", "macro")]]
|
|
end
|
|
|
|
keyBindType = keyBindType:gsub ("@BINDTYPE", bindType)
|
|
keyBindType = keyBindType:gsub ("@COMMAND", CommandKeys)
|
|
bindKeyBindTypeFunc = bindKeyBindTypeFunc .. keyBindType
|
|
|
|
--spell or macro
|
|
if (bind.action == "_spell") then
|
|
local macroTextLine
|
|
if (isMouseBinding) then
|
|
macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "/cast [@mouseover] @SPELL")]]
|
|
else
|
|
macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "/cast [@mouseover] @SPELL")]]
|
|
end
|
|
macroTextLine = macroTextLine:gsub ("@BINDTYPE", bindType)
|
|
macroTextLine = macroTextLine:gsub ("@SPELL", bind.actiontext)
|
|
macroTextLine = macroTextLine:gsub ("@COMMAND", CommandKeys)
|
|
bindMacroTextFunc = bindMacroTextFunc .. macroTextLine
|
|
|
|
elseif (bind.action == "_macro") then
|
|
local macroTextLine
|
|
if (isMouseBinding) then
|
|
macroTextLine = [[unitFrame:SetAttribute ("@COMMANDmacrotext@BINDTYPE", "@MACRO")]]
|
|
else
|
|
macroTextLine = [[unitFrame:SetAttribute ("macrotext@BINDTYPE", "@MACRO")]]
|
|
end
|
|
macroTextLine = macroTextLine:gsub ("@BINDTYPE", bindType)
|
|
macroTextLine = macroTextLine:gsub ("@MACRO", bind.actiontext)
|
|
macroTextLine = macroTextLine:gsub ("@COMMAND", CommandKeys)
|
|
bindMacroTextFunc = bindMacroTextFunc .. macroTextLine
|
|
|
|
end
|
|
end
|
|
|
|
--~key
|
|
local bindTypeFuncLoaded = loadstring (bindKeyBindTypeFunc)
|
|
local bindMacroFuncLoaded = loadstring (bindMacroTextFunc)
|
|
|
|
if (not bindMacroFuncLoaded or not bindTypeFuncLoaded) then
|
|
return
|
|
end
|
|
|
|
return bindString, bindTypeFuncLoaded, bindMacroFuncLoaded
|
|
end
|
|
|
|
|
|
function DF:SetKeybindsOnProtectedFrame (frame, bind_string, bind_type_func, bind_macro_func)
|
|
|
|
bind_type_func (frame)
|
|
bind_macro_func (frame)
|
|
frame:SetAttribute ("_onenter", bind_string)
|
|
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~standard backdrop
|
|
|
|
function DF:ApplyStandardBackdrop (f, darkTheme, alphaScale)
|
|
alphaScale = alphaScale or 1.0
|
|
|
|
if(not f.SetBackdrop)then
|
|
print(debugstack(1,2,1))
|
|
end
|
|
|
|
if (darkTheme) then
|
|
f:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Cooldown\cooldown2]], tileSize = 32, tile = true})
|
|
f:SetBackdropBorderColor (0, 0, 0, 1)
|
|
f:SetBackdropColor (.54, .54, .54, .54 * alphaScale)
|
|
else
|
|
f:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
|
|
f:SetBackdropBorderColor (0, 0, 0, 1)
|
|
f:SetBackdropColor (0, 0, 0, 0.2 * alphaScale)
|
|
end
|
|
|
|
if (not f.__background) then
|
|
f.__background = f:CreateTexture (nil, "background")
|
|
end
|
|
|
|
f.__background:SetColorTexture (0.2317647, 0.2317647, 0.2317647)
|
|
f.__background:SetVertexColor (0.27, 0.27, 0.27)
|
|
f.__background:SetAlpha (0.8 * alphaScale)
|
|
f.__background:SetVertTile (true)
|
|
f.__background:SetHorizTile (true)
|
|
f.__background:SetAllPoints()
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~title bar
|
|
|
|
DF.TitleFunctions = {
|
|
|
|
SetTitle = function (self, titleText, titleColor, font, size)
|
|
self.TitleLabel:SetText (titleText or self.TitleLabel:GetText())
|
|
|
|
if (titleColor) then
|
|
local r, g, b, a = DF:ParseColors (titleColor)
|
|
self.TitleLabel:SetTextColor (r, g, b, a)
|
|
end
|
|
|
|
if (font) then
|
|
DF:SetFontFace (self.TitleLabel, font)
|
|
end
|
|
|
|
if (size) then
|
|
DF:SetFontSize (self.TitleLabel, size)
|
|
end
|
|
end
|
|
|
|
|
|
}
|
|
|
|
function DF:CreateTitleBar (f, titleText)
|
|
|
|
local titleBar = CreateFrame ("frame", f:GetName() and f:GetName() .. "TitleBar" or nil, f,"BackdropTemplate")
|
|
titleBar:SetPoint ("topleft", f, "topleft", 2, -3)
|
|
titleBar:SetPoint ("topright", f, "topright", -2, -3)
|
|
titleBar:SetHeight (20)
|
|
titleBar:SetBackdrop (SimplePanel_frame_backdrop) --it's an upload from this file
|
|
titleBar:SetBackdropColor (.2, .2, .2, 1)
|
|
titleBar:SetBackdropBorderColor (0, 0, 0, 1)
|
|
|
|
local closeButton = CreateFrame ("button", titleBar:GetName() and titleBar:GetName() .. "CloseButton" or nil, titleBar, "BackdropTemplate")
|
|
closeButton:SetSize (16, 16)
|
|
|
|
closeButton:SetNormalTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
closeButton:SetHighlightTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
closeButton:SetPushedTexture ([[Interface\GLUES\LOGIN\Glues-CheckBox-Check]])
|
|
closeButton:GetNormalTexture():SetDesaturated(true)
|
|
closeButton:GetHighlightTexture():SetDesaturated(true)
|
|
closeButton:GetPushedTexture():SetDesaturated(true)
|
|
|
|
closeButton:SetAlpha (0.7)
|
|
closeButton:SetScript ("OnClick", simple_panel_close_click) --upvalue from this file
|
|
|
|
local titleLabel = titleBar:CreateFontString (titleBar:GetName() and titleBar:GetName() .. "TitleText" or nil, "overlay", "GameFontNormal")
|
|
titleLabel:SetTextColor (.8, .8, .8, 1)
|
|
titleLabel:SetText (titleText or "")
|
|
|
|
--anchors
|
|
closeButton:SetPoint ("right", titleBar, "right", -2, 0)
|
|
titleLabel:SetPoint ("center", titleBar, "center")
|
|
|
|
--members
|
|
f.TitleBar = titleBar
|
|
f.CloseButton = closeButton
|
|
f.TitleLabel = titleLabel
|
|
|
|
titleBar.CloseButton = closeButton
|
|
titleBar.Text = titleLabel
|
|
|
|
DF:Mixin (f, DF.TitleFunctions)
|
|
|
|
return titleBar
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
-- ~icon row
|
|
|
|
DF.IconRowFunctions = {
|
|
|
|
GetIcon = function (self)
|
|
local iconFrame = self.IconPool [self.NextIcon]
|
|
|
|
if (not iconFrame) then
|
|
local newIconFrame = CreateFrame ("frame", "$parentIcon" .. self.NextIcon, self, "BackdropTemplate")
|
|
|
|
newIconFrame.Texture = newIconFrame:CreateTexture (nil, "artwork")
|
|
PixelUtil.SetPoint (newIconFrame.Texture, "topleft", newIconFrame, "topleft", 1, -1)
|
|
PixelUtil.SetPoint (newIconFrame.Texture, "bottomright", newIconFrame, "bottomright", -1, 1)
|
|
|
|
newIconFrame.Border = newIconFrame:CreateTexture (nil, "background")
|
|
newIconFrame.Border:SetAllPoints()
|
|
newIconFrame.Border:SetColorTexture (0, 0, 0)
|
|
|
|
newIconFrame:SetBackdrop ({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
|
|
newIconFrame:SetBackdropBorderColor (0, 0, 0, 0)
|
|
newIconFrame:EnableMouse (false)
|
|
|
|
local cooldownFrame = CreateFrame ("cooldown", "$parentIconCooldown" .. self.NextIcon, newIconFrame, "CooldownFrameTemplate, BackdropTemplate")
|
|
cooldownFrame:SetAllPoints()
|
|
cooldownFrame:EnableMouse (false)
|
|
cooldownFrame:SetFrameLevel (newIconFrame:GetFrameLevel()+1)
|
|
cooldownFrame:SetHideCountdownNumbers (self.options.surpress_blizzard_cd_timer)
|
|
cooldownFrame.noCooldownCount = self.options.surpress_tulla_omni_cc
|
|
|
|
newIconFrame.CountdownText = cooldownFrame:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
--newIconFrame.CountdownText:SetPoint ("center")
|
|
newIconFrame.CountdownText:SetPoint (self.options.text_anchor or "center", newIconFrame, self.options.text_rel_anchor or "center", self.options.text_x_offset or 0, self.options.text_y_offset or 0)
|
|
newIconFrame.CountdownText:Hide()
|
|
|
|
newIconFrame.StackText = newIconFrame:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
--newIconFrame.StackText:SetPoint ("bottomright")
|
|
newIconFrame.StackText:SetPoint (self.options.stack_text_anchor or "center", newIconFrame, self.options.stack_text_rel_anchor or "bottomright", self.options.stack_text_x_offset or 0, self.options.stack_text_y_offset or 0)
|
|
newIconFrame.StackText:Hide()
|
|
|
|
newIconFrame.Desc = newIconFrame:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
--newIconFrame.Desc:SetPoint ("bottom", newIconFrame, "top", 0, 2)
|
|
newIconFrame.Desc:SetPoint(self.options.desc_text_anchor or "bottom", newIconFrame, self.options.desc_text_rel_anchor or "top", self.options.desc_text_x_offset or 0, self.options.desc_text_y_offset or 2)
|
|
newIconFrame.Desc:Hide()
|
|
|
|
newIconFrame.Cooldown = cooldownFrame
|
|
|
|
self.IconPool [self.NextIcon] = newIconFrame
|
|
iconFrame = newIconFrame
|
|
end
|
|
|
|
iconFrame:ClearAllPoints()
|
|
|
|
local anchor = self.options.anchor
|
|
local anchorTo = self.NextIcon == 1 and self or self.IconPool [self.NextIcon - 1]
|
|
local xPadding = self.NextIcon == 1 and self.options.left_padding or self.options.icon_padding
|
|
local growDirection = self.options.grow_direction
|
|
|
|
if (growDirection == 1) then --grow to right
|
|
if (self.NextIcon == 1) then
|
|
PixelUtil.SetPoint (iconFrame, "left", anchorTo, "left", xPadding, 0)
|
|
else
|
|
PixelUtil.SetPoint (iconFrame, "left", anchorTo, "right", xPadding, 0)
|
|
end
|
|
|
|
elseif (growDirection == 2) then --grow to left
|
|
if (self.NextIcon == 1) then
|
|
PixelUtil.SetPoint (iconFrame, "right", anchorTo, "right", xPadding, 0)
|
|
else
|
|
PixelUtil.SetPoint (iconFrame, "right", anchorTo, "left", xPadding, 0)
|
|
end
|
|
|
|
end
|
|
|
|
DF:SetFontColor (iconFrame.CountdownText, self.options.text_color)
|
|
|
|
self.NextIcon = self.NextIcon + 1
|
|
return iconFrame
|
|
end,
|
|
|
|
SetIcon = function (self, spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge)
|
|
|
|
local spellName, _, spellIcon
|
|
|
|
if (not forceTexture) then
|
|
spellName, _, spellIcon = GetSpellInfo (spellId)
|
|
else
|
|
spellIcon = forceTexture
|
|
end
|
|
|
|
if (spellIcon) then
|
|
local iconFrame = self:GetIcon()
|
|
iconFrame.Texture:SetTexture (spellIcon)
|
|
iconFrame.Texture:SetTexCoord (unpack (self.options.texcoord))
|
|
|
|
if (borderColor) then
|
|
iconFrame:SetBackdropBorderColor (Plater:ParseColors (borderColor))
|
|
else
|
|
iconFrame:SetBackdropBorderColor (0, 0, 0 ,0)
|
|
end
|
|
|
|
if (startTime) then
|
|
CooldownFrame_Set (iconFrame.Cooldown, startTime, duration, true, true)
|
|
|
|
if (self.options.show_text) then
|
|
iconFrame.CountdownText:Show()
|
|
|
|
local formattedTime = floor (startTime + duration - GetTime())
|
|
|
|
if (formattedTime >= 3600) then
|
|
formattedTime = floor (formattedTime / 3600) .. "h"
|
|
|
|
elseif (formattedTime >= 60) then
|
|
formattedTime = floor (formattedTime / 60) .. "m"
|
|
|
|
else
|
|
formattedTime = floor (formattedTime)
|
|
end
|
|
|
|
iconFrame.CountdownText:SetPoint (self.options.text_anchor or "center", iconFrame, self.options.text_rel_anchor or "center", self.options.text_x_offset or 0, self.options.text_y_offset or 0)
|
|
DF:SetFontSize (iconFrame.CountdownText, self.options.text_size)
|
|
DF:SetFontFace (iconFrame.CountdownText, self.options.text_font)
|
|
DF:SetFontOutline (iconFrame.CountdownText, self.options.text_outline)
|
|
iconFrame.CountdownText:SetText (formattedTime)
|
|
|
|
else
|
|
iconFrame.CountdownText:Hide()
|
|
end
|
|
|
|
iconFrame.Cooldown:SetHideCountdownNumbers (self.options.surpress_blizzard_cd_timer)
|
|
else
|
|
iconFrame.CountdownText:Hide()
|
|
end
|
|
|
|
if (descText and self.options.desc_text) then
|
|
iconFrame.Desc:Show()
|
|
iconFrame.Desc:SetText (descText.text)
|
|
iconFrame.Desc:SetTextColor (DF:ParseColors (descText.text_color or self.options.desc_text_color))
|
|
iconFrame.Desc:SetPoint(self.options.desc_text_anchor or "bottom", iconFrame, self.options.desc_text_rel_anchor or "top", self.options.desc_text_x_offset or 0, self.options.desc_text_y_offset or 2)
|
|
DF:SetFontSize (iconFrame.Desc, descText.text_size or self.options.desc_text_size)
|
|
DF:SetFontFace (iconFrame.Desc, self.options.desc_text_font)
|
|
DF:SetFontOutline (iconFrame.Desc, self.options.desc_text_outline)
|
|
else
|
|
iconFrame.Desc:Hide()
|
|
end
|
|
|
|
if (count and count > 1 and self.options.stack_text) then
|
|
iconFrame.StackText:Show()
|
|
iconFrame.StackText:SetText (count)
|
|
iconFrame.StackText:SetTextColor (DF:ParseColors (self.options.desc_text_color))
|
|
iconFrame.StackText:SetPoint (self.options.stack_text_anchor or "center", iconFrame, self.options.stack_text_rel_anchor or "bottomright", self.options.stack_text_x_offset or 0, self.options.stack_text_y_offset or 0)
|
|
DF:SetFontSize (iconFrame.StackText, self.options.stack_text_size)
|
|
DF:SetFontFace (iconFrame.StackText, self.options.stack_text_font)
|
|
DF:SetFontOutline (iconFrame.StackText, self.options.stack_text_outline)
|
|
else
|
|
iconFrame.StackText:Hide()
|
|
end
|
|
|
|
PixelUtil.SetSize (iconFrame, self.options.icon_width, self.options.icon_height)
|
|
iconFrame:Show()
|
|
|
|
--> update the size of the frame
|
|
self:SetWidth ((self.options.left_padding * 2) + (self.options.icon_padding * (self.NextIcon-2)) + (self.options.icon_width * (self.NextIcon - 1)))
|
|
self:SetHeight (self.options.icon_height + (self.options.top_padding * 2))
|
|
|
|
--> make information available
|
|
iconFrame.spellId = spellId
|
|
iconFrame.startTime = startTime
|
|
iconFrame.duration = duration
|
|
iconFrame.count = count
|
|
iconFrame.debuffType = debuffType
|
|
iconFrame.caster = caster
|
|
iconFrame.canStealOrPurge = canStealOrPurge
|
|
|
|
--> show the frame
|
|
self:Show()
|
|
|
|
return iconFrame
|
|
end
|
|
end,
|
|
|
|
ClearIcons = function (self)
|
|
for i = 1, self.NextIcon -1 do
|
|
self.IconPool [i]:Hide()
|
|
end
|
|
self.NextIcon = 1
|
|
self:Hide()
|
|
end,
|
|
|
|
GetIconGrowDirection = function (self)
|
|
local side = self.options.anchor.side
|
|
|
|
if (side == 1) then
|
|
return 1
|
|
elseif (side == 2) then
|
|
return 2
|
|
elseif (side == 3) then
|
|
return 1
|
|
elseif (side == 4) then
|
|
return 1
|
|
elseif (side == 5) then
|
|
return 2
|
|
elseif (side == 6) then
|
|
return 1
|
|
elseif (side == 7) then
|
|
return 2
|
|
elseif (side == 8) then
|
|
return 1
|
|
elseif (side == 9) then
|
|
return 1
|
|
elseif (side == 10) then
|
|
return 1
|
|
elseif (side == 11) then
|
|
return 2
|
|
elseif (side == 12) then
|
|
return 1
|
|
elseif (side == 13) then
|
|
return 1
|
|
end
|
|
end,
|
|
|
|
OnOptionChanged = function (self, optionName)
|
|
self:SetBackdropColor (unpack (self.options.backdrop_color))
|
|
self:SetBackdropBorderColor (unpack (self.options.backdrop_border_color))
|
|
end,
|
|
}
|
|
|
|
local default_icon_row_options = {
|
|
icon_width = 20,
|
|
icon_height = 20,
|
|
texcoord = {.1, .9, .1, .9},
|
|
show_text = true,
|
|
text_color = {1, 1, 1, 1},
|
|
text_size = 12,
|
|
text_font = "Arial Narrow",
|
|
text_outline = "NONE",
|
|
text_anchor = "center",
|
|
text_rel_anchor = "center",
|
|
text_x_offset = 0,
|
|
text_y_offset = 0,
|
|
desc_text = true,
|
|
desc_text_color = {1, 1, 1, 1},
|
|
desc_text_size = 7,
|
|
desc_text_font = "Arial Narrow",
|
|
desc_text_outline = "NONE",
|
|
desc_text_anchor = "bottom",
|
|
desc_text_rel_anchor = "top",
|
|
desc_text_x_offset = 0,
|
|
desc_text_y_offset = 2,
|
|
stack_text = true,
|
|
stack_text_color = {1, 1, 1, 1},
|
|
stack_text_size = 10,
|
|
stack_text_font = "Arial Narrow",
|
|
stack_text_outline = "NONE",
|
|
stack_text_anchor = "center",
|
|
stack_text_rel_anchor = "bottomright",
|
|
stack_text_x_offset = 0,
|
|
stack_text_y_offset = 0,
|
|
left_padding = 1, --distance between right and left
|
|
top_padding = 1, --distance between top and bottom
|
|
icon_padding = 1, --distance between each icon
|
|
backdrop = {},
|
|
backdrop_color = {0, 0, 0, 0.5},
|
|
backdrop_border_color = {0, 0, 0, 1},
|
|
anchor = {side = 6, x = 2, y = 0},
|
|
grow_direction = 1, --1 = to right 2 = to left
|
|
surpress_blizzard_cd_timer = false,
|
|
surpress_tulla_omni_cc = false,
|
|
}
|
|
|
|
function DF:CreateIconRow (parent, name, options)
|
|
local f = CreateFrame("frame", name, parent, "BackdropTemplate")
|
|
f.IconPool = {}
|
|
f.NextIcon = 1
|
|
|
|
DF:Mixin (f, DF.IconRowFunctions)
|
|
DF:Mixin (f, DF.OptionsFunctions)
|
|
|
|
f:BuildOptionsTable (default_icon_row_options, options)
|
|
|
|
f:SetSize (f.options.icon_width, f.options.icon_height + (f.options.top_padding * 2))
|
|
|
|
f:SetBackdrop (f.options.backdrop)
|
|
f:SetBackdropColor (unpack (f.options.backdrop_color))
|
|
f:SetBackdropBorderColor (unpack (f.options.backdrop_border_color))
|
|
|
|
return f
|
|
end
|
|
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> ~header
|
|
|
|
--mixed functions
|
|
DF.HeaderFunctions = {
|
|
AddFrameToHeaderAlignment = function (self, frame)
|
|
self.FramesToAlign = self.FramesToAlign or {}
|
|
tinsert (self.FramesToAlign, frame)
|
|
end,
|
|
|
|
--@self: an object like a line
|
|
--@headerFrame: the main header frame
|
|
--@anchor: which side the columnHeaders are attach
|
|
AlignWithHeader = function (self, headerFrame, anchor)
|
|
local columnHeaderFrames = headerFrame.columnHeadersCreated
|
|
anchor = anchor or "topleft"
|
|
|
|
for i = 1, #self.FramesToAlign do
|
|
local frame = self.FramesToAlign [i]
|
|
frame:ClearAllPoints()
|
|
|
|
local columnHeader = columnHeaderFrames [i]
|
|
local offset = 0
|
|
|
|
if (columnHeader.columnAlign == "right") then
|
|
offset = columnHeader:GetWidth()
|
|
if (frame:GetObjectType() == "FontString") then
|
|
frame:SetJustifyH ("right")
|
|
end
|
|
end
|
|
|
|
frame:SetPoint (columnHeader.columnAlign, self, anchor, columnHeader.XPosition + columnHeader.columnOffset + offset, 0)
|
|
end
|
|
end,
|
|
|
|
--@self: column header button
|
|
OnClick = function (self, buttonClicked)
|
|
|
|
--get the header main frame
|
|
local headerFrame = self:GetParent()
|
|
|
|
--if this header does not have a clickable header, just ignore
|
|
if (not headerFrame.columnSelected) then
|
|
return
|
|
end
|
|
|
|
--get the latest column header selected
|
|
local previousColumnHeader = headerFrame.columnHeadersCreated [headerFrame.columnSelected]
|
|
previousColumnHeader.Arrow:Hide()
|
|
headerFrame:ResetColumnHeaderBackdrop (previousColumnHeader)
|
|
headerFrame:SetBackdropColorForSelectedColumnHeader (self)
|
|
|
|
if (headerFrame.columnSelected == self.columnIndex) then
|
|
self.order = self.order ~= "ASC" and "ASC" or "DESC"
|
|
end
|
|
headerFrame.columnOrder = self.order
|
|
|
|
--set the new column header selected
|
|
headerFrame.columnSelected = self.columnIndex
|
|
|
|
headerFrame:UpdateSortArrow (self)
|
|
|
|
if (headerFrame.options.header_click_callback) then
|
|
--callback with the main header frame, column header, column index and column order as payload
|
|
local okay, errortext = pcall (headerFrame.options.header_click_callback, headerFrame, self, self.columnIndex, self.order)
|
|
if (not okay) then
|
|
print ("DF: Header onClick callback error:", errortext)
|
|
end
|
|
end
|
|
end,
|
|
}
|
|
|
|
DF.HeaderCoreFunctions = {
|
|
SetHeaderTable = function (self, newTable)
|
|
self.columnHeadersCreated = self.columnHeadersCreated or {}
|
|
self.HeaderTable = newTable
|
|
self.NextHeader = 1
|
|
self.HeaderWidth = 0
|
|
self.HeaderHeight = 0
|
|
self:Refresh()
|
|
end,
|
|
|
|
--return which header is current selected and the the order ASC DESC
|
|
GetSelectedColumn = function (self)
|
|
return self.columnSelected, self.columnHeadersCreated [self.columnSelected or 1].order
|
|
end,
|
|
|
|
--clean up and rebuild the header following the header options
|
|
--@self: main header frame
|
|
Refresh = function (self)
|
|
--> refresh background frame
|
|
self:SetBackdrop (self.options.backdrop)
|
|
self:SetBackdropColor (unpack (self.options.backdrop_color))
|
|
self:SetBackdropBorderColor (unpack (self.options.backdrop_border_color))
|
|
|
|
--> reset all header frames
|
|
for i = 1, #self.columnHeadersCreated do
|
|
local columnHeader = self.columnHeadersCreated [i]
|
|
columnHeader.InUse = false
|
|
columnHeader:Hide()
|
|
end
|
|
|
|
local previousColumnHeader
|
|
local growDirection = string.lower (self.options.grow_direction)
|
|
|
|
--> update header frames
|
|
local headerSize = #self.HeaderTable
|
|
for i = 1, headerSize do
|
|
|
|
--> get the header button, a new one is created if it doesn't exists yet
|
|
local columnHeader = self:GetNextHeader()
|
|
self:UpdateColumnHeader (columnHeader, i)
|
|
|
|
--> grow direction
|
|
if (not previousColumnHeader) then
|
|
columnHeader:SetPoint ("topleft", self, "topleft", 0, 0)
|
|
|
|
if (growDirection == "right") then
|
|
if (self.options.use_line_separators) then
|
|
columnHeader.Separator:Show()
|
|
columnHeader.Separator:SetWidth (self.options.line_separator_width)
|
|
columnHeader.Separator:SetColorTexture (unpack (self.options.line_separator_color))
|
|
|
|
columnHeader.Separator:ClearAllPoints()
|
|
if (self.options.line_separator_gap_align) then
|
|
columnHeader.Separator:SetPoint ("topleft", columnHeader, "topright", 0, 0)
|
|
else
|
|
columnHeader.Separator:SetPoint ("topright", columnHeader, "topright", 0, 0)
|
|
end
|
|
columnHeader.Separator:SetHeight (self.options.line_separator_height)
|
|
end
|
|
end
|
|
|
|
else
|
|
if (growDirection == "right") then
|
|
columnHeader:SetPoint ("topleft", previousColumnHeader, "topright", self.options.padding, 0)
|
|
|
|
if (self.options.use_line_separators) then
|
|
columnHeader.Separator:Show()
|
|
columnHeader.Separator:SetWidth (self.options.line_separator_width)
|
|
columnHeader.Separator:SetColorTexture (unpack (self.options.line_separator_color))
|
|
|
|
columnHeader.Separator:ClearAllPoints()
|
|
if (self.options.line_separator_gap_align) then
|
|
columnHeader.Separator:SetPoint ("topleft", columnHeader, "topright", 0, 0)
|
|
else
|
|
columnHeader.Separator:SetPoint ("topleft", columnHeader, "topright", 0, 0)
|
|
end
|
|
columnHeader.Separator:SetHeight (self.options.line_separator_height)
|
|
|
|
if (headerSize == i) then
|
|
columnHeader.Separator:Hide()
|
|
end
|
|
end
|
|
|
|
elseif (growDirection == "left") then
|
|
columnHeader:SetPoint ("topright", previousColumnHeader, "topleft", -self.options.padding, 0)
|
|
|
|
elseif (growDirection == "bottom") then
|
|
columnHeader:SetPoint ("topleft", previousColumnHeader, "bottomleft", 0, -self.options.padding)
|
|
|
|
elseif (growDirection == "top") then
|
|
columnHeader:SetPoint ("bottomleft", previousColumnHeader, "topleft", 0, self.options.padding)
|
|
end
|
|
end
|
|
|
|
previousColumnHeader = columnHeader
|
|
end
|
|
|
|
self:SetSize (self.HeaderWidth, self.HeaderHeight)
|
|
|
|
end,
|
|
|
|
--@self: main header frame
|
|
UpdateSortArrow = function (self, columnHeader, defaultShown, defaultOrder)
|
|
|
|
local options = self.options
|
|
local order = defaultOrder or columnHeader.order
|
|
local arrowIcon = columnHeader.Arrow
|
|
|
|
if (type (defaultShown) ~= "boolean") then
|
|
arrowIcon:Show()
|
|
else
|
|
arrowIcon:SetShown (defaultShown)
|
|
if (defaultShown) then
|
|
self:SetBackdropColorForSelectedColumnHeader (columnHeader)
|
|
end
|
|
end
|
|
|
|
arrowIcon:SetAlpha (options.arrow_alpha)
|
|
|
|
if (order == "ASC") then
|
|
arrowIcon:SetTexture (options.arrow_up_texture)
|
|
arrowIcon:SetTexCoord (unpack (options.arrow_up_texture_coords))
|
|
arrowIcon:SetSize (unpack (options.arrow_up_size))
|
|
|
|
elseif (order == "DESC") then
|
|
arrowIcon:SetTexture (options.arrow_down_texture)
|
|
arrowIcon:SetTexCoord (unpack (options.arrow_down_texture_coords))
|
|
arrowIcon:SetSize (unpack (options.arrow_down_size))
|
|
end
|
|
|
|
end,
|
|
|
|
--@self: main header frame
|
|
UpdateColumnHeader = function (self, columnHeader, headerIndex)
|
|
local headerData = self.HeaderTable [headerIndex]
|
|
|
|
if (headerData.icon) then
|
|
columnHeader.Icon:SetTexture (headerData.icon)
|
|
|
|
if (headerData.texcoord) then
|
|
columnHeader.Icon:SetTexCoord (unpack (headerData.texcoord))
|
|
else
|
|
columnHeader.Icon:SetTexCoord (0, 1, 0, 1)
|
|
end
|
|
|
|
columnHeader.Icon:SetPoint ("left", columnHeader, "left", self.options.padding, 0)
|
|
columnHeader.Icon:Show()
|
|
end
|
|
|
|
if (headerData.text) then
|
|
columnHeader.Text:SetText (headerData.text)
|
|
|
|
--> text options
|
|
DF:SetFontColor (columnHeader.Text, self.options.text_color)
|
|
DF:SetFontSize (columnHeader.Text, self.options.text_size)
|
|
DF:SetFontOutline (columnHeader.Text, self.options.text_shadow)
|
|
|
|
--> point
|
|
if (not headerData.icon) then
|
|
columnHeader.Text:SetPoint ("left", columnHeader, "left", self.options.padding, 0)
|
|
else
|
|
columnHeader.Text:SetPoint ("left", columnHeader.Icon, "right", self.options.padding, 0)
|
|
end
|
|
|
|
columnHeader.Text:Show()
|
|
end
|
|
|
|
--column header index
|
|
columnHeader.columnIndex = headerIndex
|
|
|
|
if (headerData.canSort) then
|
|
columnHeader.order = "DESC"
|
|
columnHeader.Arrow:SetTexture (self.options.arrow_up_texture)
|
|
else
|
|
columnHeader.Arrow:Hide()
|
|
end
|
|
|
|
if (headerData.selected) then
|
|
columnHeader.Arrow:Show()
|
|
columnHeader.Arrow:SetAlpha (.843)
|
|
self:UpdateSortArrow (columnHeader, true, columnHeader.order)
|
|
self.columnSelected = headerIndex
|
|
else
|
|
if (headerData.canSort) then
|
|
self:UpdateSortArrow (columnHeader, false, columnHeader.order)
|
|
end
|
|
end
|
|
|
|
--> size
|
|
if (headerData.width) then
|
|
columnHeader:SetWidth (headerData.width)
|
|
end
|
|
if (headerData.height) then
|
|
columnHeader:SetHeight (headerData.height)
|
|
end
|
|
|
|
columnHeader.XPosition = self.HeaderWidth-- + self.options.padding
|
|
columnHeader.YPosition = self.HeaderHeight-- + self.options.padding
|
|
|
|
columnHeader.columnAlign = headerData.align or "left"
|
|
columnHeader.columnOffset = headerData.offset or 0
|
|
|
|
--> add the header piece size to the total header size
|
|
local growDirection = string.lower (self.options.grow_direction)
|
|
|
|
if (growDirection == "right" or growDirection == "left") then
|
|
self.HeaderWidth = self.HeaderWidth + columnHeader:GetWidth() + self.options.padding
|
|
self.HeaderHeight = math.max (self.HeaderHeight, columnHeader:GetHeight())
|
|
|
|
elseif (growDirection == "top" or growDirection == "bottom") then
|
|
self.HeaderWidth = math.max (self.HeaderWidth, columnHeader:GetWidth())
|
|
self.HeaderHeight = self.HeaderHeight + columnHeader:GetHeight() + self.options.padding
|
|
end
|
|
|
|
columnHeader:Show()
|
|
columnHeader.InUse = true
|
|
end,
|
|
|
|
--reset column header backdrop
|
|
--@self: main header frame
|
|
ResetColumnHeaderBackdrop = function (self, columnHeader)
|
|
columnHeader:SetBackdrop (self.options.header_backdrop)
|
|
columnHeader:SetBackdropColor (unpack (self.options.header_backdrop_color))
|
|
columnHeader:SetBackdropBorderColor (unpack (self.options.header_backdrop_border_color))
|
|
end,
|
|
|
|
--@self: main header frame
|
|
SetBackdropColorForSelectedColumnHeader = function (self, columnHeader)
|
|
columnHeader:SetBackdropColor (unpack (self.options.header_backdrop_color_selected))
|
|
end,
|
|
|
|
--clear the column header
|
|
--@self: main header frame
|
|
ClearColumnHeader = function (self, columnHeader)
|
|
columnHeader:SetSize (self.options.header_width, self.options.header_height)
|
|
self:ResetColumnHeaderBackdrop (columnHeader)
|
|
|
|
columnHeader:ClearAllPoints()
|
|
|
|
columnHeader.Icon:SetTexture ("")
|
|
columnHeader.Icon:Hide()
|
|
columnHeader.Text:SetText ("")
|
|
columnHeader.Text:Hide()
|
|
end,
|
|
|
|
--get the next column header, create one if doesn't exists
|
|
--@self: main header frame
|
|
GetNextHeader = function (self)
|
|
local nextHeader = self.NextHeader
|
|
local columnHeader = self.columnHeadersCreated [nextHeader]
|
|
|
|
if (not columnHeader) then
|
|
--create a new column header
|
|
local newHeader = CreateFrame ("button", "$parentHeaderIndex" .. nextHeader, self,"BackdropTemplate")
|
|
newHeader:SetScript ("OnClick", DF.HeaderFunctions.OnClick)
|
|
|
|
--header icon
|
|
DF:CreateImage (newHeader, "", self.options.header_height, self.options.header_height, "ARTWORK", nil, "Icon", "$parentIcon")
|
|
--header separator
|
|
DF:CreateImage (newHeader, "", 1, 1, "ARTWORK", nil, "Separator", "$parentSeparator")
|
|
--header name text
|
|
DF:CreateLabel (newHeader, "", self.options.text_size, self.options.text_color, "GameFontNormal", "Text", "$parentText", "ARTWORK")
|
|
--header selected and order icon
|
|
DF:CreateImage (newHeader, self.options.arrow_up_texture, 12, 12, "ARTWORK", nil, "Arrow", "$parentArrow")
|
|
|
|
newHeader.Arrow:SetPoint ("right", newHeader, "right", -1, 0)
|
|
|
|
newHeader.Separator:Hide()
|
|
newHeader.Arrow:Hide()
|
|
|
|
self:UpdateSortArrow (newHeader, false, "DESC")
|
|
|
|
tinsert (self.columnHeadersCreated, newHeader)
|
|
columnHeader = newHeader
|
|
end
|
|
|
|
self:ClearColumnHeader (columnHeader)
|
|
self.NextHeader = self.NextHeader + 1
|
|
return columnHeader
|
|
end,
|
|
|
|
NextHeader = 1,
|
|
HeaderWidth = 0,
|
|
HeaderHeight = 0,
|
|
}
|
|
|
|
local default_header_options = {
|
|
backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
backdrop_color = {0, 0, 0, 0.2},
|
|
backdrop_border_color = {0.1, 0.1, 0.1, .2},
|
|
|
|
text_color = {1, 1, 1, 1},
|
|
text_size = 10,
|
|
text_shadow = false,
|
|
grow_direction = "RIGHT",
|
|
padding = 2,
|
|
|
|
--each piece of the header
|
|
header_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
header_backdrop_color = {0, 0, 0, 0.5},
|
|
header_backdrop_color_selected = {0.3, 0.3, 0.3, 0.5},
|
|
header_backdrop_border_color = {0, 0, 0, 0},
|
|
header_width = 120,
|
|
header_height = 20,
|
|
|
|
arrow_up_texture = [[Interface\Buttons\Arrow-Up-Down]],
|
|
arrow_up_texture_coords = {0, 1, 6/16, 1},
|
|
arrow_up_size = {12, 11},
|
|
arrow_down_texture = [[Interface\Buttons\Arrow-Down-Down]],
|
|
arrow_down_texture_coords = {0, 1, 0, 11/16},
|
|
arrow_down_size = {12, 11},
|
|
arrow_alpha = 0.659,
|
|
|
|
use_line_separators = false,
|
|
line_separator_color = {.1, .1, .1, .6},
|
|
line_separator_width = 1,
|
|
line_separator_height = 200,
|
|
line_separator_gap_align = false,
|
|
}
|
|
|
|
function DF:CreateHeader (parent, headerTable, options, frameName)
|
|
local f = CreateFrame ("frame", frameName or "$parentHeaderLine", parent,"BackdropTemplate")
|
|
|
|
DF:Mixin (f, DF.OptionsFunctions)
|
|
DF:Mixin (f, DF.HeaderCoreFunctions)
|
|
|
|
f:BuildOptionsTable (default_header_options, options)
|
|
|
|
f:SetBackdrop (f.options.backdrop)
|
|
f:SetBackdropColor (unpack (f.options.backdrop_color))
|
|
f:SetBackdropBorderColor (unpack (f.options.backdrop_border_color))
|
|
|
|
f:SetHeaderTable (headerTable)
|
|
|
|
return f
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> radio group
|
|
|
|
local default_radiogroup_options = {
|
|
width = 1,
|
|
height = 1,
|
|
backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
backdrop_color = {0, 0, 0, 0.2},
|
|
backdrop_border_color = {0.1, 0.1, 0.1, .2},
|
|
is_radio = false,
|
|
}
|
|
|
|
DF.RadioGroupCoreFunctions = {
|
|
RadioOnClick = function (self, fixedParam, value)
|
|
--turn off all checkboxes
|
|
local frameList = {self:GetParent():GetChildren()}
|
|
for _, checkbox in ipairs (frameList) do
|
|
checkbox = checkbox.GetCapsule and checkbox:GetCapsule() or checkbox
|
|
checkbox:SetValue (false)
|
|
end
|
|
|
|
--turn on the clicked checkbox
|
|
self:SetValue (true)
|
|
|
|
--callback
|
|
DF:QuickDispatch (self._set, fixedParam)
|
|
end,
|
|
|
|
Disable = function (self)
|
|
local frameList = {self:GetChildren()}
|
|
for _, checkbox in ipairs (frameList) do
|
|
checkbox = checkbox.GetCapsule and checkbox:GetCapsule() or checkbox
|
|
checkbox:Disable()
|
|
end
|
|
end,
|
|
|
|
Enable = function (self)
|
|
local frameList = {self:GetChildren()}
|
|
for _, checkbox in ipairs (frameList) do
|
|
checkbox = checkbox.GetCapsule and checkbox:GetCapsule() or checkbox
|
|
checkbox:Enable()
|
|
end
|
|
end,
|
|
|
|
DeselectAll = function (self)
|
|
local frameList = {self:GetChildren()}
|
|
for _, checkbox in ipairs (frameList) do
|
|
checkbox = checkbox.GetCapsule and checkbox:GetCapsule() or checkbox
|
|
checkbox:SetValue (false)
|
|
end
|
|
end,
|
|
|
|
FadeIn = function (self)
|
|
local frameList = {self:GetChildren()}
|
|
for _, checkbox in ipairs (frameList) do
|
|
checkbox:SetAlpha (1)
|
|
end
|
|
end,
|
|
|
|
FadeOut = function (self)
|
|
local frameList = {self:GetChildren()}
|
|
for _, checkbox in ipairs (frameList) do
|
|
checkbox:SetAlpha (.7)
|
|
end
|
|
end,
|
|
|
|
SetFadeState = function (self, state)
|
|
if (state) then
|
|
self:FadeIn()
|
|
else
|
|
self:FadeOut()
|
|
end
|
|
end,
|
|
|
|
CreateCheckbox = function (self)
|
|
local checkbox = DF:CreateSwitch (self, function()end, false, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, DF:GetTemplate ("switch", "OPTIONS_CHECKBOX_BRIGHT_TEMPLATE"))
|
|
checkbox:SetAsCheckBox()
|
|
checkbox.Icon = DF:CreateImage (checkbox, "", 16, 16)
|
|
checkbox.Label = DF:CreateLabel (checkbox, "")
|
|
|
|
return checkbox
|
|
end,
|
|
|
|
RefreshCheckbox = function (self, checkbox, optionTable)
|
|
checkbox = checkbox.GetCapsule and checkbox:GetCapsule() or checkbox
|
|
|
|
local setFunc = self.options.is_radio and self.RadioOnClick or optionTable.set
|
|
checkbox:SetSwitchFunction (setFunc)
|
|
checkbox._set = setFunc
|
|
checkbox:SetFixedParameter (optionTable.param)
|
|
|
|
local isChecked = DF:Dispatch (optionTable.get)
|
|
checkbox:SetValue (isChecked)
|
|
|
|
checkbox.Label:SetText (optionTable.name)
|
|
|
|
if (optionTable.texture) then
|
|
checkbox.Icon:SetTexture (optionTable.texture)
|
|
checkbox.Icon:SetPoint ("left", checkbox, "right", 2, 0)
|
|
checkbox.Label:SetPoint ("left", checkbox.Icon, "right", 2, 0)
|
|
|
|
if (optionTable.texcoord) then
|
|
checkbox.Icon:SetTexCoord (unpack (optionTable.texcoord))
|
|
else
|
|
checkbox.Icon:SetTexCoord (0, 1, 0, 1)
|
|
end
|
|
else
|
|
checkbox.Icon:SetTexture ("")
|
|
checkbox.Label:SetPoint ("left", checkbox, "right", 2, 0)
|
|
end
|
|
end,
|
|
|
|
Refresh = function (self)
|
|
local radioOptions = self.RadioOptionsTable
|
|
local radioCheckboxes = {self:GetChildren()}
|
|
|
|
for _, checkbox in ipairs (radioCheckboxes) do
|
|
checkbox:Hide()
|
|
end
|
|
|
|
for radioIndex, optionsTable in ipairs (radioOptions) do
|
|
local checkbox = radioCheckboxes [radioIndex]
|
|
if (not checkbox) then
|
|
checkbox = self:CreateCheckbox()
|
|
end
|
|
checkbox.OptionID = radioIndex
|
|
checkbox:Show()
|
|
self:RefreshCheckbox (checkbox, optionsTable)
|
|
end
|
|
|
|
--sending false to automatically use the radio group children
|
|
self:ArrangeFrames (false, self.AnchorOptions)
|
|
end,
|
|
|
|
SetOptions = function (self, radioOptions)
|
|
self.RadioOptionsTable = radioOptions
|
|
self:Refresh()
|
|
end,
|
|
}
|
|
|
|
--[=[
|
|
radionOptions: an index table with options for the radio group {name = "", set = func (self, param, value), param = value, get = func, texture = "", texcoord = {}}
|
|
set function receives as self the checkbox, use :GetParent() to get the radion group frame
|
|
if get function return nil or false the checkbox isn't checked
|
|
name: the name of the frame
|
|
options: override options for default_radiogroup_options table
|
|
anchorOptions: override options for default_framelayout_options table
|
|
--]=]
|
|
function DF:CreateRadionGroup (parent, radioOptions, name, options, anchorOptions)
|
|
local f = CreateFrame ("frame", name, parent, "BackdropTemplate")
|
|
|
|
DF:Mixin (f, DF.OptionsFunctions)
|
|
DF:Mixin (f, DF.RadioGroupCoreFunctions)
|
|
DF:Mixin (f, DF.LayoutFrame)
|
|
|
|
f:BuildOptionsTable (default_radiogroup_options, options)
|
|
|
|
f:SetSize (f.options.width, f.options.height)
|
|
f:SetBackdrop (f.options.backdrop)
|
|
f:SetBackdropColor (unpack (f.options.backdrop_color))
|
|
f:SetBackdropBorderColor (unpack (f.options.backdrop_border_color))
|
|
|
|
f.AnchorOptions = anchorOptions or {}
|
|
|
|
if (f.options.title) then
|
|
local titleLabel = DF:CreateLabel (f, f.options.title, DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
titleLabel:SetPoint ("bottomleft", f, "topleft", 0, 2)
|
|
f.Title = titleLabel
|
|
end
|
|
|
|
f:SetOptions (radioOptions)
|
|
|
|
return f
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> load conditions panel
|
|
|
|
--this is the table prototype to hold load conditions settings
|
|
local default_load_conditions = {
|
|
class = {},
|
|
spec = {},
|
|
race = {},
|
|
talent = {},
|
|
pvptalent = {},
|
|
group = {},
|
|
role = {},
|
|
affix = {},
|
|
encounter_ids = {},
|
|
map_ids = {},
|
|
}
|
|
|
|
local default_load_conditions_frame_options = {
|
|
title = "Details! Framework: Load Conditions",
|
|
name = "Object",
|
|
}
|
|
|
|
function DF:CreateLoadFilterParser (callback)
|
|
local f = CreateFrame ("frame")
|
|
f:RegisterEvent ("PLAYER_ENTERING_WORLD")
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
f:RegisterEvent ("PLAYER_SPECIALIZATION_CHANGED")
|
|
f:RegisterEvent ("PLAYER_TALENT_UPDATE")
|
|
end
|
|
f:RegisterEvent ("PLAYER_ROLES_ASSIGNED")
|
|
f:RegisterEvent ("ZONE_CHANGED_NEW_AREA")
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
f:RegisterEvent ("CHALLENGE_MODE_START")
|
|
end
|
|
f:RegisterEvent ("ENCOUNTER_START")
|
|
f:RegisterEvent ("PLAYER_REGEN_ENABLED")
|
|
|
|
f:SetScript ("OnEvent", function (self, event, ...)
|
|
if (event == "ENCOUNTER_START") then
|
|
local encounterID = ...
|
|
f.EncounterIDCached = encounterID
|
|
|
|
elseif (event == "ENCOUNTER_END") then
|
|
f.EncounterIDCached = nil
|
|
|
|
elseif (event == "PLAYER_REGEN_ENABLED") then
|
|
--f.EncounterIDCached = nil
|
|
--when the player dies during an encounter, the game is triggering regen enabled
|
|
|
|
elseif (event == "PLAYER_SPECIALIZATION_CHANGED") then
|
|
if (DetailsFrameworkLoadConditionsPanel and DetailsFrameworkLoadConditionsPanel:IsShown()) then
|
|
DetailsFrameworkLoadConditionsPanel:Refresh()
|
|
end
|
|
|
|
local unit = ...
|
|
if (not unit or not UnitIsUnit ("player", unit)) then
|
|
return
|
|
end
|
|
|
|
elseif (event == "PLAYER_ROLES_ASSIGNED") then
|
|
local assignedRole = UnitGroupRolesAssigned ("player")
|
|
if (assignedRole == "NONE") then
|
|
local spec = DetailsFramework.GetSpecialization()
|
|
if (spec) then
|
|
assignedRole = DetailsFramework.GetSpecializationRole (spec)
|
|
end
|
|
end
|
|
|
|
if (DF.CurrentPlayerRole == assignedRole) then
|
|
return
|
|
end
|
|
|
|
DF.CurrentPlayerRole = assignedRole
|
|
end
|
|
|
|
--print ("Plater Script Update:", event, ...)
|
|
|
|
DF:QuickDispatch (callback, f.EncounterIDCached)
|
|
end)
|
|
end
|
|
|
|
function DF:PassLoadFilters (loadTable, encounterID)
|
|
--class
|
|
local passLoadClass
|
|
if (loadTable.class.Enabled) then
|
|
local _, classFileName = UnitClass ("player")
|
|
if (not loadTable.class [classFileName]) then
|
|
return false
|
|
else
|
|
passLoadClass = true
|
|
end
|
|
end
|
|
|
|
--spec
|
|
if (IS_WOW_PROJECT_MAINLINE and loadTable.spec.Enabled) then
|
|
local canCheckTalents = true
|
|
|
|
if (passLoadClass) then
|
|
--if is allowed to load on this class, check if the talents isn't from another class
|
|
local _, classFileName = UnitClass ("player")
|
|
local specsForThisClass = DF:GetClassSpecIDs (classFileName)
|
|
|
|
canCheckTalents = false
|
|
|
|
for _, specID in ipairs (specsForThisClass) do
|
|
if (loadTable.spec [specID] or loadTable.spec [specID..""]) then
|
|
--theres a talent for this class
|
|
canCheckTalents = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if (canCheckTalents) then
|
|
local specIndex = DetailsFramework.GetSpecialization()
|
|
if (specIndex) then
|
|
local specID = DetailsFramework.GetSpecializationInfo (specIndex)
|
|
if not specID or (not loadTable.spec [specID] and not loadTable.spec [specID..""]) then
|
|
return false
|
|
end
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
--race
|
|
if (loadTable.race.Enabled) then
|
|
local raceName, raceFileName, raceID = UnitRace ("player")
|
|
if (not loadTable.race [raceFileName]) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
--talents
|
|
if (IS_WOW_PROJECT_MAINLINE and loadTable.talent.Enabled) then
|
|
local talentsInUse = DF:GetCharacterTalents (false, true)
|
|
local hasTalent
|
|
for talentID, _ in pairs (talentsInUse) do
|
|
if talentID and (loadTable.talent [talentID] or loadTable.talent [talentID .. ""]) then
|
|
hasTalent = true
|
|
break
|
|
end
|
|
end
|
|
if (not hasTalent) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
--pvptalent
|
|
if (IS_WOW_PROJECT_MAINLINE and loadTable.pvptalent.Enabled) then
|
|
local talentsInUse = DF:GetCharacterPvPTalents (false, true)
|
|
local hasTalent
|
|
for talentID, _ in pairs (talentsInUse) do
|
|
if talentID and (loadTable.pvptalent [talentID] or loadTable.pvptalent [talentID .. ""]) then
|
|
hasTalent = true
|
|
break
|
|
end
|
|
end
|
|
if (not hasTalent) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
--group
|
|
if (loadTable.group.Enabled) then
|
|
local _, zoneType = GetInstanceInfo()
|
|
if (not loadTable.group [zoneType]) then
|
|
return
|
|
end
|
|
end
|
|
|
|
--role
|
|
if (loadTable.role.Enabled) then
|
|
local assignedRole = UnitGroupRolesAssigned ("player")
|
|
if (assignedRole == "NONE") then
|
|
local spec = DetailsFramework.GetSpecialization()
|
|
if (spec) then
|
|
assignedRole = DetailsFramework.GetSpecializationRole (spec)
|
|
end
|
|
end
|
|
if (not loadTable.role [assignedRole]) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
--affix
|
|
if (IS_WOW_PROJECT_MAINLINE and loadTable.affix.Enabled) then
|
|
local isInMythicDungeon = C_ChallengeMode.IsChallengeModeActive()
|
|
if (not isInMythicDungeon) then
|
|
return false
|
|
end
|
|
|
|
local level, affixes, wasEnergized = C_ChallengeMode.GetActiveKeystoneInfo()
|
|
local hasAffix = false
|
|
for _, affixID in ipairs (affixes) do
|
|
if affixID and (loadTable.affix [affixID] or loadTable.affix [affixID .. ""]) then
|
|
hasAffix = true
|
|
break
|
|
end
|
|
end
|
|
|
|
if (not hasAffix) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
--encounter id
|
|
if (loadTable.encounter_ids.Enabled) then
|
|
if (not encounterID) then
|
|
return
|
|
end
|
|
local hasEncounter
|
|
for _, ID in ipairs (loadTable.encounter_ids) do
|
|
if (ID == encounterID) then
|
|
hasEncounter = true
|
|
break
|
|
end
|
|
if (not hasEncounter) then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
--map id
|
|
if (loadTable.map_ids.Enabled) then
|
|
local _, _, _, _, _, _, _, zoneMapID = GetInstanceInfo()
|
|
local uiMapID = C_Map.GetBestMapForUnit ("player")
|
|
|
|
local hasMapID
|
|
for _, ID in ipairs (loadTable.map_ids) do
|
|
if (ID == zoneMapID or ID == uiMapID) then
|
|
hasMapID = true
|
|
break
|
|
end
|
|
if (not hasMapID) then
|
|
return false
|
|
end
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
--this func will deploy the default values from the prototype into the config table
|
|
function DF:UpdateLoadConditionsTable (configTable)
|
|
configTable = configTable or {}
|
|
DF.table.deploy (configTable, default_load_conditions)
|
|
return configTable
|
|
end
|
|
|
|
--/run Plater.OpenOptionsPanel()PlaterOptionsPanelContainer:SelectIndex (Plater, 14)
|
|
|
|
function DF:OpenLoadConditionsPanel (optionsTable, callback, frameOptions)
|
|
|
|
frameOptions = frameOptions or {}
|
|
DF.table.deploy (frameOptions, default_load_conditions_frame_options)
|
|
|
|
DF:UpdateLoadConditionsTable (optionsTable)
|
|
|
|
if (not DetailsFrameworkLoadConditionsPanel) then
|
|
|
|
local f = DF:CreateSimplePanel (UIParent, 970, 505, "Load Conditions", "DetailsFrameworkLoadConditionsPanel")
|
|
f:SetBackdropColor (0, 0, 0, 1)
|
|
f.AllRadioGroups = {}
|
|
f.AllTextEntries = {}
|
|
f.OptionsTable = optionsTable
|
|
|
|
DF:ApplyStandardBackdrop (f, false, 1.1)
|
|
|
|
local xStartAt = 10
|
|
local x2StartAt = 500
|
|
local anchorPositions = {
|
|
class = {xStartAt, -70},
|
|
spec = {xStartAt, -170},
|
|
race = {xStartAt, -210},
|
|
role = {xStartAt, -310},
|
|
talent = {xStartAt, -350},
|
|
pvptalent = {x2StartAt, -70},
|
|
group = {x2StartAt, -210},
|
|
affix = {x2StartAt, -270},
|
|
encounter_ids = {x2StartAt, -400},
|
|
map_ids = {x2StartAt, -440},
|
|
}
|
|
|
|
local editingLabel = DF:CreateLabel (f, "Load Conditions For:")
|
|
local editingWhatLabel = DF:CreateLabel (f, "")
|
|
editingLabel:SetPoint ("topleft", f, "topleft", 10, -35)
|
|
editingWhatLabel:SetPoint ("left", editingLabel, "right", 2, 0)
|
|
|
|
--this label store the name of what is being edited
|
|
f.EditingLabel = editingWhatLabel
|
|
|
|
--when the user click on an option, run the callback
|
|
f.RunCallback = function()
|
|
DF:Dispatch (f.CallbackFunc)
|
|
end
|
|
|
|
--when the user click on an option or when the panel is opened
|
|
--check if there's an option enabled and fadein all options, fadeout otherwise
|
|
f.OnRadioStateChanged = function (radioGroup, subConfigTable)
|
|
subConfigTable.Enabled = nil
|
|
subConfigTable.Enabled = next (subConfigTable) and true or nil
|
|
radioGroup:SetFadeState (subConfigTable.Enabled)
|
|
end
|
|
|
|
--create the radio group for character class
|
|
f.OnRadioCheckboxClick = function (self, key, value)
|
|
--hierarchy: DBKey ["class"] key ["HUNTER"] value TRUE
|
|
local DBKey = self:GetParent().DBKey
|
|
f.OptionsTable [DBKey] [key and key .. ""] = value and true or nil
|
|
if not value then -- cleanup "number" type values
|
|
f.OptionsTable [DBKey] [key] = nil
|
|
end
|
|
f.OnRadioStateChanged (self:GetParent(), f.OptionsTable [DBKey])
|
|
f.RunCallback()
|
|
end
|
|
|
|
--create the radio group for classes
|
|
local classes = {}
|
|
for _, classTable in pairs (DF:GetClassList()) do
|
|
tinsert (classes, {
|
|
name = classTable.Name,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = classTable.FileString,
|
|
get = function() return f.OptionsTable.class [classTable.FileString] end,
|
|
texture = classTable.Texture,
|
|
texcoord = classTable.TexCoord,
|
|
})
|
|
end
|
|
|
|
local classGroup = DF:CreateRadionGroup (f, classes, name, {width = 200, height = 200, title = "Character Class"}, {offset_x = 130, amount_per_line = 3})
|
|
classGroup:SetPoint ("topleft", f, "topleft", anchorPositions.class [1], anchorPositions.class [2])
|
|
classGroup.DBKey = "class"
|
|
tinsert (f.AllRadioGroups, classGroup)
|
|
|
|
--create the radio group for character spec
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
local specs = {}
|
|
for _, specID in ipairs (DF:GetClassSpecIDs (select (2, UnitClass ("player")))) do
|
|
local specID, specName, specDescription, specIcon, specBackground, specRole, specClass = DetailsFramework.GetSpecializationInfoByID (specID)
|
|
tinsert (specs, {
|
|
name = specName,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = specID,
|
|
get = function() return f.OptionsTable.spec [specID] or f.OptionsTable.spec [specID..""] end,
|
|
texture = specIcon,
|
|
})
|
|
end
|
|
local specGroup = DF:CreateRadionGroup (f, specs, name, {width = 200, height = 200, title = "Character Spec"}, {offset_x = 130, amount_per_line = 4})
|
|
specGroup:SetPoint ("topleft", f, "topleft", anchorPositions.spec [1], anchorPositions.spec [2])
|
|
specGroup.DBKey = "spec"
|
|
tinsert (f.AllRadioGroups, specGroup)
|
|
end
|
|
|
|
--create radio group for character races
|
|
local raceList = {}
|
|
for _, raceTable in ipairs (DF:GetCharacterRaceList()) do
|
|
tinsert (raceList, {
|
|
name = raceTable.Name,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = raceTable.FileString,
|
|
get = function() return f.OptionsTable.race [raceTable.FileString] end,
|
|
})
|
|
end
|
|
local raceGroup = DF:CreateRadionGroup (f, raceList, name, {width = 200, height = 200, title = "Character Race"})
|
|
raceGroup:SetPoint ("topleft", f, "topleft", anchorPositions.race [1], anchorPositions.race [2])
|
|
raceGroup.DBKey = "race"
|
|
tinsert (f.AllRadioGroups, raceGroup)
|
|
|
|
--create radio group for talents
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
local talentList = {}
|
|
for _, talentTable in ipairs (DF:GetCharacterTalents()) do
|
|
tinsert (talentList, {
|
|
name = talentTable.Name,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = talentTable.ID,
|
|
get = function() return f.OptionsTable.talent [talentTable.ID] or f.OptionsTable.talent [talentTable.ID .. ""] end,
|
|
texture = talentTable.Texture,
|
|
})
|
|
end
|
|
local talentGroup = DF:CreateRadionGroup (f, talentList, name, {width = 200, height = 200, title = "Characer Talents"}, {offset_x = 150, amount_per_line = 3})
|
|
talentGroup:SetPoint ("topleft", f, "topleft", anchorPositions.talent [1], anchorPositions.talent [2])
|
|
talentGroup.DBKey = "talent"
|
|
tinsert (f.AllRadioGroups, talentGroup)
|
|
f.TalentGroup = talentGroup
|
|
|
|
do
|
|
--create a frame to show talents selected in other specs or characters
|
|
local otherTalents = CreateFrame ("frame", nil, f, "BackdropTemplate")
|
|
otherTalents:SetSize (26, 26)
|
|
otherTalents:SetPoint ("left", talentGroup.Title.widget, "right", 10, -2)
|
|
otherTalents.Texture = DF:CreateImage (otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
|
|
otherTalents.Texture:SetAllPoints()
|
|
|
|
local removeTalent = function (_, _, talentID)
|
|
f.OptionsTable.talent [talentID] = nil
|
|
GameCooltip2:Hide()
|
|
f.OnRadioStateChanged (talentGroup, f.OptionsTable [talentGroup.DBKey])
|
|
f.CanShowTalentWarning()
|
|
end
|
|
|
|
local buildTalentMenu = function()
|
|
local playerTalents = DF:GetCharacterTalents()
|
|
local indexedTalents = {}
|
|
for _, talentTable in ipairs (playerTalents) do
|
|
tinsert (indexedTalents, talentTable.ID)
|
|
end
|
|
|
|
--talents selected to load
|
|
GameCooltip2:AddLine ("select a talent to remove it (added from a different spec or character)", "", 1, "orange", "orange", 9)
|
|
GameCooltip2:AddLine ("$div", nil, nil, -1, -1)
|
|
|
|
for talentID, _ in pairs (f.OptionsTable.talent) do
|
|
if (type (talentID) == "number" and not DF.table.find (indexedTalents, talentID)) then
|
|
local talentID, name, texture, selected, available = GetTalentInfoByID (talentID)
|
|
if (name) then
|
|
GameCooltip2:AddLine (name)
|
|
GameCooltip2:AddIcon (texture, 1, 1, 16, 16, .1, .9, .1, .9)
|
|
GameCooltip2:AddMenu (1, removeTalent, talentID)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
otherTalents.CoolTip = {
|
|
Type = "menu",
|
|
BuildFunc = buildTalentMenu,
|
|
OnEnterFunc = function (self) end,
|
|
OnLeaveFunc = function (self) end,
|
|
FixedValue = "none",
|
|
ShowSpeed = 0.05,
|
|
Options = function()
|
|
GameCooltip2:SetOption ("TextFont", "Friz Quadrata TT")
|
|
GameCooltip2:SetOption ("TextColor", "orange")
|
|
GameCooltip2:SetOption ("TextSize", 12)
|
|
GameCooltip2:SetOption ("FixedWidth", 220)
|
|
GameCooltip2:SetOption ("ButtonsYMod", -4)
|
|
GameCooltip2:SetOption ("YSpacingMod", -4)
|
|
GameCooltip2:SetOption ("IgnoreButtonAutoHeight", true)
|
|
|
|
GameCooltip2:SetColor (1, 0.5, 0.5, 0.5, 0)
|
|
|
|
local preset2_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
|
|
local gray_table = {0.37, 0.37, 0.37, 0.95}
|
|
local black_table = {0.2, 0.2, 0.2, 1}
|
|
GameCooltip2:SetBackdrop (1, preset2_backdrop, gray_table, black_table)
|
|
GameCooltip2:SetBackdrop (2, preset2_backdrop, gray_table, black_table)
|
|
end,
|
|
}
|
|
GameCooltip2:CoolTipInject (otherTalents)
|
|
|
|
function f.CanShowTalentWarning()
|
|
local playerTalents = DF:GetCharacterTalents()
|
|
local indexedTalents = {}
|
|
for _, talentTable in ipairs (playerTalents) do
|
|
tinsert (indexedTalents, talentTable.ID)
|
|
end
|
|
for talentID, _ in pairs (f.OptionsTable.talent) do
|
|
if (type (talentID) == "number" and not DF.table.find (indexedTalents, talentID)) then
|
|
otherTalents:Show()
|
|
return
|
|
end
|
|
end
|
|
otherTalents:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
--create radio group for pvp talents
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
local pvpTalentList = {}
|
|
for _, talentTable in ipairs (DF:GetCharacterPvPTalents()) do
|
|
tinsert (pvpTalentList, {
|
|
name = talentTable.Name,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = talentTable.ID,
|
|
get = function() return f.OptionsTable.pvptalent [talentTable.ID] or f.OptionsTable.pvptalent [talentTable.ID .. ""] end,
|
|
texture = talentTable.Texture,
|
|
})
|
|
end
|
|
local pvpTalentGroup = DF:CreateRadionGroup (f, pvpTalentList, name, {width = 200, height = 200, title = "Characer PvP Talents"}, {offset_x = 150, amount_per_line = 3})
|
|
pvpTalentGroup:SetPoint ("topleft", f, "topleft", anchorPositions.pvptalent [1], anchorPositions.pvptalent [2])
|
|
pvpTalentGroup.DBKey = "pvptalent"
|
|
tinsert (f.AllRadioGroups, pvpTalentGroup)
|
|
f.PvPTalentGroup = pvpTalentGroup
|
|
|
|
do
|
|
--create a frame to show talents selected in other specs or characters
|
|
local otherTalents = CreateFrame ("frame", nil, f, "BackdropTemplate")
|
|
otherTalents:SetSize (26, 26)
|
|
otherTalents:SetPoint ("left", pvpTalentGroup.Title.widget, "right", 10, -2)
|
|
otherTalents.Texture = DF:CreateImage (otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
|
|
otherTalents.Texture:SetAllPoints()
|
|
|
|
local removeTalent = function (_, _, talentID)
|
|
f.OptionsTable.pvptalent [talentID] = nil
|
|
GameCooltip2:Hide()
|
|
f.OnRadioStateChanged (pvpTalentGroup, f.OptionsTable [pvpTalentGroup.DBKey])
|
|
f.CanShowPvPTalentWarning()
|
|
end
|
|
|
|
local buildTalentMenu = function()
|
|
local playerTalents = DF:GetCharacterPvPTalents()
|
|
local indexedTalents = {}
|
|
for _, talentTable in ipairs (playerTalents) do
|
|
tinsert (indexedTalents, talentTable.ID)
|
|
end
|
|
|
|
--talents selected to load
|
|
GameCooltip2:AddLine ("select a talent to remove it (added from a different spec or character)", "", 1, "orange", "orange", 9)
|
|
GameCooltip2:AddLine ("$div", nil, nil, -1, -1)
|
|
|
|
for talentID, _ in pairs (f.OptionsTable.pvptalent) do
|
|
if (type (talentID) == "number" and not DF.table.find (indexedTalents, talentID)) then
|
|
local _, name, texture = GetPvpTalentInfoByID (talentID)
|
|
if (name) then
|
|
GameCooltip2:AddLine (name)
|
|
GameCooltip2:AddIcon (texture, 1, 1, 16, 16, .1, .9, .1, .9)
|
|
GameCooltip2:AddMenu (1, removeTalent, talentID)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
otherTalents.CoolTip = {
|
|
Type = "menu",
|
|
BuildFunc = buildTalentMenu,
|
|
OnEnterFunc = function (self) end,
|
|
OnLeaveFunc = function (self) end,
|
|
FixedValue = "none",
|
|
ShowSpeed = 0.05,
|
|
Options = function()
|
|
GameCooltip2:SetOption ("TextFont", "Friz Quadrata TT")
|
|
GameCooltip2:SetOption ("TextColor", "orange")
|
|
GameCooltip2:SetOption ("TextSize", 12)
|
|
GameCooltip2:SetOption ("FixedWidth", 220)
|
|
GameCooltip2:SetOption ("ButtonsYMod", -4)
|
|
GameCooltip2:SetOption ("YSpacingMod", -4)
|
|
GameCooltip2:SetOption ("IgnoreButtonAutoHeight", true)
|
|
|
|
GameCooltip2:SetColor (1, 0.5, 0.5, 0.5, 0)
|
|
|
|
local preset2_backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
|
|
local gray_table = {0.37, 0.37, 0.37, 0.95}
|
|
local black_table = {0.2, 0.2, 0.2, 1}
|
|
GameCooltip2:SetBackdrop (1, preset2_backdrop, gray_table, black_table)
|
|
GameCooltip2:SetBackdrop (2, preset2_backdrop, gray_table, black_table)
|
|
end,
|
|
}
|
|
GameCooltip2:CoolTipInject (otherTalents)
|
|
|
|
function f.CanShowPvPTalentWarning()
|
|
local playerTalents = DF:GetCharacterPvPTalents()
|
|
local indexedTalents = {}
|
|
for _, talentTable in ipairs (playerTalents) do
|
|
tinsert (indexedTalents, talentTable.ID)
|
|
end
|
|
for talentID, _ in pairs (f.OptionsTable.pvptalent) do
|
|
if (type (talentID) == "number" and not DF.table.find (indexedTalents, talentID)) then
|
|
otherTalents:Show()
|
|
return
|
|
end
|
|
end
|
|
otherTalents:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
--create radio for group types
|
|
local groupTypes = {}
|
|
for _, groupTable in ipairs (DF:GetGroupTypes()) do
|
|
tinsert (groupTypes, {
|
|
name = groupTable.Name,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = groupTable.ID,
|
|
get = function() return f.OptionsTable.group [groupTable.ID] or f.OptionsTable.group [groupTable.ID .. ""] end,
|
|
})
|
|
end
|
|
local groupTypesGroup = DF:CreateRadionGroup (f, groupTypes, name, {width = 200, height = 200, title = "Group Types"})
|
|
groupTypesGroup:SetPoint ("topleft", f, "topleft", anchorPositions.group [1], anchorPositions.group [2])
|
|
groupTypesGroup.DBKey = "group"
|
|
tinsert (f.AllRadioGroups, groupTypesGroup)
|
|
|
|
--create radio for character roles
|
|
local roleTypes = {}
|
|
for _, roleTable in ipairs (DF:GetRoleTypes()) do
|
|
tinsert (roleTypes, {
|
|
name = roleTable.Texture .. " " .. roleTable.Name,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = roleTable.ID,
|
|
get = function() return f.OptionsTable.role [roleTable.ID] or f.OptionsTable.role [roleTable.ID .. ""] end,
|
|
})
|
|
end
|
|
local roleTypesGroup = DF:CreateRadionGroup (f, roleTypes, name, {width = 200, height = 200, title = "Role Types"})
|
|
roleTypesGroup:SetPoint ("topleft", f, "topleft", anchorPositions.role [1], anchorPositions.role [2])
|
|
roleTypesGroup.DBKey = "role"
|
|
tinsert (f.AllRadioGroups, roleTypesGroup)
|
|
|
|
--create radio group for mythic+ affixes
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
local affixes = {}
|
|
for i = 2, 1000 do
|
|
local affixName, desc, texture = C_ChallengeMode.GetAffixInfo (i)
|
|
if (affixName) then
|
|
tinsert (affixes, {
|
|
name = affixName,
|
|
set = f.OnRadioCheckboxClick,
|
|
param = i,
|
|
get = function() return f.OptionsTable.affix [i] or f.OptionsTable.affix [i .. ""] end,
|
|
texture = texture,
|
|
})
|
|
end
|
|
end
|
|
local affixTypesGroup = DF:CreateRadionGroup (f, affixes, name, {width = 200, height = 200, title = "M+ Affixes"})
|
|
affixTypesGroup:SetPoint ("topleft", f, "topleft", anchorPositions.affix [1], anchorPositions.affix [2])
|
|
affixTypesGroup.DBKey = "affix"
|
|
tinsert (f.AllRadioGroups, affixTypesGroup)
|
|
end
|
|
|
|
--text entries functions
|
|
local textEntryRefresh = function (self)
|
|
local idList = f.OptionsTable [self.DBKey]
|
|
self:SetText ("")
|
|
for i = 1, #idList do
|
|
self:SetText (self:GetText() .. " " .. idList [i])
|
|
end
|
|
self:SetText (self:GetText():gsub ("^ ", ""))
|
|
end
|
|
|
|
local textEntryOnEnterPressed = function (_, self)
|
|
wipe (f.OptionsTable [self.DBKey])
|
|
local text = self:GetText()
|
|
|
|
for _, ID in ipairs ({strsplit ("", text)}) do
|
|
ID = DF:trim (ID)
|
|
ID = tonumber (ID)
|
|
if (ID) then
|
|
tinsert (f.OptionsTable [self.DBKey], ID)
|
|
f.OptionsTable [self.DBKey].Enabled = true
|
|
end
|
|
end
|
|
end
|
|
|
|
--create the text entry to type the encounter ID
|
|
local encounterIDLabel = DF:CreateLabel (f, "Encounter ID", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
local encounterIDEditbox = DF:CreateTextEntry (f, function()end, 200, 20, "EncounterEditbox", _, _, DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
|
encounterIDLabel:SetPoint ("topleft", f, "topleft", anchorPositions.encounter_ids [1], anchorPositions.encounter_ids [2])
|
|
encounterIDEditbox:SetPoint ("topleft", encounterIDLabel, "bottomleft", 0, -2)
|
|
encounterIDEditbox.DBKey = "encounter_ids"
|
|
encounterIDEditbox.Refresh = textEntryRefresh
|
|
encounterIDEditbox.tooltip = "Enter multiple IDs separating with a semicolon ()\nExample: 35 45 95\n\nUldir:\n"
|
|
for _, encounterTable in ipairs (DF:GetCLEncounterIDs()) do
|
|
encounterIDEditbox.tooltip = encounterIDEditbox.tooltip .. encounterTable.ID .. " - " .. encounterTable.Name .. "\n"
|
|
end
|
|
encounterIDEditbox:SetHook ("OnEnterPressed", textEntryOnEnterPressed)
|
|
tinsert (f.AllTextEntries, encounterIDEditbox)
|
|
|
|
--create the text entry for map ID
|
|
local mapIDLabel = DF:CreateLabel (f, "Map ID", DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
local mapIDEditbox = DF:CreateTextEntry (f, function()end, 200, 20, "MapEditbox", _, _, DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
|
mapIDLabel:SetPoint ("topleft", f, "topleft", anchorPositions.map_ids [1], anchorPositions.map_ids [2])
|
|
mapIDEditbox:SetPoint ("topleft", mapIDLabel, "bottomleft", 0, -2)
|
|
mapIDEditbox.DBKey = "map_ids"
|
|
mapIDEditbox.Refresh = textEntryRefresh
|
|
mapIDEditbox.tooltip = "Enter multiple IDs separating with a semicolon ()\nExample: 35 45 95"
|
|
mapIDEditbox:SetHook ("OnEnterPressed", textEntryOnEnterPressed)
|
|
tinsert (f.AllTextEntries, mapIDEditbox)
|
|
|
|
function f.Refresh (self)
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
--update the talents (might have changed if the player changed its specialization)
|
|
local talentList = {}
|
|
for _, talentTable in ipairs (DF:GetCharacterTalents()) do
|
|
tinsert (talentList, {
|
|
name = talentTable.Name,
|
|
set = DetailsFrameworkLoadConditionsPanel.OnRadioCheckboxClick,
|
|
param = talentTable.ID,
|
|
get = function() return DetailsFrameworkLoadConditionsPanel.OptionsTable.talent [talentTable.ID] or DetailsFrameworkLoadConditionsPanel.OptionsTable.talent [talentTable.ID .. ""] end,
|
|
texture = talentTable.Texture,
|
|
})
|
|
end
|
|
DetailsFrameworkLoadConditionsPanel.TalentGroup:SetOptions (talentList)
|
|
end
|
|
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
local pvpTalentList = {}
|
|
for _, talentTable in ipairs (DF:GetCharacterPvPTalents()) do
|
|
tinsert (pvpTalentList, {
|
|
name = talentTable.Name,
|
|
set = DetailsFrameworkLoadConditionsPanel.OnRadioCheckboxClick,
|
|
param = talentTable.ID,
|
|
get = function() return DetailsFrameworkLoadConditionsPanel.OptionsTable.pvptalent [talentTable.ID] or DetailsFrameworkLoadConditionsPanel.OptionsTable.pvptalent [talentTable.ID .. ""] end,
|
|
texture = talentTable.Texture,
|
|
})
|
|
end
|
|
DetailsFrameworkLoadConditionsPanel.PvPTalentGroup:SetOptions (pvpTalentList)
|
|
end
|
|
|
|
--refresh the radio group
|
|
for _, radioGroup in ipairs (DetailsFrameworkLoadConditionsPanel.AllRadioGroups) do
|
|
radioGroup:Refresh()
|
|
DetailsFrameworkLoadConditionsPanel.OnRadioStateChanged (radioGroup, DetailsFrameworkLoadConditionsPanel.OptionsTable [radioGroup.DBKey])
|
|
end
|
|
|
|
--refresh text entries
|
|
for _, textEntry in ipairs (DetailsFrameworkLoadConditionsPanel.AllTextEntries) do
|
|
textEntry:Refresh()
|
|
end
|
|
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
DetailsFrameworkLoadConditionsPanel.CanShowTalentWarning()
|
|
DetailsFrameworkLoadConditionsPanel.CanShowPvPTalentWarning()
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
--set the options table
|
|
DetailsFrameworkLoadConditionsPanel.OptionsTable = optionsTable
|
|
|
|
--set the callback func
|
|
DetailsFrameworkLoadConditionsPanel.CallbackFunc = callback
|
|
DetailsFrameworkLoadConditionsPanel.OptionsTable = optionsTable
|
|
|
|
--set title
|
|
DetailsFrameworkLoadConditionsPanel.EditingLabel:SetText (frameOptions.name)
|
|
DetailsFrameworkLoadConditionsPanel.Title:SetText (frameOptions.title)
|
|
|
|
--show the panel to the user
|
|
DetailsFrameworkLoadConditionsPanel:Show()
|
|
|
|
DetailsFrameworkLoadConditionsPanel:Refresh()
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> simple data scroll
|
|
|
|
DF.DataScrollFunctions = {
|
|
RefreshScroll = function (self, data, offset, totalLines)
|
|
local filter = self.Filter
|
|
local currentData = {}
|
|
if (type (filter) == "string" and filter ~= "") then
|
|
for i = 1, #data do
|
|
for o = 1, #data[i] do
|
|
if (data[i][o]:find (filter)) then
|
|
tinsert (currentData, data[i])
|
|
break
|
|
end
|
|
end
|
|
end
|
|
else
|
|
currentData = data
|
|
end
|
|
|
|
if (self.SortAlphabetical) then
|
|
table.sort (currentData, function(t1, t2) return t1[1] < t2[1] end)
|
|
end
|
|
|
|
--update the scroll
|
|
for i = 1, totalLines do
|
|
local index = i + offset
|
|
local thisData = currentData [index]
|
|
if (thisData) then
|
|
local line = self:GetLine (i)
|
|
line:Update (index, thisData)
|
|
end
|
|
end
|
|
end,
|
|
|
|
CreateLine = function (self, index)
|
|
--create a new line
|
|
local line = CreateFrame ("button", "$parentLine" .. index, self, "BackdropTemplate")
|
|
line.Update = self.options.update_line_func
|
|
|
|
--set its parameters
|
|
line:SetPoint ("topleft", self, "topleft", 1, -((index-1) * (self.options.line_height+1)) - 1)
|
|
line:SetSize (self.options.width - 2, self.options.line_height)
|
|
line:RegisterForClicks ("LeftButtonDown", "RightButtonDown")
|
|
|
|
line:SetScript ("OnEnter", self.options.on_enter)
|
|
line:SetScript ("OnLeave", self.options.on_leave)
|
|
line:SetScript ("OnClick", self.options.on_click)
|
|
|
|
line:SetBackdrop (self.options.backdrop)
|
|
line:SetBackdropColor (unpack (self.options.backdrop_color))
|
|
line:SetBackdropBorderColor (unpack (self.options.backdrop_border_color))
|
|
|
|
local title = DF:CreateLabel (line, "", DF:GetTemplate ("font", self.options.title_template))
|
|
local date = DF:CreateLabel (line, "", DF:GetTemplate ("font", self.options.title_template))
|
|
local text = DF:CreateLabel (line, "", DF:GetTemplate ("font", self.options.text_tempate))
|
|
|
|
title.textsize = 14
|
|
date.textsize = 14
|
|
text:SetSize (self.options.width - 20, self.options.line_height)
|
|
text:SetJustifyV ("top")
|
|
|
|
--setup anchors
|
|
if (self.options.show_title) then
|
|
title:SetPoint ("topleft", line, "topleft", 2, 0)
|
|
date:SetPoint ("topright", line, "topright", -2, 0)
|
|
text:SetPoint ("topleft", title, "bottomleft", 0, -4)
|
|
else
|
|
text:SetPoint ("topleft", line, "topleft", 2, 0)
|
|
end
|
|
|
|
line.Title = title
|
|
line.Date = date
|
|
line.Text = text
|
|
|
|
line.backdrop_color = self.options.backdrop_color or {.1, .1, .1, .3}
|
|
line.backdrop_color_highlight = self.options.backdrop_color_highlight or {.3, .3, .3, .5}
|
|
|
|
return line
|
|
end,
|
|
|
|
LineOnEnter = function (self)
|
|
self:SetBackdropColor (unpack (self.backdrop_color_highlight))
|
|
end,
|
|
LineOnLeave = function (self)
|
|
self:SetBackdropColor (unpack (self.backdrop_color))
|
|
end,
|
|
|
|
OnClick = function (self)
|
|
|
|
end,
|
|
|
|
UpdateLine = function (line, lineIndex, data)
|
|
local parent = line:GetParent()
|
|
|
|
if (parent.options.show_title) then
|
|
line.Title.text = data [2] or ""
|
|
line.Date.text = data [3] or ""
|
|
line.Text.text = data [4] or ""
|
|
else
|
|
line.Text.text = data [2] or ""
|
|
end
|
|
|
|
if (line:GetParent().OnUpdateLineHook) then
|
|
DF:CoreDispatch ((line:GetName() or "ScrollBoxDataScrollUpdateLineHook") .. ":UpdateLineHook()", line:GetParent().OnUpdateLineHook, line, lineIndex, data)
|
|
end
|
|
end,
|
|
}
|
|
|
|
local default_datascroll_options = {
|
|
width = 400,
|
|
height = 700,
|
|
line_amount = 10,
|
|
line_height = 20,
|
|
|
|
show_title = true,
|
|
|
|
backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
backdrop_color = {0, 0, 0, 0.2},
|
|
backdrop_color_highlight = {.2, .2, .2, 0.4},
|
|
backdrop_border_color = {0.1, 0.1, 0.1, .2},
|
|
|
|
title_template = "ORANGE_FONT_TEMPLATE",
|
|
text_tempate = "OPTIONS_FONT_TEMPLATE",
|
|
|
|
create_line_func = DF.DataScrollFunctions.CreateLine,
|
|
update_line_func = DF.DataScrollFunctions.UpdateLine,
|
|
refresh_func = DF.DataScrollFunctions.RefreshScroll,
|
|
on_enter = DF.DataScrollFunctions.LineOnEnter,
|
|
on_leave = DF.DataScrollFunctions.LineOnLeave,
|
|
on_click = DF.DataScrollFunctions.OnClick,
|
|
|
|
data = {},
|
|
}
|
|
|
|
--[=[
|
|
Create a scroll frame to show text in an organized way
|
|
Functions in the options table can be overritten to customize the layout
|
|
@parent = the parent of the frame
|
|
@name = the frame name to use in the CreateFrame call
|
|
@options = options table to override default values from the table above
|
|
--]=]
|
|
function DF:CreateDataScrollFrame (parent, name, options)
|
|
--call the mixin with a dummy table to built the default options before the frame creation
|
|
--this is done because CreateScrollBox needs parameters at creation time
|
|
local optionsTable = {}
|
|
DF.OptionsFunctions.BuildOptionsTable (optionsTable, default_datascroll_options, options)
|
|
optionsTable = optionsTable.options
|
|
|
|
--scroll frame
|
|
local newScroll = DF:CreateScrollBox (parent, name, optionsTable.refresh_func, optionsTable.data, optionsTable.width, optionsTable.height, optionsTable.line_amount, optionsTable.line_height)
|
|
DF:ReskinSlider (newScroll)
|
|
|
|
DF:Mixin (newScroll, DF.OptionsFunctions)
|
|
DF:Mixin (newScroll, DF.LayoutFrame)
|
|
|
|
newScroll:BuildOptionsTable (default_datascroll_options, options)
|
|
|
|
--create the scrollbox lines
|
|
for i = 1, newScroll.options.line_amount do
|
|
newScroll:CreateLine (newScroll.options.create_line_func)
|
|
end
|
|
|
|
newScroll:Refresh()
|
|
|
|
return newScroll
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> "WHAT's NEW" window
|
|
|
|
local default_newsframe_options = {
|
|
width = 400,
|
|
height = 700,
|
|
|
|
line_amount = 16,
|
|
line_height = 40,
|
|
|
|
backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
backdrop_color = {0, 0, 0, 0.2},
|
|
backdrop_border_color = {0.1, 0.1, 0.1, .2},
|
|
|
|
title = "What's New?",
|
|
show_title = true,
|
|
}
|
|
|
|
DF.NewsFrameFunctions = {
|
|
|
|
}
|
|
|
|
--[=[
|
|
Get the amount of news that the player didn't see yet
|
|
@newsTable = an indexed table of tables
|
|
@lastNewsTime = last time the player opened the news window
|
|
--]=]
|
|
function DF:GetNumNews (newsTable, lastNewsTime)
|
|
local now = time()
|
|
local nonReadNews = 0
|
|
|
|
for _, news in ipairs (newsTable) do
|
|
if (news[1] > lastNewsTime) then
|
|
nonReadNews = nonReadNews + 1
|
|
end
|
|
end
|
|
|
|
return nonReadNews
|
|
end
|
|
|
|
--[=[
|
|
Creates a panel with a scroll to show texts organized in separated lines
|
|
@parent = the parent of the frame
|
|
@name = the frame name to use in the CreateFrame call
|
|
@options = options table to override default values from the table above
|
|
@newsTable = an indexed table of tables
|
|
@db = (optional) an empty table from the addon database to store the position of the frame between game sessions
|
|
--]=]
|
|
function DF:CreateNewsFrame (parent, name, options, newsTable, db)
|
|
|
|
local f = DF:CreateSimplePanel (parent, 400, 700, options and options.title or default_newsframe_options.title, name, {UseScaleBar = db and true}, db)
|
|
f:SetFrameStrata ("MEDIUM")
|
|
DF:ApplyStandardBackdrop (f)
|
|
|
|
DF:Mixin (f, DF.OptionsFunctions)
|
|
DF:Mixin (f, DF.LayoutFrame)
|
|
|
|
f:BuildOptionsTable (default_newsframe_options, options)
|
|
|
|
f:SetSize (f.options.width, f.options.height)
|
|
f:SetBackdrop (f.options.backdrop)
|
|
f:SetBackdropColor (unpack (f.options.backdrop_color))
|
|
f:SetBackdropBorderColor (unpack (f.options.backdrop_border_color))
|
|
|
|
local scrollOptions = {
|
|
data = newsTable,
|
|
width = f.options.width - 32, --frame distance from walls and scroll bar space
|
|
height = f.options.height - 40 + (not f.options.show_title and 20 or 0),
|
|
line_amount = f.options.line_amount,
|
|
line_height = f.options.line_height,
|
|
}
|
|
local newsScroll = DF:CreateDataScrollFrame (f, "$parentScroll", scrollOptions)
|
|
|
|
if (not f.options.show_title) then
|
|
f.TitleBar:Hide()
|
|
newsScroll:SetPoint ("topleft", f, "topleft", 5, -10)
|
|
else
|
|
newsScroll:SetPoint ("topleft", f, "topleft", 5, -30)
|
|
end
|
|
|
|
f.NewsScroll = newsScroll
|
|
|
|
return f
|
|
end
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> statusbar info
|
|
|
|
--[[
|
|
authorTable = {
|
|
{
|
|
authorName = "author name 1",
|
|
link = "twitter.com/author1Handle",
|
|
}
|
|
}
|
|
]]
|
|
|
|
function DF:BuildStatusbarAuthorInfo (f, addonBy, authorsNameString)
|
|
local authorName = DF:CreateLabel (f, "" .. (addonBy or "An addon by") .. "|cFFFFFFFF" .. (authorsNameString or "Terciob") .. "|r")
|
|
authorName.textcolor = "silver"
|
|
local discordLabel = DF:CreateLabel (f, "Discord: ")
|
|
discordLabel.textcolor = "silver"
|
|
|
|
local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
|
|
local discordTextEntry = DF:CreateTextEntry (f, function()end, 200, 18, "DiscordTextBox", _, _, options_dropdown_template)
|
|
discordTextEntry:SetText ("https://discord.gg/AGSzAZX")
|
|
discordTextEntry:SetFrameLevel (5000)
|
|
|
|
authorName:SetPoint ("left", f, "left", 2, 0)
|
|
discordLabel:SetPoint ("left", authorName, "right", 20, 0)
|
|
discordTextEntry:SetPoint ("left", discordLabel, "right", 2, 0)
|
|
|
|
--format
|
|
authorName:SetAlpha (.4)
|
|
discordLabel:SetAlpha (.4)
|
|
discordTextEntry:SetAlpha (.4)
|
|
discordTextEntry:SetBackdropBorderColor (1, 1, 1, 0)
|
|
|
|
discordTextEntry:SetHook ("OnEditFocusGained", function()
|
|
discordTextEntry:HighlightText()
|
|
end)
|
|
|
|
f.authorName = authorName
|
|
f.discordLabel = discordLabel
|
|
f.discordTextEntry = discordTextEntry
|
|
end
|
|
|
|
local statusbar_default_options = {
|
|
attach = "bottom", --bottomleft from statusbar attach to bottomleft of the frame | other option is "top": topleft attach to bottomleft
|
|
}
|
|
|
|
function DF:CreateStatusBar(f, options)
|
|
local statusBar = CreateFrame ("frame", nil, f, "BackdropTemplate")
|
|
|
|
DF:Mixin (statusBar, DF.OptionsFunctions)
|
|
DF:Mixin (statusBar, DF.LayoutFrame)
|
|
|
|
statusBar:BuildOptionsTable (statusbar_default_options, options)
|
|
|
|
if (statusBar.options.attach == "bottom") then
|
|
statusBar:SetPoint ("bottomleft", f, "bottomleft")
|
|
statusBar:SetPoint ("bottomright", f, "bottomright")
|
|
|
|
else
|
|
statusBar:SetPoint ("topleft", f, "bottomleft")
|
|
statusBar:SetPoint ("topright", f, "bottomright")
|
|
end
|
|
|
|
statusBar:SetHeight (20)
|
|
DF:ApplyStandardBackdrop (statusBar)
|
|
statusBar:SetAlpha (0.8)
|
|
|
|
return statusBar
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> statusbar mixin
|
|
|
|
--[=[
|
|
collection of functions to embed into a statusbar
|
|
statusBar:GetTexture()
|
|
statusBar:SetTexture (texture)
|
|
statusBar:SetColor (unparsed color)
|
|
statusBar:GetColor()
|
|
statusBar:
|
|
statusBar:
|
|
|
|
--]=]
|
|
|
|
DF.StatusBarFunctions = {
|
|
|
|
GetTexture = function (self)
|
|
return self.barTexture:GetTexture()
|
|
end,
|
|
|
|
SetTexture = function (self, texture)
|
|
self.barTexture:SetTexture (texture)
|
|
end,
|
|
|
|
SetColor = function (self, r, g, b, a)
|
|
r, g, b, a = DF:ParseColors (r, g, b, a)
|
|
self:SetStatusBarColor (r, g, b, a)
|
|
end,
|
|
|
|
GetColor = function (self)
|
|
return self:GetStatusBarColor()
|
|
end,
|
|
|
|
}
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> health bar frame
|
|
|
|
--[=[
|
|
DF:CreateHealthBar (parent, name, settingsOverride)
|
|
creates a health bar to show an unit health
|
|
@parent = frame to pass for the CreateFrame function
|
|
@name = absolute name of the frame, if omitted it uses the parent's name .. "HealthBar"
|
|
@settingsOverride = table with keys and values to replace the defaults from the framework
|
|
|
|
methods:
|
|
healthbar:SetUnit (unit)
|
|
healthBar:GetTexture()
|
|
healthBar:SetTexture (texture)
|
|
--]=]
|
|
|
|
--debug performance isn't placed anywhere
|
|
--how to use debug performance: I don't remember
|
|
|
|
--Details:Dump (debugPerformance)
|
|
|
|
local debugPerformance = {
|
|
eventCall = {},
|
|
unitCall = {},
|
|
functionCall = {},
|
|
CPUUsageByFunction = {},
|
|
}
|
|
|
|
local function CalcPerformance (type, data)
|
|
if (type == "event") then
|
|
debugPerformance.eventCall [data] = (debugPerformance.eventCall [data] or 0) + 1
|
|
|
|
elseif (type == "unit") then
|
|
debugPerformance.unitCall [data] = (debugPerformance.unitCall [data] or 0) + 1
|
|
|
|
elseif (type == "call") then
|
|
debugPerformance.functionCall [data] = (debugPerformance.functionCall [data] or 0) + 1
|
|
|
|
end
|
|
end
|
|
|
|
function DF_CalcCpuUsage (name)
|
|
local cpu = debugPerformance.CPUUsageByFunction [name] or {usage = 0, last = 0, active = false}
|
|
debugPerformance.CPUUsageByFunction [name] = cpu
|
|
|
|
if (cpu.active) then
|
|
cpu.active = false
|
|
local diff = debugprofilestop() - cpu.last
|
|
cpu.usage = cpu.usage + diff
|
|
else
|
|
cpu.active = true
|
|
cpu.last = debugprofilestop()
|
|
end
|
|
end
|
|
|
|
function UnitFrameStats()
|
|
for functionName, functionTable in pairs (debugPerformance.CPUUsageByFunction) do
|
|
debugPerformance.CPUUsageByFunction [functionName] = floor (functionTable.usage)
|
|
end
|
|
|
|
for functionName, functionTable in pairs (debugPerformance.CPUUsageByFunction) do
|
|
debugPerformance.CPUUsageByFunction [functionName] = {usage = 0, last = 0, active = false}
|
|
end
|
|
end
|
|
--end of performance calcs
|
|
|
|
--healthBar meta prototype
|
|
local healthBarMetaPrototype = {
|
|
WidgetType = "healthBar",
|
|
SetHook = DF.SetHook,
|
|
RunHooksForWidget = DF.RunHooksForWidget,
|
|
|
|
dversion = DF.dversion,
|
|
}
|
|
|
|
--check if there's a metaPrototype already existing
|
|
if (_G[DF.GlobalWidgetControlNames["healthBar"]]) then
|
|
--get the already existing metaPrototype
|
|
local oldMetaPrototype = _G[DF.GlobalWidgetControlNames ["healthBar"]]
|
|
--check if is older
|
|
if ( (not oldMetaPrototype.dversion) or (oldMetaPrototype.dversion < DF.dversion) ) then
|
|
--the version is older them the currently loading one
|
|
--copy the new values into the old metatable
|
|
for funcName, _ in pairs(healthBarMetaPrototype) do
|
|
oldMetaPrototype[funcName] = healthBarMetaPrototype[funcName]
|
|
end
|
|
end
|
|
else
|
|
--first time loading the framework
|
|
_G[DF.GlobalWidgetControlNames ["healthBar"]] = healthBarMetaPrototype
|
|
end
|
|
|
|
local healthBarMetaFunctions = _G[DF.GlobalWidgetControlNames ["healthBar"]]
|
|
|
|
--hook list
|
|
local defaultHooksForHealthBar = {
|
|
OnHide = {},
|
|
OnShow = {},
|
|
OnHealthChange = {},
|
|
OnHealthMaxChange = {},
|
|
}
|
|
|
|
--use the hook already existing
|
|
healthBarMetaFunctions.HookList = healthBarMetaFunctions.HookList or defaultHooksForHealthBar
|
|
--copy the non existing values from a new version to the already existing hook table
|
|
DF.table.deploy (healthBarMetaFunctions.HookList, defaultHooksForHealthBar)
|
|
|
|
--> Health Bar Meta Functions
|
|
|
|
--health bar settings
|
|
healthBarMetaFunctions.Settings = {
|
|
CanTick = false, --> if true calls the method 'OnTick' every tick, the function needs to be overloaded, it receives self and deltaTime as parameters
|
|
ShowHealingPrediction = true, --> when casting a healing pass, show the amount of health that spell will heal
|
|
ShowShields = true, --> indicator of the amount of damage absortion the unit has
|
|
|
|
--appearance
|
|
BackgroundColor = DF:CreateColorTable (.2, .2, .2, .8),
|
|
Texture = [[Interface\RaidFrame\Raid-Bar-Hp-Fill]],
|
|
ShieldIndicatorTexture = [[Interface\RaidFrame\Shield-Fill]],
|
|
ShieldGlowTexture = [[Interface\RaidFrame\Shield-Overshield]],
|
|
ShieldGlowWidth = 16,
|
|
|
|
--default size
|
|
Width = 100,
|
|
Height = 20,
|
|
}
|
|
|
|
healthBarMetaFunctions.HealthBarEvents = {
|
|
{"PLAYER_ENTERING_WORLD"},
|
|
{"UNIT_HEALTH", true},
|
|
{"UNIT_MAXHEALTH", true},
|
|
{(IS_WOW_PROJECT_NOT_MAINLINE) and "UNIT_HEALTH_FREQUENT", true}, -- this one is classic-only...
|
|
{(IS_WOW_PROJECT_MAINLINE) and "UNIT_HEAL_PREDICTION", true},
|
|
{(IS_WOW_PROJECT_MAINLINE) and "UNIT_ABSORB_AMOUNT_CHANGED", true},
|
|
{(IS_WOW_PROJECT_MAINLINE) and "UNIT_HEAL_ABSORB_AMOUNT_CHANGED", true},
|
|
}
|
|
|
|
--> setup the castbar to be used by another unit
|
|
healthBarMetaFunctions.SetUnit = function (self, unit, displayedUnit)
|
|
if (self.unit ~= unit or self.displayedUnit ~= displayedUnit or unit == nil) then
|
|
|
|
self.unit = unit
|
|
self.displayedUnit = displayedUnit or unit
|
|
|
|
--> register events
|
|
if (unit) then
|
|
self.currentHealth = UnitHealth (unit) or 0
|
|
self.currentHealthMax = UnitHealthMax (unit) or 0
|
|
|
|
for _, eventTable in ipairs (self.HealthBarEvents) do
|
|
local event = eventTable [1]
|
|
local isUnitEvent = eventTable [2]
|
|
if event then
|
|
if (isUnitEvent) then
|
|
self:RegisterUnitEvent (event, self.displayedUnit, self.unit)
|
|
else
|
|
self:RegisterEvent (event)
|
|
end
|
|
end
|
|
end
|
|
|
|
--> check for settings and update some events
|
|
if (not self.Settings.ShowHealingPrediction) then
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
self:UnregisterEvent ("UNIT_HEAL_PREDICTION")
|
|
self:UnregisterEvent ("UNIT_HEAL_ABSORB_AMOUNT_CHANGED")
|
|
end
|
|
self.incomingHealIndicator:Hide()
|
|
self.healAbsorbIndicator:Hide()
|
|
end
|
|
if (not self.Settings.ShowShields) then
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
self:UnregisterEvent ("UNIT_ABSORB_AMOUNT_CHANGED")
|
|
end
|
|
self.shieldAbsorbIndicator:Hide()
|
|
self.shieldAbsorbGlow:Hide()
|
|
end
|
|
|
|
--> set scripts
|
|
self:SetScript ("OnEvent", self.OnEvent)
|
|
|
|
if (self.Settings.CanTick) then
|
|
self:SetScript ("OnUpdate", self.OnTick)
|
|
end
|
|
|
|
self:PLAYER_ENTERING_WORLD (self.unit, self.displayedUnit)
|
|
else
|
|
--> remove all registered events
|
|
for _, eventTable in ipairs (self.HealthBarEvents) do
|
|
local event = eventTable [1]
|
|
if event then
|
|
self:UnregisterEvent (event)
|
|
end
|
|
end
|
|
|
|
--> remove scripts
|
|
self:SetScript ("OnEvent", nil)
|
|
self:SetScript ("OnUpdate", nil)
|
|
self:Hide()
|
|
end
|
|
end
|
|
end
|
|
|
|
healthBarMetaFunctions.Initialize = function (self)
|
|
PixelUtil.SetWidth (self, self.Settings.Width, 1)
|
|
PixelUtil.SetHeight (self, self.Settings.Height, 1)
|
|
|
|
self:SetTexture (self.Settings.Texture)
|
|
|
|
self.background:SetAllPoints()
|
|
self.background:SetColorTexture (self.Settings.BackgroundColor:GetColor())
|
|
|
|
--setpoint of these widgets are set inside the function that updates the incoming heal
|
|
self.incomingHealIndicator:SetTexture (self:GetTexture())
|
|
self.healAbsorbIndicator:SetTexture (self:GetTexture())
|
|
self.healAbsorbIndicator:SetVertexColor (.1, .8, .8)
|
|
self.shieldAbsorbIndicator:SetTexture (self.Settings.ShieldIndicatorTexture, true, true)
|
|
|
|
self.shieldAbsorbGlow:SetWidth (self.Settings.ShieldGlowWidth)
|
|
self.shieldAbsorbGlow:SetTexture (self.Settings.ShieldGlowTexture)
|
|
self.shieldAbsorbGlow:SetBlendMode ("ADD")
|
|
self.shieldAbsorbGlow:SetPoint ("topright", self, "topright", 8, 0)
|
|
self.shieldAbsorbGlow:SetPoint ("bottomright", self, "bottomright", 8, 0)
|
|
self.shieldAbsorbGlow:Hide()
|
|
|
|
self:SetUnit (nil)
|
|
end
|
|
|
|
--call every tick
|
|
healthBarMetaFunctions.OnTick = function (self, deltaTime) end --if overrided, set 'CanTick' to true on the settings table
|
|
|
|
--when an event happen for this unit, send it to the apropriate function
|
|
healthBarMetaFunctions.OnEvent = function (self, event, ...)
|
|
local eventFunc = self [event]
|
|
if (eventFunc) then
|
|
--the function doesn't receive which event was, only 'self' and the parameters
|
|
eventFunc (self, ...)
|
|
end
|
|
end
|
|
|
|
--when the unit max health is changed
|
|
healthBarMetaFunctions.UpdateMaxHealth = function (self)
|
|
local maxHealth = UnitHealthMax (self.displayedUnit)
|
|
self:SetMinMaxValues (0, maxHealth)
|
|
self.currentHealthMax = maxHealth
|
|
|
|
self:RunHooksForWidget ("OnHealthMaxChange", self, self.displayedUnit)
|
|
end
|
|
|
|
healthBarMetaFunctions.UpdateHealth = function (self)
|
|
-- update max health regardless to avoid weird wrong values on UpdateMaxHealth sometimes
|
|
-- local maxHealth = UnitHealthMax (self.displayedUnit)
|
|
-- self:SetMinMaxValues (0, maxHealth)
|
|
-- self.currentHealthMax = maxHealth
|
|
|
|
local health = UnitHealth (self.displayedUnit)
|
|
self.currentHealth = health
|
|
PixelUtil.SetStatusBarValue (self, health)
|
|
|
|
self:RunHooksForWidget ("OnHealthChange", self, self.displayedUnit)
|
|
end
|
|
|
|
--health and absorbs prediction
|
|
healthBarMetaFunctions.UpdateHealPrediction = function (self)
|
|
if IS_WOW_PROJECT_NOT_MAINLINE then return end
|
|
local currentHealth = self.currentHealth
|
|
local currentHealthMax = self.currentHealthMax
|
|
local healthPercent = currentHealth / currentHealthMax
|
|
|
|
if (not currentHealthMax or currentHealthMax <= 0) then
|
|
return
|
|
end
|
|
|
|
--order is: the health of the unit > damage absorb > heal absorb > incoming heal
|
|
local width = self:GetWidth()
|
|
|
|
if (self.Settings.ShowHealingPrediction) then
|
|
--incoming heal on the unit from all sources
|
|
local unitHealIncoming = self.displayedUnit and UnitGetIncomingHeals (self.displayedUnit) or 0
|
|
--heal absorbs
|
|
local unitHealAbsorb = self.displayedUnit and UnitGetTotalHealAbsorbs (self.displayedUnit) or 0
|
|
|
|
if (unitHealIncoming > 0) then
|
|
--calculate what is the percent of health incoming based on the max health the player has
|
|
local incomingPercent = unitHealIncoming / currentHealthMax
|
|
self.incomingHealIndicator:Show()
|
|
self.incomingHealIndicator:SetWidth (max (1, min (width * incomingPercent, abs (healthPercent - 1) * width)))
|
|
self.incomingHealIndicator:SetPoint ("topleft", self, "topleft", width * healthPercent, 0)
|
|
self.incomingHealIndicator:SetPoint ("bottomleft", self, "bottomleft", width * healthPercent, 0)
|
|
else
|
|
self.incomingHealIndicator:Hide()
|
|
end
|
|
|
|
if (unitHealAbsorb > 0) then
|
|
local healAbsorbPercent = unitHealAbsorb / currentHealthMax
|
|
self.healAbsorbIndicator:Show()
|
|
self.healAbsorbIndicator:SetWidth (max (1, min (width * healAbsorbPercent, abs (healthPercent - 1) * width)))
|
|
self.healAbsorbIndicator:SetPoint ("topleft", self, "topleft", width * healthPercent, 0)
|
|
self.healAbsorbIndicator:SetPoint ("bottomleft", self, "bottomleft", width * healthPercent, 0)
|
|
else
|
|
self.healAbsorbIndicator:Hide()
|
|
end
|
|
end
|
|
|
|
if (self.Settings.ShowShields) then
|
|
--damage absorbs
|
|
local unitDamageAbsorb = self.displayedUnit and UnitGetTotalAbsorbs (self.displayedUnit) or 0
|
|
|
|
if (unitDamageAbsorb > 0) then
|
|
local damageAbsorbPercent = unitDamageAbsorb / currentHealthMax
|
|
self.shieldAbsorbIndicator:Show()
|
|
--set the width where the max width size is what is lower: the absorb size or the missing amount of health in the health bar
|
|
--/dump NamePlate1PlaterUnitFrameHealthBar.shieldAbsorbIndicator:GetSize()
|
|
self.shieldAbsorbIndicator:SetWidth (max (1, min (width * damageAbsorbPercent, abs (healthPercent - 1) * width)))
|
|
self.shieldAbsorbIndicator:SetPoint ("topleft", self, "topleft", width * healthPercent, 0)
|
|
self.shieldAbsorbIndicator:SetPoint ("bottomleft", self, "bottomleft", width * healthPercent, 0)
|
|
|
|
--if the absorb percent pass 100%, show the glow
|
|
if ((healthPercent + damageAbsorbPercent) > 1) then
|
|
self.shieldAbsorbGlow:Show()
|
|
else
|
|
self.shieldAbsorbGlow:Hide()
|
|
end
|
|
else
|
|
self.shieldAbsorbIndicator:Hide()
|
|
self.shieldAbsorbGlow:Hide()
|
|
end
|
|
else
|
|
self.shieldAbsorbIndicator:Hide()
|
|
self.shieldAbsorbGlow:Hide()
|
|
end
|
|
end
|
|
|
|
--> Health Events
|
|
healthBarMetaFunctions.PLAYER_ENTERING_WORLD = function (self, ...)
|
|
self:UpdateMaxHealth()
|
|
self:UpdateHealth()
|
|
self:UpdateHealPrediction()
|
|
end
|
|
|
|
healthBarMetaFunctions.UNIT_HEALTH = function (self, ...)
|
|
self:UpdateHealth()
|
|
self:UpdateHealPrediction()
|
|
end
|
|
|
|
healthBarMetaFunctions.UNIT_HEALTH_FREQUENT = function (self, ...)
|
|
self:UpdateHealth()
|
|
self:UpdateHealPrediction()
|
|
end
|
|
|
|
healthBarMetaFunctions.UNIT_MAXHEALTH = function (self, ...)
|
|
self:UpdateMaxHealth()
|
|
self:UpdateHealth()
|
|
self:UpdateHealPrediction()
|
|
end
|
|
|
|
|
|
healthBarMetaFunctions.UNIT_HEAL_PREDICTION = function (self, ...)
|
|
self:UpdateMaxHealth()
|
|
self:UpdateHealth()
|
|
self:UpdateHealPrediction()
|
|
end
|
|
|
|
healthBarMetaFunctions.UNIT_ABSORB_AMOUNT_CHANGED = function (self, ...)
|
|
self:UpdateMaxHealth()
|
|
self:UpdateHealth()
|
|
self:UpdateHealPrediction()
|
|
end
|
|
|
|
healthBarMetaFunctions.UNIT_HEAL_ABSORB_AMOUNT_CHANGED = function (self, ...)
|
|
self:UpdateMaxHealth()
|
|
self:UpdateHealth()
|
|
self:UpdateHealPrediction()
|
|
end
|
|
|
|
|
|
-- ~healthbar
|
|
function DF:CreateHealthBar (parent, name, settingsOverride)
|
|
|
|
assert (name or parent:GetName(), "DetailsFramework:CreateHealthBar parameter 'name' omitted and parent has no name.")
|
|
|
|
local healthBar = CreateFrame ("StatusBar", name or (parent:GetName() .. "HealthBar"), parent, "BackdropTemplate")
|
|
do --layers
|
|
--background
|
|
healthBar.background = healthBar:CreateTexture (nil, "background")
|
|
healthBar.background:SetDrawLayer ("background", -6)
|
|
|
|
--artwork
|
|
--healing incoming
|
|
healthBar.incomingHealIndicator = healthBar:CreateTexture (nil, "artwork")
|
|
healthBar.incomingHealIndicator:SetDrawLayer ("artwork", 4)
|
|
--current shields on the unit
|
|
healthBar.shieldAbsorbIndicator = healthBar:CreateTexture (nil, "artwork")
|
|
healthBar.shieldAbsorbIndicator:SetDrawLayer ("artwork", 5)
|
|
--debuff absorbing heal
|
|
healthBar.healAbsorbIndicator = healthBar:CreateTexture (nil, "artwork")
|
|
healthBar.healAbsorbIndicator:SetDrawLayer ("artwork", 6)
|
|
--the shield fills all the bar, show that cool glow
|
|
healthBar.shieldAbsorbGlow = healthBar:CreateTexture (nil, "artwork")
|
|
healthBar.shieldAbsorbGlow:SetDrawLayer ("artwork", 7)
|
|
--statusbar texture
|
|
healthBar.barTexture = healthBar:CreateTexture (nil, "artwork")
|
|
healthBar:SetStatusBarTexture (healthBar.barTexture)
|
|
end
|
|
|
|
--> mixins
|
|
DF:Mixin (healthBar, healthBarMetaFunctions)
|
|
DF:Mixin (healthBar, DF.StatusBarFunctions)
|
|
|
|
--> settings and hooks
|
|
local settings = DF.table.copy ({}, healthBarMetaFunctions.Settings)
|
|
if (settingsOverride) then
|
|
DF.table.copy (settings, settingsOverride)
|
|
end
|
|
healthBar.Settings = settings
|
|
|
|
--> hook list
|
|
healthBar.HookList = DF.table.copy ({}, healthBarMetaFunctions.HookList)
|
|
|
|
--> initialize the cast bar
|
|
healthBar:Initialize()
|
|
|
|
return healthBar
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> power bar frame
|
|
|
|
--[=[
|
|
DF:CreatePowerBar (parent, name, settingsOverride)
|
|
creates statusbar frame to show the unit power bar
|
|
@parent = frame to pass for the CreateFrame function
|
|
@name = absolute name of the frame, if omitted it uses the parent's name .. "PPowerBar"
|
|
@settingsOverride = table with keys and values to replace the defaults from the framework
|
|
--]=]
|
|
|
|
DF.PowerFrameFunctions = {
|
|
|
|
WidgetType = "powerBar",
|
|
SetHook = DF.SetHook,
|
|
RunHooksForWidget = DF.RunHooksForWidget,
|
|
|
|
HookList = {
|
|
OnHide = {},
|
|
OnShow = {},
|
|
},
|
|
|
|
Settings = {
|
|
--> misc
|
|
ShowAlternatePower = true, --> if true it'll show alternate power over the regular power the unit uses
|
|
ShowPercentText = true, --> if true show a text with the current energy percent
|
|
HideIfNoPower = true, --> if true and the UnitMaxPower returns zero, it'll hide the power bar with self:Hide()
|
|
CanTick = false, --> if it calls the OnTick function every tick
|
|
|
|
--appearance
|
|
BackgroundColor = DF:CreateColorTable (.2, .2, .2, .8),
|
|
Texture = [[Interface\RaidFrame\Raid-Bar-Resource-Fill]],
|
|
|
|
--> default size
|
|
Width = 100,
|
|
Height = 20,
|
|
},
|
|
|
|
PowerBarEvents = {
|
|
{"PLAYER_ENTERING_WORLD"},
|
|
{"UNIT_DISPLAYPOWER", true},
|
|
{"UNIT_POWER_BAR_SHOW", true},
|
|
{"UNIT_POWER_BAR_HIDE", true},
|
|
{"UNIT_MAXPOWER", true},
|
|
{"UNIT_POWER_UPDATE", true},
|
|
{"UNIT_POWER_FREQUENT", true},
|
|
},
|
|
|
|
--> setup the castbar to be used by another unit
|
|
SetUnit = function (self, unit, displayedUnit)
|
|
if (self.unit ~= unit or self.displayedUnit ~= displayedUnit or unit == nil) then
|
|
self.unit = unit
|
|
self.displayedUnit = displayedUnit or unit
|
|
|
|
--> register events
|
|
if (unit) then
|
|
for _, eventTable in ipairs (self.PowerBarEvents) do
|
|
local event = eventTable [1]
|
|
local isUnitEvent = eventTable [2]
|
|
|
|
if (isUnitEvent) then
|
|
self:RegisterUnitEvent (event, self.displayedUnit)
|
|
else
|
|
self:RegisterEvent (event)
|
|
end
|
|
end
|
|
|
|
--> set scripts
|
|
self:SetScript ("OnEvent", self.OnEvent)
|
|
|
|
if (self.Settings.CanTick) then
|
|
self:SetScript ("OnUpdate", self.OnTick)
|
|
end
|
|
|
|
self:Show()
|
|
self:UpdatePowerBar()
|
|
else
|
|
--> remove all registered events
|
|
for _, eventTable in ipairs (self.PowerBarEvents) do
|
|
local event = eventTable [1]
|
|
self:UnregisterEvent (event)
|
|
end
|
|
|
|
--> remove scripts
|
|
self:SetScript ("OnEvent", nil)
|
|
self:SetScript ("OnUpdate", nil)
|
|
self:Hide()
|
|
end
|
|
end
|
|
end,
|
|
|
|
Initialize = function (self)
|
|
PixelUtil.SetWidth (self, self.Settings.Width)
|
|
PixelUtil.SetHeight (self, self.Settings.Height)
|
|
|
|
self:SetTexture (self.Settings.Texture)
|
|
|
|
self.background:SetAllPoints()
|
|
self.background:SetColorTexture (self.Settings.BackgroundColor:GetColor())
|
|
|
|
if (self.Settings.ShowPercentText) then
|
|
self.percentText:Show()
|
|
PixelUtil.SetPoint (self.percentText, "center", self, "center", 0, 0)
|
|
|
|
DF:SetFontSize (self.percentText, 9)
|
|
DF:SetFontColor (self.percentText, "white")
|
|
DF:SetFontOutline (self.percentText, "OUTLINE")
|
|
else
|
|
self.percentText:Hide()
|
|
end
|
|
|
|
self:SetUnit (nil)
|
|
end,
|
|
|
|
--> call every tick
|
|
OnTick = function (self, deltaTime) end, --if overrided, set 'CanTick' to true on the settings table
|
|
|
|
--> when an event happen for this unit, send it to the apropriate function
|
|
OnEvent = function (self, event, ...)
|
|
local eventFunc = self [event]
|
|
if (eventFunc) then
|
|
--the function doesn't receive which event was, only 'self' and the parameters
|
|
eventFunc (self, ...)
|
|
end
|
|
end,
|
|
|
|
UpdatePowerBar = function (self)
|
|
self:UpdatePowerInfo()
|
|
self:UpdateMaxPower()
|
|
self:UpdatePower()
|
|
self:UpdatePowerColor()
|
|
end,
|
|
|
|
--> power update
|
|
UpdateMaxPower = function (self)
|
|
self.currentPowerMax = UnitPowerMax (self.displayedUnit, self.powerType)
|
|
self:SetMinMaxValues (self.minPower, self.currentPowerMax)
|
|
|
|
if (self.currentPowerMax == 0 and self.Settings.HideIfNoPower) then
|
|
self:Hide()
|
|
end
|
|
end,
|
|
UpdatePower = function (self)
|
|
self.currentPower = UnitPower (self.displayedUnit, self.powerType)
|
|
PixelUtil.SetStatusBarValue (self, self.currentPower)
|
|
|
|
if (self.Settings.ShowPercentText) then
|
|
self.percentText:SetText (floor (self.currentPower / self.currentPowerMax * 100) .. "%")
|
|
end
|
|
end,
|
|
|
|
--> when a event different from unit_power_update is triggered, update which type of power the unit should show
|
|
UpdatePowerInfo = function (self)
|
|
if (IS_WOW_PROJECT_MAINLINE and self.Settings.ShowAlternatePower) then -- not available in classic
|
|
local barID = UnitPowerBarID(self.displayedUnit)
|
|
local barInfo = GetUnitPowerBarInfoByID(barID)
|
|
--local name, tooltip, cost = GetUnitPowerBarStringsByID(barID);
|
|
--barInfo.barType,barInfo.minPower, barInfo.startInset, barInfo.endInset, barInfo.smooth, barInfo.hideFromOthers, barInfo.showOnRaid, barInfo.opaqueSpark, barInfo.opaqueFlash, barInfo.anchorTop, name, tooltip, cost, barInfo.ID, barInfo.forcePercentage, barInfo.sparkUnderFrame;
|
|
if (barInfo and barInfo.showOnRaid and IsInGroup()) then
|
|
self.powerType = ALTERNATE_POWER_INDEX
|
|
self.minPower = barInfo.minPower
|
|
return
|
|
end
|
|
end
|
|
|
|
self.powerType = UnitPowerType (self.displayedUnit)
|
|
self.minPower = 0
|
|
end,
|
|
|
|
--> tint the bar with the color of the power, e.g. blue for a mana bar
|
|
UpdatePowerColor = function (self)
|
|
if (not UnitIsConnected (self.unit)) then
|
|
self:SetStatusBarColor (.5, .5, .5)
|
|
return
|
|
end
|
|
|
|
if (self.powerType == ALTERNATE_POWER_INDEX) then
|
|
--> don't change this, keep the same color as the game tints on CompactUnitFrame.lua
|
|
self:SetStatusBarColor (0.7, 0.7, 0.6)
|
|
return
|
|
end
|
|
|
|
local powerColor = PowerBarColor [self.powerType] --> don't appear to be, but PowerBarColor is a global table with all power colors /run Details:Dump (PowerBarColor)
|
|
if (powerColor) then
|
|
self:SetStatusBarColor (powerColor.r, powerColor.g, powerColor.b)
|
|
return
|
|
end
|
|
|
|
local _, _, r, g, b = UnitPowerType (self.displayedUnit)
|
|
if (r) then
|
|
self:SetStatusBarColor (r, g, b)
|
|
return
|
|
end
|
|
|
|
--> if everything else fails, tint as rogue energy
|
|
powerColor = PowerBarColor ["ENERGY"]
|
|
self:SetStatusBarColor (powerColor.r, powerColor.g, powerColor.b)
|
|
end,
|
|
|
|
--> events
|
|
PLAYER_ENTERING_WORLD = function (self, ...)
|
|
self:UpdatePowerBar()
|
|
end,
|
|
UNIT_DISPLAYPOWER = function (self, ...)
|
|
self:UpdatePowerBar()
|
|
end,
|
|
UNIT_POWER_BAR_SHOW = function (self, ...)
|
|
self:UpdatePowerBar()
|
|
end,
|
|
UNIT_POWER_BAR_HIDE = function (self, ...)
|
|
self:UpdatePowerBar()
|
|
end,
|
|
|
|
UNIT_MAXPOWER = function (self, ...)
|
|
self:UpdateMaxPower()
|
|
self:UpdatePower()
|
|
end,
|
|
UNIT_POWER_UPDATE = function (self, ...)
|
|
self:UpdatePower()
|
|
end,
|
|
UNIT_POWER_FREQUENT = function (self, ...)
|
|
self:UpdatePower()
|
|
end,
|
|
}
|
|
|
|
-- ~powerbar
|
|
function DF:CreatePowerBar (parent, name, settingsOverride)
|
|
|
|
assert (name or parent:GetName(), "DetailsFramework:CreatePowerBar parameter 'name' omitted and parent has no name.")
|
|
|
|
local powerBar = CreateFrame ("StatusBar", name or (parent:GetName() .. "PowerBar"), parent, "BackdropTemplate")
|
|
do --layers
|
|
--background
|
|
powerBar.background = powerBar:CreateTexture (nil, "background")
|
|
powerBar.background:SetDrawLayer ("background", -6)
|
|
|
|
--artwork
|
|
powerBar.barTexture = powerBar:CreateTexture (nil, "artwork")
|
|
powerBar:SetStatusBarTexture (powerBar.barTexture)
|
|
|
|
--overlay
|
|
powerBar.percentText = powerBar:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
end
|
|
|
|
--> mixins
|
|
DF:Mixin (powerBar, DF.PowerFrameFunctions)
|
|
DF:Mixin (powerBar, DF.StatusBarFunctions)
|
|
|
|
--> settings and hooks
|
|
local settings = DF.table.copy ({}, DF.PowerFrameFunctions.Settings)
|
|
if (settingsOverride) then
|
|
DF.table.copy (settings, settingsOverride)
|
|
end
|
|
powerBar.Settings = settings
|
|
|
|
local hookList = DF.table.copy ({}, DF.PowerFrameFunctions.HookList)
|
|
powerBar.HookList = hookList
|
|
|
|
--> initialize the cast bar
|
|
powerBar:Initialize()
|
|
|
|
return powerBar
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> cast bar frame
|
|
|
|
--[=[
|
|
DF:CreateCastBar (parent, name, settingsOverride)
|
|
creates a cast bar to show an unit cast
|
|
@parent = frame to pass for the CreateFrame function
|
|
@name = absolute name of the frame, if omitted it uses the parent's name .. "CastBar"
|
|
@settingsOverride = table with keys and values to replace the defaults from the framework
|
|
--]=]
|
|
|
|
DF.CastFrameFunctions = {
|
|
|
|
WidgetType = "castBar",
|
|
SetHook = DF.SetHook,
|
|
RunHooksForWidget = DF.RunHooksForWidget,
|
|
|
|
HookList = {
|
|
OnHide = {},
|
|
OnShow = {},
|
|
|
|
--can be regular cast or channel
|
|
OnCastStart = {},
|
|
},
|
|
|
|
CastBarEvents = {
|
|
{"UNIT_SPELLCAST_INTERRUPTED"},
|
|
{"UNIT_SPELLCAST_DELAYED"},
|
|
{"UNIT_SPELLCAST_CHANNEL_START"},
|
|
{"UNIT_SPELLCAST_CHANNEL_UPDATE"},
|
|
{"UNIT_SPELLCAST_CHANNEL_STOP"},
|
|
{(IS_WOW_PROJECT_MAINLINE) and "UNIT_SPELLCAST_INTERRUPTIBLE"},
|
|
{(IS_WOW_PROJECT_MAINLINE) and "UNIT_SPELLCAST_NOT_INTERRUPTIBLE"},
|
|
{"PLAYER_ENTERING_WORLD"},
|
|
{"UNIT_SPELLCAST_START", true},
|
|
{"UNIT_SPELLCAST_STOP", true},
|
|
{"UNIT_SPELLCAST_FAILED", true},
|
|
},
|
|
|
|
Settings = {
|
|
NoFadeEffects = false, --if true it won't play fade effects when a cast if finished
|
|
ShowTradeSkills = false, --if true, it shows cast for trade skills, e.g. creating an icon with blacksmith
|
|
ShowShield = true, --if true, shows the shield above the spell icon for non interruptible casts
|
|
CanTick = true, --if true it will run its OnTick function every tick.
|
|
ShowCastTime = true, --if true, show the remaining time to finish the cast, lazy tick must be enabled
|
|
FadeInTime = 0.1, --amount of time in seconds to go from zero to 100% alpha when starting to cast
|
|
FadeOutTime = 0.5, --amount of time in seconds to go from 100% to zero alpha when the cast finishes
|
|
CanLazyTick = true, --if true, it'll execute the lazy tick function, it ticks in a much slower pace comparece with the regular tick
|
|
LazyUpdateCooldown = 0.2, --amount of time to wait for the next lazy update, this updates non critical things like the cast timer
|
|
|
|
--default size
|
|
Width = 100,
|
|
Height = 20,
|
|
|
|
--colour the castbar statusbar by the type of the cast
|
|
Colors = {
|
|
Casting = DF:CreateColorTable (1, 0.73, .1, 1),
|
|
Channeling = DF:CreateColorTable (1, 0.73, .1, 1),
|
|
Finished = DF:CreateColorTable (0, 1, 0, 1),
|
|
NonInterruptible = DF:CreateColorTable (.7, .7, .7, 1),
|
|
Failed = DF:CreateColorTable (.4, .4, .4, 1),
|
|
Interrupted = DF:CreateColorTable (.965, .754, .154, 1),
|
|
},
|
|
|
|
--appearance
|
|
BackgroundColor = DF:CreateColorTable (.2, .2, .2, .8),
|
|
Texture = [[Interface\TargetingFrame\UI-StatusBar]],
|
|
BorderShieldWidth = 10,
|
|
BorderShieldHeight = 12,
|
|
BorderShieldCoords = {0.26171875, 0.31640625, 0.53125, 0.65625},
|
|
BorderShieldTexture = 1300837,
|
|
SpellIconWidth = 10,
|
|
SpellIconHeight = 10,
|
|
ShieldIndicatorTexture = [[Interface\RaidFrame\Shield-Fill]],
|
|
ShieldGlowTexture = [[Interface\RaidFrame\Shield-Overshield]],
|
|
SparkTexture = [[Interface\CastingBar\UI-CastingBar-Spark]],
|
|
SparkWidth = 16,
|
|
SparkHeight = 16,
|
|
SparkOffset = 0,
|
|
},
|
|
|
|
Initialize = function (self)
|
|
self.unit = "unutilized unit"
|
|
self.lazyUpdateCooldown = self.Settings.LazyUpdateCooldown
|
|
self.Colors = self.Settings.Colors
|
|
|
|
self:SetUnit (nil)
|
|
PixelUtil.SetWidth (self, self.Settings.Width)
|
|
PixelUtil.SetHeight (self, self.Settings.Height)
|
|
|
|
self.background:SetColorTexture (self.Settings.BackgroundColor:GetColor())
|
|
self.background:SetAllPoints()
|
|
self.extraBackground:SetColorTexture (0, 0, 0, 1)
|
|
self.extraBackground:SetVertexColor (self.Settings.BackgroundColor:GetColor())
|
|
self.extraBackground:SetAllPoints()
|
|
|
|
self:SetTexture (self.Settings.Texture)
|
|
|
|
self.BorderShield:SetPoint ("center", self, "left", 0, 0)
|
|
self.BorderShield:SetTexture (self.Settings.BorderShieldTexture)
|
|
self.BorderShield:SetTexCoord (unpack (self.Settings.BorderShieldCoords))
|
|
self.BorderShield:SetSize (self.Settings.BorderShieldWidth, self.Settings.BorderShieldHeight)
|
|
|
|
self.Icon:SetPoint ("center", self, "left", 2, 0)
|
|
self.Icon:SetSize (self.Settings.SpellIconWidth, self.Settings.SpellIconHeight)
|
|
|
|
self.Spark:SetTexture (self.Settings.SparkTexture)
|
|
self.Spark:SetSize (self.Settings.SparkWidth, self.Settings.SparkHeight)
|
|
|
|
self.percentText:SetPoint ("right", self, "right", -2, 0)
|
|
self.percentText:SetJustifyH ("right")
|
|
|
|
self.fadeOutAnimation.alpha1:SetDuration (self.Settings.FadeOutTime)
|
|
self.fadeInAnimation.alpha1:SetDuration (self.Settings.FadeInTime)
|
|
end,
|
|
|
|
SetDefaultColor = function (self, colorType, r, g, b, a)
|
|
assert (type (colorType) == "string", "DetailsFramework: CastBar:SetDefaultColor require a string in the first argument.")
|
|
self.Colors [colorType]:SetColor (r, g, b, a)
|
|
end,
|
|
|
|
--> this get a color suggestion based on the type of cast being shown in the cast bar
|
|
GetCastColor = function (self)
|
|
if (not self.canInterrupt) then
|
|
return self.Colors.NonInterruptible
|
|
|
|
elseif (self.channeling) then
|
|
return self.Colors.Channeling
|
|
|
|
elseif (self.failed) then
|
|
return self.Colors.Failed
|
|
|
|
elseif (self.interrupted) then
|
|
return self.Colors.Interrupted
|
|
|
|
elseif (self.finished) then
|
|
return self.Colors.Finished
|
|
|
|
else
|
|
return self.Colors.Casting
|
|
end
|
|
end,
|
|
|
|
--> update all colors of the cast bar
|
|
UpdateCastColor = function (self)
|
|
local castColor = self:GetCastColor()
|
|
self:SetColor (castColor) --SetColor handles with ParseColors()
|
|
end,
|
|
|
|
--> initial checks to know if this is a valid cast and should show the cast bar, if this fails the cast bar won't show
|
|
IsValid = function (self, unit, castName, isTradeSkill, ignoreVisibility)
|
|
if (not ignoreVisibility and not self:IsShown()) then
|
|
return false
|
|
end
|
|
|
|
if (not self.Settings.ShowTradeSkills) then
|
|
if (isTradeSkill) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
if (not castName) then
|
|
return false
|
|
end
|
|
|
|
return true
|
|
end,
|
|
|
|
--> handle the interrupt state of the cast
|
|
--> this does not change the cast bar color because this function is called inside the start cast where is already handles the cast color
|
|
UpdateInterruptState = function (self)
|
|
if (self.Settings.ShowShield and not self.canInterrupt) then
|
|
self.BorderShield:Show()
|
|
else
|
|
self.BorderShield:Hide()
|
|
end
|
|
end,
|
|
|
|
--> this check if the cast did reach 100% in the statusbar, mostly called from OnTick
|
|
CheckCastIsDone = function (self, event, isFinished)
|
|
|
|
--> check max value
|
|
if (not isFinished and not self.finished) then
|
|
if (self.casting) then
|
|
if (self.value >= self.maxValue) then
|
|
isFinished = true
|
|
end
|
|
|
|
elseif (self.channeling) then
|
|
if (self.value > self.maxValue or self.value <= 0) then
|
|
isFinished = true
|
|
end
|
|
end
|
|
|
|
--> check if passed an event (not begin used at the moment)
|
|
if (event) then
|
|
if (event == UNIT_SPELLCAST_STOP or event == UNIT_SPELLCAST_CHANNEL_STOP) then
|
|
isFinished = true
|
|
end
|
|
end
|
|
end
|
|
|
|
--> the cast is finished
|
|
if (isFinished) then
|
|
if (self.casting) then
|
|
self.UNIT_SPELLCAST_STOP (self, self.unit, self.unit, self.castID, self.spellID)
|
|
|
|
elseif (self.channeling) then
|
|
self.UNIT_SPELLCAST_CHANNEL_STOP (self, self.unit, self.unit, self.castID, self.spellID)
|
|
end
|
|
|
|
return true
|
|
end
|
|
end,
|
|
|
|
--> setup the castbar to be used by another unit
|
|
SetUnit = function (self, unit, displayedUnit)
|
|
if (self.unit ~= unit or self.displayedUnit ~= displayedUnit or unit == nil) then
|
|
self.unit = unit
|
|
self.displayedUnit = displayedUnit or unit
|
|
|
|
--> reset the cast bar
|
|
self.casting = nil
|
|
self.channeling = nil
|
|
self.caninterrupt = nil
|
|
|
|
--> register events
|
|
if (unit) then
|
|
for _, eventTable in ipairs (self.CastBarEvents) do
|
|
local event = eventTable [1]
|
|
local isUnitEvent = eventTable [2]
|
|
|
|
if event then
|
|
if (isUnitEvent) then
|
|
self:RegisterUnitEvent (event, unit)
|
|
else
|
|
self:RegisterEvent (event)
|
|
end
|
|
end
|
|
end
|
|
|
|
--> set scripts
|
|
self:SetScript ("OnEvent", self.OnEvent)
|
|
self:SetScript ("OnShow", self.OnShow)
|
|
self:SetScript ("OnHide", self.OnHide)
|
|
|
|
if (self.Settings.CanTick) then
|
|
self:SetScript ("OnUpdate", self.OnTick)
|
|
end
|
|
|
|
--> check is can show the cast time text
|
|
if (self.Settings.ShowCastTime and self.Settings.CanLazyTick) then
|
|
self.percentText:Show()
|
|
else
|
|
self.percentText:Hide()
|
|
end
|
|
|
|
--> setup animtions
|
|
self:CancelScheduleToHide()
|
|
|
|
--self:PLAYER_ENTERING_WORLD (unit, unit)
|
|
self:OnEvent ("PLAYER_ENTERING_WORLD", unit, unit)
|
|
|
|
else
|
|
for _, eventTable in ipairs (self.CastBarEvents) do
|
|
local event = eventTable [1]
|
|
if event then
|
|
self:UnregisterEvent (event)
|
|
end
|
|
end
|
|
|
|
--> register main events
|
|
self:SetScript ("OnUpdate", nil)
|
|
self:SetScript ("OnEvent", nil)
|
|
self:SetScript ("OnShow", nil)
|
|
self:SetScript ("OnHide", nil)
|
|
|
|
self:Hide()
|
|
end
|
|
end
|
|
end,
|
|
|
|
--> executed after a scheduled to hide timer is done
|
|
DoScheduledHide = function (timerObject)
|
|
timerObject.castBar.scheduledHideTime = nil
|
|
|
|
--just to make sure it isn't casting
|
|
if (not timerObject.castBar.casting and not timerObject.castBar.channeling) then
|
|
if (not timerObject.castBar.Settings.NoFadeEffects) then
|
|
timerObject.castBar:Animation_FadeOut()
|
|
else
|
|
timerObject.castBar:Hide()
|
|
end
|
|
end
|
|
end,
|
|
|
|
HasScheduledHide = function (self)
|
|
return self.scheduledHideTime and not self.scheduledHideTime._cancelled
|
|
end,
|
|
|
|
CancelScheduleToHide = function (self)
|
|
if (self:HasScheduledHide()) then
|
|
self.scheduledHideTime:Cancel()
|
|
end
|
|
end,
|
|
|
|
--> after an interrupt, do not immediately hide the cast bar, let it up for short amount of time to give feedback to the player
|
|
ScheduleToHide = function (self, delay)
|
|
if (not delay) then
|
|
if (self.scheduledHideTime and not self.scheduledHideTime._cancelled) then
|
|
self.scheduledHideTime:Cancel()
|
|
end
|
|
|
|
self.scheduledHideTime = nil
|
|
return
|
|
end
|
|
|
|
--> already have a scheduled timer?
|
|
if (self.scheduledHideTime and not self.scheduledHideTime._cancelled) then
|
|
self.scheduledHideTime:Cancel()
|
|
end
|
|
|
|
self.scheduledHideTime = C_Timer.NewTimer (delay, self.DoScheduledHide)
|
|
self.scheduledHideTime.castBar = self
|
|
end,
|
|
|
|
OnHide = function (self)
|
|
--> just in case some other effects made it have a different alpha since SetUnit won't load if the unit is the same.
|
|
self:SetAlpha (1)
|
|
--> cancel any timer to hide scheduled
|
|
self:CancelScheduleToHide()
|
|
end,
|
|
|
|
--> just update the current value if a spell is being cast since it wasn't running its tick function during the hide state
|
|
--> everything else should be in the correct state
|
|
OnShow = function (self)
|
|
self.flashTexture:Hide()
|
|
|
|
if (self.unit) then
|
|
if (self.casting) then
|
|
local name, text, texture, startTime = UnitCastingInfo (self.unit)
|
|
if (name) then
|
|
self.value = GetTime() - self.spellStartTime
|
|
end
|
|
|
|
self:RunHooksForWidget ("OnShow", self, self.unit)
|
|
|
|
elseif (self.channeling) then
|
|
local name, text, texture, endTime = UnitChannelInfo (self.unit)
|
|
if (name) then
|
|
self.value = self.spellEndTime - GetTime()
|
|
end
|
|
|
|
self:RunHooksForWidget ("OnShow", self, self.unit)
|
|
end
|
|
end
|
|
end,
|
|
|
|
--it's triggering several events since it's not registered for the unit with RegisterUnitEvent
|
|
OnEvent = function (self, event, ...)
|
|
local arg1 = ...
|
|
local unit = self.unit
|
|
|
|
if (event == "PLAYER_ENTERING_WORLD") then
|
|
local newEvent = self.PLAYER_ENTERING_WORLD (self, unit, ...)
|
|
if (newEvent) then
|
|
self.OnEvent (self, newEvent, unit)
|
|
return
|
|
end
|
|
|
|
elseif (arg1 ~= unit) then
|
|
return
|
|
end
|
|
|
|
local eventFunc = self [event]
|
|
if (eventFunc) then
|
|
eventFunc (self, unit, ...)
|
|
end
|
|
end,
|
|
|
|
OnTick_LazyTick = function (self)
|
|
--> run the lazy tick if allowed
|
|
if (self.Settings.CanLazyTick) then
|
|
--> update the cast time
|
|
if (self.Settings.ShowCastTime) then
|
|
if (self.casting) then
|
|
self.percentText:SetText (format ("%.1f", abs (self.value - self.maxValue)))
|
|
|
|
elseif (self.channeling) then
|
|
local remainingTime = abs (self.value)
|
|
if (remainingTime > 999) then
|
|
self.percentText:SetText ("")
|
|
else
|
|
self.percentText:SetText (format ("%.1f", remainingTime))
|
|
end
|
|
else
|
|
self.percentText:SetText ("")
|
|
end
|
|
end
|
|
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end,
|
|
|
|
--> tick function for regular casts
|
|
OnTick_Casting = function (self, deltaTime)
|
|
self.value = self.value + deltaTime
|
|
|
|
if (self:CheckCastIsDone()) then
|
|
return
|
|
else
|
|
self:SetValue (self.value)
|
|
end
|
|
|
|
--update spark position
|
|
local sparkPosition = self.value / self.maxValue * self:GetWidth()
|
|
self.Spark:SetPoint ("center", self, "left", sparkPosition + self.Settings.SparkOffset, 0)
|
|
|
|
--in order to allow the lazy tick run, it must return true, it tell that the cast didn't finished
|
|
return true
|
|
end,
|
|
|
|
--> tick function for channeling casts
|
|
OnTick_Channeling = function (self, deltaTime)
|
|
self.value = self.value - deltaTime
|
|
|
|
if (self:CheckCastIsDone()) then
|
|
return
|
|
else
|
|
self:SetValue (self.value)
|
|
end
|
|
|
|
--update spark position
|
|
local sparkPosition = self.value / self.maxValue * self:GetWidth()
|
|
self.Spark:SetPoint ("center", self, "left", sparkPosition + self.Settings.SparkOffset, 0)
|
|
|
|
return true
|
|
end,
|
|
|
|
OnTick = function (self, deltaTime)
|
|
if (self.casting) then
|
|
if (not self:OnTick_Casting (deltaTime)) then
|
|
return
|
|
end
|
|
|
|
--lazy tick
|
|
self.lazyUpdateCooldown = self.lazyUpdateCooldown - deltaTime
|
|
if (self.lazyUpdateCooldown < 0) then
|
|
self:OnTick_LazyTick()
|
|
self.lazyUpdateCooldown = self.Settings.LazyUpdateCooldown
|
|
end
|
|
|
|
elseif (self.channeling) then
|
|
if (not self:OnTick_Channeling (deltaTime)) then
|
|
return
|
|
end
|
|
|
|
--lazy tick
|
|
self.lazyUpdateCooldown = self.lazyUpdateCooldown - deltaTime
|
|
if (self.lazyUpdateCooldown < 0) then
|
|
self:OnTick_LazyTick()
|
|
self.lazyUpdateCooldown = self.Settings.LazyUpdateCooldown
|
|
end
|
|
end
|
|
end,
|
|
|
|
--> animation start script
|
|
Animation_FadeOutStarted = function (self)
|
|
|
|
end,
|
|
|
|
--> animation finished script
|
|
Animation_FadeOutFinished = function (self)
|
|
local castBar = self:GetParent()
|
|
castBar:SetAlpha (1)
|
|
castBar:Hide()
|
|
end,
|
|
|
|
--> animation start script
|
|
Animation_FadeInStarted = function (self)
|
|
|
|
end,
|
|
|
|
--> animation finished script
|
|
Animation_FadeInFinished = function (self)
|
|
local castBar = self:GetParent()
|
|
castBar:Show()
|
|
castBar:SetAlpha (1)
|
|
end,
|
|
|
|
--> animation calls
|
|
Animation_FadeOut = function (self)
|
|
self:ScheduleToHide (false)
|
|
|
|
if (self.fadeInAnimation:IsPlaying()) then
|
|
self.fadeInAnimation:Stop()
|
|
end
|
|
|
|
if (not self.fadeOutAnimation:IsPlaying()) then
|
|
self.fadeOutAnimation:Play()
|
|
end
|
|
end,
|
|
|
|
Animation_FadeIn = function (self)
|
|
self:ScheduleToHide (false)
|
|
|
|
if (self.fadeOutAnimation:IsPlaying()) then
|
|
self.fadeOutAnimation:Stop()
|
|
end
|
|
|
|
if (not self.fadeInAnimation:IsPlaying()) then
|
|
self.fadeInAnimation:Play()
|
|
end
|
|
end,
|
|
|
|
Animation_Flash = function (self)
|
|
if (not self.flashAnimation:IsPlaying()) then
|
|
self.flashAnimation:Play()
|
|
end
|
|
end,
|
|
|
|
Animation_StopAllAnimations = function (self)
|
|
if (self.flashAnimation:IsPlaying()) then
|
|
self.flashAnimation:Stop()
|
|
end
|
|
|
|
if (self.fadeOutAnimation:IsPlaying()) then
|
|
self.fadeOutAnimation:Stop()
|
|
end
|
|
|
|
if (self.fadeInAnimation:IsPlaying()) then
|
|
self.fadeInAnimation:Stop()
|
|
end
|
|
end,
|
|
|
|
PLAYER_ENTERING_WORLD = function (self, unit, arg1)
|
|
local isChannel = UnitChannelInfo (unit)
|
|
local isRegularCast = UnitCastingInfo (unit)
|
|
|
|
if (isChannel) then
|
|
self.channeling = true
|
|
return self.unit == arg1 and "UNIT_SPELLCAST_CHANNEL_START"
|
|
|
|
elseif (isRegularCast) then
|
|
self.casting = true
|
|
return self.unit == arg1 and "UNIT_SPELLCAST_START"
|
|
|
|
else
|
|
self.casting = nil
|
|
self.channeling = nil
|
|
self.failed = nil
|
|
self.finished = nil
|
|
self.interrupted = nil
|
|
self.Spark:Hide()
|
|
self:Hide()
|
|
end
|
|
end,
|
|
|
|
UNIT_SPELLCAST_START = function (self, unit)
|
|
|
|
local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible, spellID = UnitCastingInfo (unit)
|
|
else
|
|
name, text, texture, startTime, endTime, isTradeSkill, castID, spellID = UnitCastingInfo (unit)
|
|
notInterruptible = false
|
|
end
|
|
|
|
--> is valid?
|
|
if (not self:IsValid (unit, name, isTradeSkill, true)) then
|
|
return
|
|
end
|
|
|
|
--> setup cast
|
|
self.casting = true
|
|
self.channeling = nil
|
|
self.interrupted = nil
|
|
self.failed = nil
|
|
self.finished = nil
|
|
self.canInterrupt = not notInterruptible
|
|
self.spellID = spellID
|
|
self.castID = castID
|
|
self.spellName = name
|
|
self.spellTexture = texture
|
|
self.spellStartTime = startTime / 1000
|
|
self.spellEndTime = endTime / 1000
|
|
self.value = GetTime() - self.spellStartTime
|
|
self.maxValue = self.spellEndTime - self.spellStartTime
|
|
|
|
self:SetMinMaxValues (0, self.maxValue)
|
|
self:SetValue (self.value)
|
|
self:SetAlpha (1)
|
|
self.Icon:SetTexture (texture)
|
|
self.Icon:Show()
|
|
self.Text:SetText (text)
|
|
|
|
if (self.Settings.ShowCastTime and self.Settings.CanLazyTick) then
|
|
self.percentText:Show()
|
|
end
|
|
|
|
self.flashTexture:Hide()
|
|
self:Animation_StopAllAnimations()
|
|
|
|
self:SetAlpha (1)
|
|
|
|
--> set the statusbar color
|
|
self:UpdateCastColor()
|
|
|
|
if (not self:IsShown()) then
|
|
self:Animation_FadeIn()
|
|
end
|
|
|
|
self.Spark:Show()
|
|
self:Show()
|
|
|
|
--> update the interrupt cast border
|
|
self:UpdateInterruptState()
|
|
|
|
self:RunHooksForWidget ("OnCastStart", self, self.unit, "UNIT_SPELLCAST_START")
|
|
end,
|
|
|
|
UNIT_SPELLCAST_CHANNEL_START = function (self, unit, ...)
|
|
local name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID
|
|
if IS_WOW_PROJECT_MAINLINE then
|
|
name, text, texture, startTime, endTime, isTradeSkill, notInterruptible, spellID = UnitChannelInfo (unit)
|
|
else
|
|
name, text, texture, startTime, endTime, isTradeSkill, spellID = UnitChannelInfo (unit)
|
|
end
|
|
|
|
--> is valid?
|
|
if (not self:IsValid (unit, name, isTradeSkill, true)) then
|
|
return
|
|
end
|
|
|
|
--> setup cast
|
|
self.casting = nil
|
|
self.channeling = true
|
|
self.interrupted = nil
|
|
self.failed = nil
|
|
self.finished = nil
|
|
self.canInterrupt = not notInterruptible
|
|
self.spellID = spellID
|
|
self.castID = castID
|
|
self.spellName = name
|
|
self.spellTexture = texture
|
|
self.spellStartTime = startTime / 1000
|
|
self.spellEndTime = endTime / 1000
|
|
self.value = self.spellEndTime - GetTime()
|
|
self.maxValue = self.spellEndTime - self.spellStartTime
|
|
|
|
self:SetMinMaxValues (0, self.maxValue)
|
|
self:SetValue (self.value)
|
|
|
|
self:SetAlpha (1)
|
|
self.Icon:SetTexture (texture)
|
|
self.Icon:Show()
|
|
self.Text:SetText (text)
|
|
|
|
if (self.Settings.ShowCastTime and self.Settings.CanLazyTick) then
|
|
self.percentText:Show()
|
|
end
|
|
|
|
self.flashTexture:Hide()
|
|
self:Animation_StopAllAnimations()
|
|
|
|
self:SetAlpha (1)
|
|
|
|
--> set the statusbar color
|
|
self:UpdateCastColor()
|
|
|
|
if (not self:IsShown()) then
|
|
self:Animation_FadeIn()
|
|
end
|
|
|
|
self.Spark:Show()
|
|
self:Show()
|
|
|
|
--> update the interrupt cast border
|
|
self:UpdateInterruptState()
|
|
|
|
self:RunHooksForWidget ("OnCastStart", self, self.unit, "UNIT_SPELLCAST_CHANNEL_START")
|
|
end,
|
|
|
|
UNIT_SPELLCAST_STOP = function (self, unit, ...)
|
|
local unitID, castID, spellID = ...
|
|
if (self.castID == castID) then
|
|
self.Spark:Hide()
|
|
self.percentText:Hide()
|
|
|
|
local value = self:GetValue()
|
|
local _, maxValue = self:GetMinMaxValues()
|
|
self:SetValue (self.maxValue or maxValue or 1)
|
|
|
|
self.casting = nil
|
|
self.finished = true
|
|
|
|
if (not self:HasScheduledHide()) then
|
|
--> check if settings has no fade option or if its parents are not visible
|
|
if (not self:IsVisible()) then
|
|
self:Hide()
|
|
|
|
elseif (self.Settings.NoFadeEffects) then
|
|
self:ScheduleToHide (0.3)
|
|
|
|
else
|
|
self:Animation_Flash()
|
|
self:Animation_FadeOut()
|
|
end
|
|
end
|
|
|
|
self:UpdateCastColor()
|
|
end
|
|
end,
|
|
|
|
UNIT_SPELLCAST_CHANNEL_STOP = function (self, unit, ...)
|
|
local unitID, castID, spellID = ...
|
|
|
|
if (self.channeling and castID == self.castID) then
|
|
self.Spark:Hide()
|
|
self.percentText:Hide()
|
|
|
|
local value = self:GetValue()
|
|
local _, maxValue = self:GetMinMaxValues()
|
|
self:SetValue (self.maxValue or maxValue or 1)
|
|
|
|
self.channeling = nil
|
|
self.finished = true
|
|
|
|
if (not self:HasScheduledHide()) then
|
|
--> check if settings has no fade option or if its parents are not visible
|
|
if (not self:IsVisible()) then
|
|
self:Hide()
|
|
|
|
elseif (self.Settings.NoFadeEffects) then
|
|
self:ScheduleToHide (0.3)
|
|
|
|
else
|
|
self:Animation_Flash()
|
|
self:Animation_FadeOut()
|
|
end
|
|
end
|
|
|
|
self:UpdateCastColor()
|
|
end
|
|
end,
|
|
|
|
UNIT_SPELLCAST_FAILED = function (self, unit, ...)
|
|
local unitID, castID, spellID = ...
|
|
|
|
if (self.casting and castID == self.castID and not self.fadeOut) then
|
|
self.casting = nil
|
|
self.channeling = nil
|
|
self.failed = true
|
|
self.finished = true
|
|
self:SetValue (self.maxValue or select (2, self:GetMinMaxValues()) or 1)
|
|
|
|
--> set the statusbar color
|
|
self:UpdateCastColor()
|
|
|
|
self.Spark:Hide()
|
|
self.percentText:Hide()
|
|
self.Text:SetText (FAILED) --> auto locale within the global namespace
|
|
|
|
self:ScheduleToHide (1)
|
|
end
|
|
end,
|
|
|
|
UNIT_SPELLCAST_INTERRUPTED = function (self, unit, ...)
|
|
local unitID, castID, spellID = ...
|
|
|
|
if (self.casting and castID == self.castID and not self.fadeOut) then
|
|
self.casting = nil
|
|
self.channeling = nil
|
|
self.interrupted = true
|
|
self.finished = true
|
|
self:SetValue (self.maxValue or select (2, self:GetMinMaxValues()) or 1)
|
|
|
|
local castColor = self:GetCastColor()
|
|
self:SetColor (castColor) --SetColor handles with ParseColors()
|
|
|
|
self.Spark:Hide()
|
|
self.percentText:Hide()
|
|
self.Text:SetText (INTERRUPTED) --> auto locale within the global namespace
|
|
|
|
self:ScheduleToHide (1)
|
|
end
|
|
end,
|
|
|
|
UNIT_SPELLCAST_DELAYED = function (self, unit, ...)
|
|
local name, text, texture, startTime, endTime, isTradeSkill, castID, notInterruptible = UnitCastingInfo (unit)
|
|
|
|
if (not self:IsValid (unit, name, isTradeSkill)) then
|
|
return
|
|
end
|
|
|
|
--> update the cast time
|
|
self.spellStartTime = startTime / 1000
|
|
self.spellEndTime = endTime / 1000
|
|
self.value = GetTime() - self.spellStartTime
|
|
self.maxValue = self.spellEndTime - self.spellStartTime
|
|
self:SetMinMaxValues (0, self.maxValue)
|
|
end,
|
|
|
|
UNIT_SPELLCAST_CHANNEL_UPDATE = function (self, unit, ...)
|
|
local name, text, texture, startTime, endTime, isTradeSkill = UnitChannelInfo (unit)
|
|
|
|
if (not self:IsValid (unit, name, isTradeSkill)) then
|
|
return
|
|
end
|
|
|
|
--> update the cast time
|
|
self.spellStartTime = startTime / 1000
|
|
self.spellEndTime = endTime / 1000
|
|
self.value = self.spellEndTime - GetTime()
|
|
|
|
if (self.value < 0) then
|
|
self.value = 0
|
|
end
|
|
|
|
self.maxValue = self.spellEndTime - self.spellStartTime
|
|
self:SetMinMaxValues (0, self.maxValue)
|
|
self:SetValue (self.value)
|
|
end,
|
|
|
|
--> cast changed its state to interruptable
|
|
UNIT_SPELLCAST_INTERRUPTIBLE = function (self, unit, ...)
|
|
self.canInterrupt = true
|
|
self:UpdateCastColor()
|
|
self:UpdateInterruptState()
|
|
end,
|
|
|
|
--> cast changed its state to non interruptable
|
|
UNIT_SPELLCAST_NOT_INTERRUPTIBLE = function (self, unit, ...)
|
|
self.canInterrupt = false
|
|
self:UpdateCastColor()
|
|
self:UpdateInterruptState()
|
|
end,
|
|
|
|
}
|
|
|
|
-- ~castbar
|
|
|
|
function DF:CreateCastBar (parent, name, settingsOverride)
|
|
|
|
assert (name or parent:GetName(), "DetailsFramework:CreateCastBar parameter 'name' omitted and parent has no name.")
|
|
|
|
local castBar = CreateFrame ("StatusBar", name or (parent:GetName() .. "CastBar"), parent, "BackdropTemplate")
|
|
|
|
do --layers
|
|
|
|
--these widgets was been made with back compatibility in mind
|
|
--they are using the same names as the retail game uses on the nameplate castbar
|
|
--this should make Plater core and Plater scripts made by users compatible with the new unit frame made on the framework
|
|
|
|
--background
|
|
castBar.background = castBar:CreateTexture (nil, "background")
|
|
castBar.background:SetDrawLayer ("background", -6)
|
|
|
|
castBar.extraBackground = castBar:CreateTexture (nil, "background")
|
|
castBar.extraBackground:SetDrawLayer ("background", -5)
|
|
|
|
--overlay
|
|
castBar.Text = castBar:CreateFontString (nil, "overlay", "SystemFont_Shadow_Small")
|
|
castBar.Text:SetPoint ("center", 0, 0)
|
|
castBar.Text:SetDrawLayer ("overlay", 1)
|
|
|
|
castBar.BorderShield = castBar:CreateTexture (nil, "overlay")
|
|
castBar.BorderShield:SetDrawLayer ("overlay", 5)
|
|
castBar.BorderShield:Hide()
|
|
|
|
castBar.Icon = castBar:CreateTexture (nil, "overlay")
|
|
castBar.Icon:SetDrawLayer ("overlay", 4)
|
|
castBar.Icon:Hide()
|
|
|
|
castBar.Spark = castBar:CreateTexture (nil, "overlay")
|
|
castBar.Spark:SetDrawLayer ("overlay", 3)
|
|
castBar.Spark:SetBlendMode ("ADD")
|
|
|
|
--time left on the cast
|
|
castBar.percentText = castBar:CreateFontString (nil, "overlay", "SystemFont_Shadow_Small")
|
|
castBar.percentText:SetDrawLayer ("overlay", 7)
|
|
|
|
--statusbar texture
|
|
castBar.barTexture = castBar:CreateTexture (nil, "artwork")
|
|
castBar:SetStatusBarTexture (castBar.barTexture)
|
|
|
|
--animations fade in and out
|
|
local fadeOutAnimationHub = DF:CreateAnimationHub (castBar, DF.CastFrameFunctions.Animation_FadeOutStarted, DF.CastFrameFunctions.Animation_FadeOutFinished)
|
|
fadeOutAnimationHub.alpha1 = DF:CreateAnimation (fadeOutAnimationHub, "ALPHA", 1, 1, 1, 0)
|
|
castBar.fadeOutAnimation = fadeOutAnimationHub
|
|
|
|
local fadeInAnimationHub = DF:CreateAnimationHub (castBar, DF.CastFrameFunctions.Animation_FadeInStarted, DF.CastFrameFunctions.Animation_FadeInFinished)
|
|
fadeInAnimationHub.alpha1 = DF:CreateAnimation (fadeInAnimationHub, "ALPHA", 1, 0.150, 0, 1)
|
|
castBar.fadeInAnimation = fadeInAnimationHub
|
|
|
|
--animatios flash
|
|
local flashTexture = castBar:CreateTexture (nil, "overlay")
|
|
flashTexture:SetDrawLayer ("overlay", 7)
|
|
flashTexture:SetColorTexture (1, 1, 1, 1)
|
|
flashTexture:SetAllPoints()
|
|
flashTexture:SetAlpha (0)
|
|
flashTexture:Hide()
|
|
flashTexture:SetBlendMode ("ADD")
|
|
castBar.flashTexture = flashTexture
|
|
|
|
local flashAnimationHub = DF:CreateAnimationHub (flashTexture, function() flashTexture:Show() end, function() flashTexture:Hide() end)
|
|
DF:CreateAnimation (flashAnimationHub, "ALPHA", 1, 0.2, 0, 0.8)
|
|
DF:CreateAnimation (flashAnimationHub, "ALPHA", 2, 0.2, 1, 0)
|
|
castBar.flashAnimation = flashAnimationHub
|
|
end
|
|
|
|
--> mixins
|
|
DF:Mixin (castBar, DF.CastFrameFunctions)
|
|
DF:Mixin (castBar, DF.StatusBarFunctions)
|
|
|
|
--> settings and hooks
|
|
local settings = DF.table.copy ({}, DF.CastFrameFunctions.Settings)
|
|
if (settingsOverride) then
|
|
DF.table.copy (settings, settingsOverride)
|
|
end
|
|
castBar.Settings = settings
|
|
|
|
local hookList = DF.table.copy ({}, DF.CastFrameFunctions.HookList)
|
|
castBar.HookList = hookList
|
|
|
|
--> initialize the cast bar
|
|
castBar:Initialize()
|
|
|
|
return castBar
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> border frame
|
|
|
|
--[=[
|
|
DF:CreateBorderFrame (parent, name)
|
|
creates a frame with 4 child textures attached to each one of the 4 sides of a frame
|
|
@parent = parent frame to pass to CreateFrame function
|
|
@name = name of the frame, if omitted a random name is created
|
|
--]=]
|
|
|
|
DF.BorderFunctions = {
|
|
SetBorderColor = function (self, r, g, b, a)
|
|
r, g, b, a = DF:ParseColors (r, g, b, a)
|
|
for _, texture in ipairs (self.allTextures) do
|
|
texture:SetVertexColor (r, g, b, a)
|
|
end
|
|
end,
|
|
|
|
SetBorderThickness = function (self, newThickness)
|
|
PixelUtil.SetWidth (self.leftBorder, newThickness, newThickness)
|
|
PixelUtil.SetWidth (self.rightBorder, newThickness, newThickness)
|
|
PixelUtil.SetHeight (self.topBorder, newThickness, newThickness)
|
|
PixelUtil.SetHeight (self.bottomBorder, newThickness, newThickness)
|
|
end,
|
|
|
|
WidgetType = "border",
|
|
}
|
|
|
|
-- ~borderframe
|
|
function DF:CreateBorderFrame (parent, name)
|
|
|
|
local parentName = name or "DetailsFrameworkBorderFrame" .. tostring (math.random (1, 100000000))
|
|
|
|
local f = CreateFrame ("frame", parentName, parent, "BackdropTemplate")
|
|
f:SetFrameLevel (f:GetFrameLevel()+1)
|
|
f:SetAllPoints()
|
|
|
|
DF:Mixin (f, DF.BorderFunctions)
|
|
|
|
f.allTextures = {}
|
|
|
|
--> create left border
|
|
local leftBorder = f:CreateTexture (nil, "overlay")
|
|
leftBorder:SetDrawLayer ("overlay", 7)
|
|
leftBorder:SetColorTexture (1, 1, 1, 1)
|
|
tinsert (f.allTextures, leftBorder)
|
|
f.leftBorder = leftBorder
|
|
PixelUtil.SetPoint (leftBorder, "topright", f, "topleft", 0, 1, 0, 1)
|
|
PixelUtil.SetPoint (leftBorder, "bottomright", f, "bottomleft", 0, -1, 0, -1)
|
|
PixelUtil.SetWidth (leftBorder, 1, 1)
|
|
|
|
--> create right border
|
|
local rightBorder = f:CreateTexture (nil, "overlay")
|
|
rightBorder:SetDrawLayer ("overlay", 7)
|
|
rightBorder:SetColorTexture (1, 1, 1, 1)
|
|
tinsert (f.allTextures, rightBorder)
|
|
f.rightBorder = rightBorder
|
|
PixelUtil.SetPoint (rightBorder, "topleft", f, "topright", 0, 1, 0, 1)
|
|
PixelUtil.SetPoint (rightBorder, "bottomleft", f, "bottomright", 0, -1, 0, -1)
|
|
PixelUtil.SetWidth (rightBorder, 1, 1)
|
|
|
|
--> create top border
|
|
local topBorder = f:CreateTexture (nil, "overlay")
|
|
topBorder:SetDrawLayer ("overlay", 7)
|
|
topBorder:SetColorTexture (1, 1, 1, 1)
|
|
tinsert (f.allTextures, topBorder)
|
|
f.topBorder = topBorder
|
|
PixelUtil.SetPoint (topBorder, "bottomleft", f, "topleft", 0, 0, 0, 0)
|
|
PixelUtil.SetPoint (topBorder, "bottomright", f, "topright", 0, 0, 0, 0)
|
|
PixelUtil.SetHeight (topBorder, 1, 1)
|
|
|
|
--> create border
|
|
local bottomBorder = f:CreateTexture (nil, "overlay")
|
|
bottomBorder:SetDrawLayer ("overlay", 7)
|
|
bottomBorder:SetColorTexture (1, 1, 1, 1)
|
|
tinsert (f.allTextures, bottomBorder)
|
|
f.bottomBorder = bottomBorder
|
|
PixelUtil.SetPoint (bottomBorder, "topleft", f, "bottomleft", 0, 0, 0, 0)
|
|
PixelUtil.SetPoint (bottomBorder, "topright", f, "bottomright", 0, 0, 0, 0)
|
|
PixelUtil.SetHeight (bottomBorder, 1, 1)
|
|
|
|
return f
|
|
end
|
|
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> unit frame
|
|
|
|
--[=[
|
|
DF:CreateUnitFrame (parent, name, settingsOverride)
|
|
creates a very basic unit frame with a healthbar, castbar and power bar
|
|
each unit frame has a .Settings table which isn't shared among other unit frames created with this method
|
|
all members names are the same as the unit frame from the retail game
|
|
|
|
@parent = frame to pass for the CreateFrame function
|
|
@name = absolute name of the frame, if omitted a random name is created
|
|
@settingsOverride = table with keys and values to replace the defaults from the framework
|
|
|
|
--]=]
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> unit frame
|
|
|
|
--> return true if the unit has been claimed by another player (health bar is gray)
|
|
local unit_is_tap_denied = function (unit)
|
|
return unit and not UnitPlayerControlled (unit) and UnitIsTapDenied (unit)
|
|
end
|
|
|
|
DF.UnitFrameFunctions = {
|
|
|
|
WidgetType = "unitFrame",
|
|
|
|
Settings = {
|
|
--> unit frames
|
|
ClearUnitOnHide = true, --> if tue it'll set the unit to nil when the unit frame is set to hide
|
|
ShowCastBar = true, --if this is false, the cast bar for the unit won't be shown
|
|
ShowPowerBar = true, --if true it'll show the power bar for the unit, e.g. the mana bar
|
|
ShowUnitName = true, --if false, the unit name won't show
|
|
ShowBorder = true, --if false won't show the border frame
|
|
|
|
--> health bar color
|
|
CanModifyHealhBarColor = true, --> if false it won't change the color of the health bar
|
|
ColorByAggro = false, --if true it'll color the healthbar with red color when the unit has aggro on player
|
|
FixedHealthColor = false, --color override with a table {r=1, g=1, b=1}
|
|
UseFriendlyClassColor = true, --make the healthbar class color for friendly players
|
|
UseEnemyClassColor = true, --make the healthbar class color for enemy players
|
|
|
|
--> misc
|
|
ShowTargetOverlay = true, --shows a highlighht for the player current target
|
|
BorderColor = DF:CreateColorTable (0, 0, 0, 1), --border color, set to alpha zero for no border
|
|
CanTick = false, --if true it'll run the OnTick event
|
|
|
|
--> size
|
|
Width = 100,
|
|
Height = 20,
|
|
PowerBarHeight = 4,
|
|
CastBarHeight = 8,
|
|
},
|
|
|
|
UnitFrameEvents = {
|
|
--> run for all units
|
|
{"PLAYER_ENTERING_WORLD"},
|
|
{"PARTY_MEMBER_DISABLE"},
|
|
{"PARTY_MEMBER_ENABLE"},
|
|
{"PLAYER_TARGET_CHANGED"},
|
|
|
|
--> run for one unit
|
|
{"UNIT_NAME_UPDATE", true},
|
|
{"UNIT_CONNECTION", true},
|
|
{"UNIT_ENTERED_VEHICLE", true},
|
|
{"UNIT_EXITED_VEHICLE", true},
|
|
{"UNIT_PET", true},
|
|
{"UNIT_THREAT_LIST_UPDATE", true},
|
|
},
|
|
|
|
--> used when a event is triggered to quickly check if is a unit event
|
|
IsUnitEvent = {
|
|
["UNIT_NAME_UPDATE"] = true,
|
|
["UNIT_CONNECTION"] = true,
|
|
["UNIT_ENTERED_VEHICLE"] = true,
|
|
["UNIT_EXITED_VEHICLE"] = true,
|
|
["UNIT_PET"] = true,
|
|
["UNIT_THREAT_LIST_UPDATE"] = true,
|
|
},
|
|
|
|
Initialize = function (self)
|
|
self.border:SetBorderColor (self.Settings.BorderColor)
|
|
|
|
PixelUtil.SetWidth (self, self.Settings.Width, 1)
|
|
PixelUtil.SetHeight (self, self.Settings.Height, 1)
|
|
|
|
PixelUtil.SetPoint (self.powerBar, "bottomleft", self, "bottomleft", 0, 0, 1, 1)
|
|
PixelUtil.SetPoint (self.powerBar, "bottomright", self, "bottomright", 0, 0, 1, 1)
|
|
PixelUtil.SetHeight (self.powerBar, self.Settings.PowerBarHeight, 1)
|
|
|
|
--make the castbar overlap the powerbar
|
|
PixelUtil.SetPoint (self.castBar, "bottomleft", self, "bottomleft", 0, 0, 1, 1)
|
|
PixelUtil.SetPoint (self.castBar, "bottomright", self, "bottomright", 0, 0, 1, 1)
|
|
PixelUtil.SetHeight (self.castBar, self.Settings.CastBarHeight, 1)
|
|
end,
|
|
|
|
SetHealthBarColor = function (self, r, g, b, a)
|
|
self.healthBar:SetColor (r, g, b, a)
|
|
end,
|
|
|
|
--> register all events which will be used by the unit frame
|
|
RegisterEvents = function (self)
|
|
--> register events
|
|
for index, eventTable in ipairs (self.UnitFrameEvents) do
|
|
local event, isUnitEvent = unpack (eventTable)
|
|
if (not isUnitEvent) then
|
|
self:RegisterEvent (event)
|
|
else
|
|
self:RegisterUnitEvent (event, self.unit, self.displayedUnit ~= unit and self.displayedUnit or nil)
|
|
end
|
|
end
|
|
|
|
--> check settings and unregister events for disabled features
|
|
if (not self.Settings.ColorByAggro) then
|
|
self:UnregisterEvent ("UNIT_THREAT_LIST_UPDATE")
|
|
end
|
|
|
|
--> set scripts
|
|
self:SetScript ("OnEvent", self.OnEvent)
|
|
self:SetScript ("OnHide", self.OnHide)
|
|
|
|
if (self.Settings.CanTick) then
|
|
self:SetScript ("OnUpdate", self.OnTick)
|
|
end
|
|
end,
|
|
|
|
--> unregister events, called when this unit frame losses its unit
|
|
UnregisterEvents = function (self)
|
|
for index, eventTable in ipairs (self.UnitFrameEvents) do
|
|
local event, firstUnit, secondUnit = unpack (eventTable)
|
|
self:UnregisterEvent (event)
|
|
end
|
|
|
|
self:SetScript ("OnEvent", nil)
|
|
self:SetScript ("OnUpdate", nil)
|
|
self:SetScript ("OnHide", nil)
|
|
end,
|
|
|
|
--> call every tick
|
|
OnTick = function (self, deltaTime) end, --if overrided, set 'CanTick' to true on the settings table
|
|
|
|
--> when an event happen for this unit, send it to the apropriate function
|
|
OnEvent = function (self, event, ...)
|
|
--> run the function for this event
|
|
local eventFunc = self [event]
|
|
if (eventFunc) then
|
|
--> is this event an unit event?
|
|
if (self.IsUnitEvent [event]) then
|
|
local unit = ...
|
|
--> check if is for this unit (even if the event is registered only for the unit)
|
|
if (unit == self.unit or unit == self.displayedUnit) then
|
|
eventFunc (self, ...)
|
|
end
|
|
else
|
|
eventFunc (self, ...)
|
|
end
|
|
end
|
|
end,
|
|
|
|
OnHide = function (self)
|
|
if (self.Settings.ClearUnitOnHide) then
|
|
self:SetUnit (nil)
|
|
end
|
|
end,
|
|
|
|
--> run if the unit currently shown is different than the new one
|
|
SetUnit = function (self, unit)
|
|
if (unit ~= self.unit or unit == nil) then
|
|
self.unit = unit --absolute unit
|
|
self.displayedUnit = unit --~todo rename to 'displayedUnit' for back compatibility with older scripts in Plater
|
|
self.unitInVehicle = nil --true when the unit is in a vehicle
|
|
|
|
if (unit) then
|
|
self:RegisterEvents()
|
|
|
|
self.healthBar:SetUnit (unit, self.displayedUnit)
|
|
|
|
--> is using castbars?
|
|
if (self.Settings.ShowCastBar) then
|
|
self.castBar:SetUnit (unit, self.displayedUnit)
|
|
else
|
|
self.castBar:SetUnit (nil)
|
|
end
|
|
|
|
--> is using powerbars?
|
|
if (self.Settings.ShowPowerBar) then
|
|
self.powerBar:SetUnit (unit, self.displayedUnit)
|
|
else
|
|
self.powerBar:SetUnit (nil)
|
|
end
|
|
|
|
--> is using the border?
|
|
if (self.Settings.ShowBorder) then
|
|
self.border:Show()
|
|
else
|
|
self.border:Hide()
|
|
end
|
|
|
|
if (not self.Settings.ShowUnitName) then
|
|
self.unitName:Hide()
|
|
end
|
|
else
|
|
self:UnregisterEvents()
|
|
self.healthBar:SetUnit (nil)
|
|
self.castBar:SetUnit (nil)
|
|
self.powerBar:SetUnit (nil)
|
|
end
|
|
|
|
self:UpdateUnitFrame()
|
|
end
|
|
end,
|
|
|
|
--> if the unit is controlling a vehicle, need to show the vehicle instead
|
|
--> .unit and .displayedUnit is always the same execept when the unit is controlling a vehicle, then .displayedUnit is the unitID for the vehicle
|
|
--> todo: see what 'UnitTargetsVehicleInRaidUI' is, there's a call for this in the CompactUnitFrame.lua but zero documentation
|
|
CheckVehiclePossession = function (self)
|
|
--> this unit is possessing a vehicle?
|
|
local unitPossessVehicle = (IS_WOW_PROJECT_MAINLINE) and UnitHasVehicleUI (self.unit) or false
|
|
if (unitPossessVehicle) then
|
|
if (not self.unitInVehicle) then
|
|
if (UnitIsUnit ("player", self.unit)) then
|
|
self.displayedUnit = "vehicle"
|
|
self.unitInVehicle = true
|
|
self:RegisterEvents()
|
|
self:UpdateAllWidgets()
|
|
return true
|
|
end
|
|
|
|
local prefix, id, suffix = string.match (self.unit, "([^%d]+)([%d]*)(.*)") --CompactUnitFrame.lua
|
|
local vehicleUnitID = prefix .. "pet" .. id .. suffix
|
|
if (UnitExists (vehicleUnitID)) then
|
|
self.displayedUnit = vehicleUnitID
|
|
self.unitInVehicle = true
|
|
self:RegisterEvents()
|
|
self:UpdateAllWidgets()
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
if (self.unitInVehicle) then
|
|
self.displayedUnit = self.unit
|
|
self.unitInVehicle = nil
|
|
self:RegisterEvents()
|
|
self:UpdateAllWidgets()
|
|
end
|
|
end,
|
|
|
|
--> find a color for the health bar, if a color has been passed in the arguments use it instead, 'CanModifyHealhBarColor' must be true for this function run
|
|
UpdateHealthColor = function (self, r, g, b)
|
|
|
|
--> check if color changes is disabled
|
|
if (not self.Settings.CanModifyHealhBarColor) then
|
|
return
|
|
end
|
|
|
|
local unit = self.displayedUnit
|
|
|
|
--> check if a color has been passed within the parameters
|
|
if (r) then
|
|
--> check if passed a special color
|
|
if (type (r) ~= "number") then
|
|
r, g, b = DF:ParseColors (r)
|
|
end
|
|
|
|
self:SetHealthBarColor (r, g, b)
|
|
return
|
|
end
|
|
|
|
--> check if there is a color override in the settings
|
|
if (self.Settings.FixedHealthColor) then
|
|
local FixedHealthColor = self.Settings.FixedHealthColor
|
|
r, g, b = FixedHealthColor.r, FixedHealthColor.g, FixedHealthColor.b
|
|
self:SetHealthBarColor (r, g, b)
|
|
return
|
|
end
|
|
|
|
--> check if the unit is a player
|
|
if (UnitIsPlayer (unit)) then
|
|
|
|
--> check if the unit is disconnected (in case it is a player
|
|
if (not UnitIsConnected (unit)) then
|
|
self:SetHealthBarColor (.5, .5, .5)
|
|
return
|
|
end
|
|
|
|
--is a friendly or enemy player?
|
|
if (UnitIsFriend ("player", unit)) then
|
|
if (self.Settings.UseFriendlyClassColor) then
|
|
local _, className = UnitClass (unit)
|
|
if (className) then
|
|
local classColor = RAID_CLASS_COLORS [className]
|
|
if (classColor) then
|
|
self:SetHealthBarColor (classColor.r, classColor.g, classColor.b)
|
|
return
|
|
end
|
|
end
|
|
else
|
|
self:SetHealthBarColor (0, 1, 0)
|
|
return
|
|
end
|
|
else
|
|
if (self.Settings.UseEnemyClassColor) then
|
|
local _, className = UnitClass (unit)
|
|
if (className) then
|
|
local classColor = RAID_CLASS_COLORS [className]
|
|
if (classColor) then
|
|
self:SetHealthBarColor (classColor.r, classColor.g, classColor.b)
|
|
return
|
|
end
|
|
end
|
|
else
|
|
self:SetHealthBarColor (1, 0, 0)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
--> is tapped?
|
|
if (unit_is_tap_denied (unit)) then
|
|
self:SetHealthBarColor (.6, .6, .6)
|
|
return
|
|
end
|
|
|
|
--> is this is a npc attacking the player?
|
|
if (self.Settings.ColorByAggro) then
|
|
local _, threatStatus = UnitDetailedThreatSituation ("player", unit)
|
|
if (threatStatus) then
|
|
self:SetHealthBarColor (1, 0, 0)
|
|
return
|
|
end
|
|
end
|
|
|
|
--> get the regular color by selection
|
|
r, g, b = UnitSelectionColor (unit)
|
|
self:SetHealthBarColor (r, g, b)
|
|
end,
|
|
|
|
--> misc
|
|
UpdateName = function (self)
|
|
if (not self.Settings.ShowUnitName) then
|
|
return
|
|
end
|
|
|
|
--unit name without realm names by default
|
|
local name = UnitName (self.unit)
|
|
self.unitName:SetText (name)
|
|
self.unitName:Show()
|
|
end,
|
|
|
|
--> this runs when the player it self changes its target, need to update the current target overlay
|
|
--> todo: add focus overlay
|
|
UpdateTargetOverlay = function (self)
|
|
if (not self.Settings.ShowTargetOverlay) then
|
|
self.targetOverlay:Hide()
|
|
return
|
|
end
|
|
|
|
if (UnitIsUnit (self.displayedUnit, "target")) then
|
|
self.targetOverlay:Show()
|
|
else
|
|
self.targetOverlay:Hide()
|
|
end
|
|
end,
|
|
|
|
UpdateAllWidgets = function (self)
|
|
if (UnitExists (self.displayedUnit)) then
|
|
local unit = self.unit
|
|
local displayedUnit = self.displayedUnit
|
|
|
|
self:SetUnit (unit, displayedUnit)
|
|
|
|
--> is using castbars?
|
|
if (self.Settings.ShowCastBar) then
|
|
self.castBar:SetUnit (unit, displayedUnit)
|
|
end
|
|
|
|
--> is using powerbars?
|
|
if (self.Settings.ShowPowerBar) then
|
|
self.powerBar:SetUnit (unit, displayedUnit)
|
|
end
|
|
|
|
self:UpdateName()
|
|
self:UpdateTargetOverlay()
|
|
self:UpdateHealthColor()
|
|
end
|
|
end,
|
|
|
|
--> update the unit frame and its widgets
|
|
UpdateUnitFrame = function (self)
|
|
local unitInVehicle = self:CheckVehiclePossession()
|
|
|
|
--> if the unit is inside a vehicle, the vehicle possession function will call an update on all widgets
|
|
if (not unitInVehicle) then
|
|
self:UpdateAllWidgets()
|
|
end
|
|
end,
|
|
|
|
--> event handles
|
|
PLAYER_ENTERING_WORLD = function (self, ...)
|
|
self:UpdateUnitFrame()
|
|
end,
|
|
|
|
--> update overlays when the player changes its target
|
|
PLAYER_TARGET_CHANGED = function (self, ...)
|
|
self:UpdateTargetOverlay()
|
|
end,
|
|
|
|
--> unit received a name update
|
|
UNIT_NAME_UPDATE = function (self, ...)
|
|
self:UpdateName()
|
|
end,
|
|
|
|
--> this is registered only if .settings.ColorByAggro is true
|
|
UNIT_THREAT_LIST_UPDATE = function (self, ...)
|
|
if (self.Settings.ColorByAggro) then
|
|
self:UpdateHealthColor()
|
|
end
|
|
end,
|
|
|
|
--> vehicle
|
|
UNIT_ENTERED_VEHICLE = function (self, ...)
|
|
self:UpdateUnitFrame()
|
|
end,
|
|
UNIT_EXITED_VEHICLE = function (self, ...)
|
|
self:UpdateUnitFrame()
|
|
end,
|
|
|
|
--> pet
|
|
UNIT_PET = function (self, ...)
|
|
self:UpdateUnitFrame()
|
|
end,
|
|
|
|
--> player connection
|
|
UNIT_CONNECTION = function (self, ...)
|
|
if (UnitIsConnected (self.unit)) then
|
|
self:UpdateUnitFrame()
|
|
end
|
|
end,
|
|
PARTY_MEMBER_ENABLE = function (self, ...)
|
|
if (UnitIsConnected (self.unit)) then
|
|
self:UpdateName()
|
|
end
|
|
end,
|
|
}
|
|
|
|
-- ~unitframe
|
|
local globalBaseFrameLevel = 1 -- to be increased + used across each new plate
|
|
function DF:CreateUnitFrame (parent, name, unitFrameSettingsOverride, healthBarSettingsOverride, castBarSettingsOverride, powerBarSettingsOverride)
|
|
|
|
local parentName = name or ("DetailsFrameworkUnitFrame" .. tostring (math.random (1, 100000000)))
|
|
|
|
--> create the main unit frame
|
|
local f = CreateFrame ("button", parentName, parent, "BackdropTemplate")
|
|
|
|
--> base level
|
|
--local baseFrameLevel = f:GetFrameLevel()
|
|
local baseFrameLevel = globalBaseFrameLevel
|
|
globalBaseFrameLevel = globalBaseFrameLevel + 50
|
|
|
|
f:SetFrameLevel (baseFrameLevel)
|
|
|
|
--> create the healthBar
|
|
local healthBar = DF:CreateHealthBar (f, false, healthBarSettingsOverride)
|
|
healthBar:SetFrameLevel (baseFrameLevel + 1)
|
|
f.healthBar = healthBar
|
|
|
|
--> create the power bar
|
|
local powerBar = DF:CreatePowerBar (f, false, powerBarSettingsOverride)
|
|
powerBar:SetFrameLevel (baseFrameLevel + 2)
|
|
f.powerBar = powerBar
|
|
|
|
--> create the castBar
|
|
local castBar = DF:CreateCastBar (f, false, castBarSettingsOverride)
|
|
castBar:SetFrameLevel (baseFrameLevel + 3)
|
|
f.castBar = castBar
|
|
|
|
--> border frame
|
|
local borderFrame = DF:CreateBorderFrame (f, f:GetName() .. "Border")
|
|
borderFrame:SetFrameLevel (f:GetFrameLevel() + 5)
|
|
f.border = borderFrame
|
|
|
|
--> overlay frame (widgets that need to stay above the unit frame)
|
|
local overlayFrame = CreateFrame ("frame", "$parentOverlayFrame", f, "BackdropTemplate")
|
|
overlayFrame:SetFrameLevel (f:GetFrameLevel() + 6)
|
|
f.overlayFrame = overlayFrame
|
|
|
|
--> unit frame layers
|
|
do
|
|
--artwork
|
|
f.unitName = f:CreateFontString (nil, "artwork", "GameFontHighlightSmall")
|
|
PixelUtil.SetPoint (f.unitName, "topleft", healthBar, "topleft", 2, -2, 1, 1)
|
|
|
|
--target overlay - it's parented in the healthbar so other widgets won't get the overlay
|
|
f.targetOverlay = overlayFrame:CreateTexture (nil, "artwork")
|
|
f.targetOverlay:SetTexture (healthBar:GetTexture())
|
|
f.targetOverlay:SetBlendMode ("ADD")
|
|
f.targetOverlay:SetAlpha (.5)
|
|
f.targetOverlay:SetAllPoints (healthBar)
|
|
end
|
|
|
|
--> mixins
|
|
--inject mixins
|
|
DF:Mixin (f, DF.UnitFrameFunctions)
|
|
|
|
--create the settings table and copy the overrides into it, the table is set into the frame after the mixin
|
|
local unitFrameSettings = DF.table.copy ({}, DF.UnitFrameFunctions.Settings)
|
|
if (unitFrameSettingsOverride) then
|
|
unitFrameSettings = DF.table.copy (unitFrameSettings, unitFrameSettingsOverride)
|
|
end
|
|
f.Settings = unitFrameSettings
|
|
|
|
--> initialize scripts
|
|
--unitframe
|
|
f:Initialize()
|
|
|
|
return f
|
|
end
|
|
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> horizontal scroll frame
|
|
|
|
local timeline_options = {
|
|
width = 400,
|
|
height = 700,
|
|
line_height = 20,
|
|
line_padding = 1,
|
|
|
|
show_elapsed_timeline = true,
|
|
elapsed_timeline_height = 20,
|
|
|
|
--space to put the player/spell name and icons
|
|
header_width = 150,
|
|
|
|
--how many pixels will be use to represent 1 second
|
|
pixels_per_second = 20,
|
|
|
|
scale_min = 0.15,
|
|
scale_max = 1,
|
|
|
|
backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
backdrop_color = {0, 0, 0, 0.2},
|
|
backdrop_color_highlight = {.2, .2, .2, 0.4},
|
|
backdrop_border_color = {0.1, 0.1, 0.1, .2},
|
|
|
|
slider_backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
slider_backdrop_color = {0, 0, 0, 0.2},
|
|
slider_backdrop_border_color = {0.1, 0.1, 0.1, .2},
|
|
|
|
title_template = "ORANGE_FONT_TEMPLATE",
|
|
text_tempate = "OPTIONS_FONT_TEMPLATE",
|
|
|
|
on_enter = function (self)
|
|
self:SetBackdropColor (unpack (self.backdrop_color_highlight))
|
|
end,
|
|
on_leave = function (self)
|
|
self:SetBackdropColor (unpack (self.backdrop_color))
|
|
end,
|
|
|
|
block_on_enter = function (self)
|
|
|
|
end,
|
|
block_on_leave = function (self)
|
|
|
|
end,
|
|
}
|
|
|
|
local elapsedtime_frame_options = {
|
|
backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
backdrop_color = {.3, .3, .3, .7},
|
|
|
|
text_color = {1, 1, 1, 1},
|
|
text_size = 12,
|
|
text_font = "Arial Narrow",
|
|
text_outline = "NONE",
|
|
|
|
height = 20,
|
|
|
|
distance = 200, --distance in pixels between each label informing the time
|
|
distance_min = 50, --minimum distance in pixels
|
|
draw_line = true, --if true it'll draw a vertical line to represent a segment
|
|
draw_line_color = {1, 1, 1, 0.2},
|
|
draw_line_thickness = 1,
|
|
}
|
|
|
|
DF.TimeLineElapsedTimeFunctions = {
|
|
--get a label and update its appearance
|
|
GetLabel = function (self, index)
|
|
local label = self.labels [index]
|
|
|
|
if (not label) then
|
|
label = self:CreateFontString (nil, "artwork", "GameFontNormal")
|
|
label.line = self:CreateTexture (nil, "artwork")
|
|
label.line:SetColorTexture (1, 1, 1)
|
|
label.line:SetPoint ("topleft", label, "bottomleft", 0, -2)
|
|
self.labels [index] = label
|
|
end
|
|
|
|
DF:SetFontColor (label, self.options.text_color)
|
|
DF:SetFontSize (label, self.options.text_size)
|
|
DF:SetFontFace (label, self.options.text_font)
|
|
DF:SetFontOutline (label, self.options.text_outline)
|
|
|
|
if (self.options.draw_line) then
|
|
label.line:SetVertexColor (unpack (self.options.draw_line_color))
|
|
label.line:SetWidth (self.options.draw_line_thickness)
|
|
label.line:Show()
|
|
else
|
|
label.line:Hide()
|
|
end
|
|
|
|
return label
|
|
end,
|
|
|
|
Reset = function (self)
|
|
for i = 1, #self.labels do
|
|
self.labels [i]:Hide()
|
|
end
|
|
end,
|
|
|
|
Refresh = function (self, elapsedTime, scale)
|
|
local parent = self:GetParent()
|
|
|
|
self:SetHeight (self.options.height)
|
|
local effectiveArea = self:GetWidth() --already scaled down width
|
|
local pixelPerSecond = elapsedTime / effectiveArea --how much 1 pixels correlate to time
|
|
|
|
local distance = self.options.distance --pixels between each segment
|
|
local minDistance = self.options.distance_min --min pixels between each segment
|
|
|
|
--scale the distance between each label showing the time with the parent's scale
|
|
distance = distance * scale
|
|
distance = max (distance, minDistance)
|
|
|
|
local amountSegments = ceil (effectiveArea / distance)
|
|
|
|
for i = 1, amountSegments do
|
|
local label = self:GetLabel (i)
|
|
local xOffset = distance * (i - 1)
|
|
label:SetPoint ("left", self, "left", xOffset, 0)
|
|
|
|
local secondsOfTime = pixelPerSecond * xOffset
|
|
|
|
label:SetText (DF:IntegerToTimer (floor (secondsOfTime)))
|
|
|
|
if (label.line:IsShown()) then
|
|
label.line:SetHeight (parent:GetParent():GetHeight())
|
|
end
|
|
|
|
label:Show()
|
|
end
|
|
end,
|
|
}
|
|
|
|
--creates a frame to show the elapsed time in a row
|
|
function DF:CreateElapsedTimeFrame (parent, name, options)
|
|
local elapsedTimeFrame = CreateFrame ("frame", name, parent, "BackdropTemplate")
|
|
|
|
DF:Mixin (elapsedTimeFrame, DF.OptionsFunctions)
|
|
DF:Mixin (elapsedTimeFrame, DF.LayoutFrame)
|
|
|
|
elapsedTimeFrame:BuildOptionsTable (elapsedtime_frame_options, options)
|
|
|
|
DF:Mixin (elapsedTimeFrame, DF.TimeLineElapsedTimeFunctions)
|
|
|
|
elapsedTimeFrame:SetBackdrop (elapsedTimeFrame.options.backdrop)
|
|
elapsedTimeFrame:SetBackdropColor (unpack (elapsedTimeFrame.options.backdrop_color))
|
|
|
|
elapsedTimeFrame.labels = {}
|
|
|
|
return elapsedTimeFrame
|
|
end
|
|
|
|
|
|
DF.TimeLineBlockFunctions = {
|
|
--self is the line
|
|
SetBlock = function (self, index, blockInfo)
|
|
--get the block information
|
|
--see what is the current scale
|
|
--adjust the block position
|
|
|
|
local block = self:GetBlock (index)
|
|
|
|
--need:
|
|
--the total time of the timeline
|
|
--the current scale of the timeline
|
|
--the elapsed time of this block
|
|
--icon of the block
|
|
--text
|
|
--background color
|
|
|
|
end,
|
|
|
|
SetBlocksFromData = function (self)
|
|
local parent = self:GetParent():GetParent()
|
|
local data = parent.data
|
|
local defaultColor = parent.defaultColor --guarantee to have a value
|
|
|
|
self:Show()
|
|
|
|
--none of these values are scaled, need to calculate
|
|
local pixelPerSecond = parent.pixelPerSecond
|
|
local totalLength = parent.totalLength
|
|
local scale = parent.currentScale
|
|
|
|
pixelPerSecond = pixelPerSecond * scale
|
|
|
|
local headerWidth = parent.headerWidth
|
|
|
|
--dataIndex stores which line index from the data this line will use
|
|
--lineData store members: .text .icon .timeline
|
|
local lineData = data.lines [self.dataIndex]
|
|
|
|
--if there's an icon, anchor the text at the right side of the icon
|
|
--this is the title and icon of the title
|
|
if (lineData.icon) then
|
|
self.icon:SetTexture (lineData.icon)
|
|
self.icon:SetTexCoord (.1, .9, .1, .9)
|
|
self.text:SetText (lineData.text or "")
|
|
self.text:SetPoint ("left", self.icon.widget, "right", 2, 0)
|
|
else
|
|
self.icon:SetTexture (nil)
|
|
self.text:SetText (lineData.text or "")
|
|
self.text:SetPoint ("left", self, "left", 2, 0)
|
|
end
|
|
|
|
if (self.dataIndex % 2 == 1) then
|
|
self:SetBackdropColor (0, 0, 0, 0)
|
|
else
|
|
local r, g, b, a = unpack (self.backdrop_color)
|
|
self:SetBackdropColor (r, g, b, a)
|
|
end
|
|
|
|
self:SetWidth(5000)
|
|
|
|
local timelineData = lineData.timeline
|
|
local spellId = lineData.spellId
|
|
local useIconOnBlock = data.useIconOnBlocks
|
|
|
|
local baseFrameLevel = parent:GetFrameLevel() + 10
|
|
|
|
for i = 1, #timelineData do
|
|
local blockInfo = timelineData [i]
|
|
|
|
local time = blockInfo [1]
|
|
local length = blockInfo [2]
|
|
local isAura = blockInfo [3]
|
|
local auraDuration = blockInfo [4]
|
|
|
|
local payload = blockInfo.payload
|
|
|
|
local xOffset = pixelPerSecond * time
|
|
local width = pixelPerSecond * length
|
|
|
|
if (time < -0.2) then
|
|
xOffset = xOffset / 2.5
|
|
end
|
|
|
|
local block = self:GetBlock(i)
|
|
block:Show()
|
|
block:SetFrameLevel(baseFrameLevel + i)
|
|
|
|
PixelUtil.SetPoint(block, "left", self, "left", xOffset + headerWidth, 0)
|
|
|
|
block.info.spellId = spellId
|
|
block.info.time = time
|
|
block.info.duration = auraDuration
|
|
block.info.payload = payload
|
|
|
|
if (useIconOnBlock) then
|
|
block.icon:SetTexture (lineData.icon)
|
|
block.icon:SetTexCoord (.1, .9, .1, .9)
|
|
block.icon:SetAlpha (.834)
|
|
block.icon:SetSize (self:GetHeight(), self:GetHeight())
|
|
|
|
if (time < -0.2) then
|
|
block.icon:SetDesaturated (true)
|
|
else
|
|
block.icon:SetDesaturated (false)
|
|
end
|
|
|
|
PixelUtil.SetSize (block, self:GetHeight(), self:GetHeight())
|
|
|
|
if (isAura) then
|
|
block.auraLength:Show()
|
|
block.auraLength:SetWidth (pixelPerSecond * isAura)
|
|
block:SetWidth (max (pixelPerSecond * isAura, 16))
|
|
else
|
|
block.auraLength:Hide()
|
|
end
|
|
|
|
block.background:SetVertexColor (0, 0, 0, 0)
|
|
else
|
|
block.background:SetVertexColor (unpack (color))
|
|
PixelUtil.SetSize (block, max (width, 16), self:GetHeight())
|
|
block.auraLength:Hide()
|
|
end
|
|
end
|
|
end,
|
|
|
|
GetBlock = function (self, index)
|
|
local block = self.blocks [index]
|
|
if (not block) then
|
|
block = CreateFrame ("frame", nil, self, "BackdropTemplate")
|
|
self.blocks [index] = block
|
|
|
|
local background = block:CreateTexture (nil, "background")
|
|
background:SetColorTexture (1, 1, 1, 1)
|
|
local icon = block:CreateTexture (nil, "artwork")
|
|
local text = block:CreateFontString (nil, "artwork")
|
|
local auraLength = block:CreateTexture (nil, "border")
|
|
|
|
background:SetAllPoints()
|
|
icon:SetPoint ("left")
|
|
text:SetPoint ("left", icon, "left", 2, 0)
|
|
auraLength:SetPoint ("topleft", icon, "topleft", 0, 0)
|
|
auraLength:SetPoint ("bottomleft", icon, "bottomleft", 0, 0)
|
|
auraLength:SetColorTexture (1, 1, 1, 1)
|
|
auraLength:SetVertexColor (1, 1, 1, 0.1)
|
|
|
|
block.icon = icon
|
|
block.text = text
|
|
block.background = background
|
|
block.auraLength = auraLength
|
|
|
|
block:SetScript ("OnEnter", self:GetParent():GetParent().options.block_on_enter)
|
|
block:SetScript ("OnLeave", self:GetParent():GetParent().options.block_on_leave)
|
|
|
|
block:SetMouseClickEnabled (false)
|
|
block.info = {}
|
|
end
|
|
|
|
return block
|
|
end,
|
|
|
|
Reset = function (self)
|
|
--attention, it doesn't reset icon texture, text and background color
|
|
for i = 1, #self.blocks do
|
|
self.blocks [i]:Hide()
|
|
end
|
|
self:Hide()
|
|
end,
|
|
}
|
|
|
|
DF.TimeLineFunctions = {
|
|
|
|
GetLine = function (self, index)
|
|
local line = self.lines [index]
|
|
if (not line) then
|
|
--create a new line
|
|
line = CreateFrame ("frame", "$parentLine" .. index, self.body, "BackdropTemplate")
|
|
DF:Mixin (line, DF.TimeLineBlockFunctions)
|
|
self.lines [index] = line
|
|
|
|
--store the individual textures that shows the timeline information
|
|
line.blocks = {}
|
|
line.SetBlock = DF.TimeLineBlockFunctions.SetBlock
|
|
line.GetBlock = DF.TimeLineBlockFunctions.GetBlock
|
|
|
|
--set its parameters
|
|
|
|
if (self.options.show_elapsed_timeline) then
|
|
line:SetPoint ("topleft", self.body, "topleft", 1, -((index-1) * (self.options.line_height + 1)) - 2 - self.options.elapsed_timeline_height)
|
|
else
|
|
line:SetPoint ("topleft", self.body, "topleft", 1, -((index-1) * (self.options.line_height + 1)) - 1)
|
|
end
|
|
line:SetSize (1, self.options.line_height) --width is set when updating the frame
|
|
|
|
line:SetScript ("OnEnter", self.options.on_enter)
|
|
line:SetScript ("OnLeave", self.options.on_leave)
|
|
line:SetMouseClickEnabled (false)
|
|
|
|
line:SetBackdrop (self.options.backdrop)
|
|
line:SetBackdropColor (unpack (self.options.backdrop_color))
|
|
line:SetBackdropBorderColor (unpack (self.options.backdrop_border_color))
|
|
|
|
local icon = DF:CreateImage (line, "", self.options.line_height, self.options.line_height)
|
|
icon:SetPoint ("left", line, "left", 2, 0)
|
|
line.icon = icon
|
|
|
|
local text = DF:CreateLabel (line, "", DF:GetTemplate ("font", self.options.title_template))
|
|
text:SetPoint ("left", icon.widget, "right", 2, 0)
|
|
line.text = text
|
|
|
|
line.backdrop_color = self.options.backdrop_color or {.1, .1, .1, .3}
|
|
line.backdrop_color_highlight = self.options.backdrop_color_highlight or {.3, .3, .3, .5}
|
|
end
|
|
|
|
return line
|
|
end,
|
|
|
|
ResetAllLines = function (self)
|
|
for i = 1, #self.lines do
|
|
self.lines [i]:Reset()
|
|
end
|
|
end,
|
|
|
|
AdjustScale = function (self, index)
|
|
|
|
end,
|
|
|
|
--todo
|
|
--make the on enter and leave tooltips
|
|
--set icons and texts
|
|
--skin the sliders
|
|
|
|
RefreshTimeLine = function (self)
|
|
|
|
--debug
|
|
--self.currentScale = 1
|
|
|
|
--calculate the total width
|
|
local pixelPerSecond = self.options.pixels_per_second
|
|
local totalLength = self.data.length or 1
|
|
local currentScale = self.currentScale
|
|
|
|
self.scaleSlider:Enable()
|
|
|
|
--how many pixels represent 1 second
|
|
local bodyWidth = totalLength * pixelPerSecond * currentScale
|
|
self.body:SetWidth (bodyWidth + self.options.header_width)
|
|
self.body.effectiveWidth = bodyWidth
|
|
|
|
--reduce the default canvas size from the body with and don't allow the max value be negative
|
|
local newMaxValue = max (bodyWidth - (self:GetWidth() - self.options.header_width), 0)
|
|
|
|
--adjust the scale slider range
|
|
local oldMin, oldMax = self.horizontalSlider:GetMinMaxValues()
|
|
self.horizontalSlider:SetMinMaxValues (0, newMaxValue)
|
|
self.horizontalSlider:SetValue (DF:MapRangeClamped (oldMin, oldMax, 0, newMaxValue, self.horizontalSlider:GetValue()))
|
|
|
|
local defaultColor = self.data.defaultColor or {1, 1, 1, 1}
|
|
|
|
--cache values
|
|
self.pixelPerSecond = pixelPerSecond
|
|
self.totalLength = totalLength
|
|
self.defaultColor = defaultColor
|
|
self.headerWidth = self.options.header_width
|
|
|
|
--calculate the total height
|
|
local lineHeight = self.options.line_height
|
|
local linePadding = self.options.line_padding
|
|
|
|
local bodyHeight = (lineHeight + linePadding) * #self.data.lines
|
|
self.body:SetHeight (bodyHeight)
|
|
self.verticalSlider:SetMinMaxValues (0, max (bodyHeight - self:GetHeight(), 0))
|
|
self.verticalSlider:SetValue (0)
|
|
|
|
--refresh lines
|
|
self:ResetAllLines()
|
|
for i = 1, #self.data.lines do
|
|
local line = self:GetLine (i)
|
|
line.dataIndex = i --this index is used inside the line update function to know which data to get
|
|
line:SetBlocksFromData() --the function to update runs within the line object
|
|
end
|
|
|
|
--refresh elapsed time frame
|
|
--the elapsed frame must have a width before the refresh function is called
|
|
self.elapsedTimeFrame:ClearAllPoints()
|
|
self.elapsedTimeFrame:SetPoint ("topleft", self.body, "topleft", self.options.header_width, 0)
|
|
self.elapsedTimeFrame:SetPoint ("topright", self.body, "topright", 0, 0)
|
|
self.elapsedTimeFrame:Reset()
|
|
|
|
self.elapsedTimeFrame:Refresh (self.data.length, self.currentScale)
|
|
end,
|
|
|
|
SetData = function (self, data)
|
|
self.data = data
|
|
self:RefreshTimeLine()
|
|
end,
|
|
|
|
}
|
|
|
|
--creates a regular scroll in horizontal position
|
|
function DF:CreateTimeLineFrame (parent, name, options, timelineOptions)
|
|
|
|
local width = options and options.width or timeline_options.width
|
|
local height = options and options.height or timeline_options.height
|
|
local scrollWidth = 800 --placeholder until the timeline receives data
|
|
local scrollHeight = 800 --placeholder until the timeline receives data
|
|
|
|
local frameCanvas = CreateFrame ("scrollframe", name, parent, "BackdropTemplate")
|
|
DF:Mixin (frameCanvas, DF.TimeLineFunctions)
|
|
|
|
frameCanvas.data = {}
|
|
frameCanvas.lines = {}
|
|
frameCanvas.currentScale = 0.5
|
|
frameCanvas:SetSize (width, height)
|
|
frameCanvas:SetBackdrop({
|
|
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background",
|
|
tile = true, tileSize = 16,
|
|
insets = {left = 1, right = 1, top = 0, bottom = 1},})
|
|
frameCanvas:SetBackdropColor (.1, .1, .1, .3)
|
|
|
|
local frameBody = CreateFrame ("frame", nil, frameCanvas, "BackdropTemplate")
|
|
frameBody:SetSize (scrollWidth, scrollHeight)
|
|
|
|
frameCanvas:SetScrollChild (frameBody)
|
|
frameCanvas.body = frameBody
|
|
|
|
DF:Mixin (frameCanvas, DF.OptionsFunctions)
|
|
DF:Mixin (frameCanvas, DF.LayoutFrame)
|
|
|
|
frameCanvas:BuildOptionsTable (timeline_options, options)
|
|
|
|
--create elapsed time frame
|
|
frameCanvas.elapsedTimeFrame = DF:CreateElapsedTimeFrame (frameBody, frameCanvas:GetName() and frameCanvas:GetName() .. "ElapsedTimeFrame", timelineOptions)
|
|
|
|
--create horizontal slider
|
|
local horizontalSlider = CreateFrame ("slider", nil, parent, "BackdropTemplate")
|
|
horizontalSlider.bg = horizontalSlider:CreateTexture (nil, "background")
|
|
horizontalSlider.bg:SetAllPoints (true)
|
|
horizontalSlider.bg:SetTexture (0, 0, 0, 0.5)
|
|
|
|
horizontalSlider:SetBackdrop (frameCanvas.options.slider_backdrop)
|
|
horizontalSlider:SetBackdropColor (unpack (frameCanvas.options.slider_backdrop_color))
|
|
horizontalSlider:SetBackdropBorderColor (unpack(frameCanvas.options.slider_backdrop_border_color))
|
|
|
|
horizontalSlider.thumb = horizontalSlider:CreateTexture (nil, "OVERLAY")
|
|
horizontalSlider.thumb:SetTexture ([[Interface\AddOns\Details\images\icons2]])
|
|
horizontalSlider.thumb:SetTexCoord (478/512, 496/512, 104/512, 120/512)
|
|
horizontalSlider.thumb:SetSize (20, 18)
|
|
horizontalSlider.thumb:SetVertexColor (0.6, 0.6, 0.6, 0.95)
|
|
|
|
horizontalSlider:SetThumbTexture (horizontalSlider.thumb)
|
|
horizontalSlider:SetOrientation ("horizontal")
|
|
horizontalSlider:SetSize (width + 20, 20)
|
|
horizontalSlider:SetPoint ("topleft", frameCanvas, "bottomleft")
|
|
horizontalSlider:SetMinMaxValues (0, scrollWidth)
|
|
horizontalSlider:SetValue (0)
|
|
horizontalSlider:SetScript ("OnValueChanged", function (self)
|
|
local _, maxValue = horizontalSlider:GetMinMaxValues()
|
|
local stepValue = ceil (ceil(self:GetValue() * maxValue) / max(maxValue, SMALL_FLOAT))
|
|
if (stepValue ~= horizontalSlider.currentValue) then
|
|
horizontalSlider.currentValue = stepValue
|
|
frameCanvas:SetHorizontalScroll (stepValue)
|
|
end
|
|
end)
|
|
|
|
frameCanvas.horizontalSlider = horizontalSlider
|
|
|
|
--create scale slider
|
|
local scaleSlider = CreateFrame ("slider", nil, parent, "BackdropTemplate")
|
|
scaleSlider.bg = scaleSlider:CreateTexture (nil, "background")
|
|
scaleSlider.bg:SetAllPoints (true)
|
|
scaleSlider.bg:SetTexture (0, 0, 0, 0.5)
|
|
scaleSlider:Disable()
|
|
frameCanvas.scaleSlider = scaleSlider
|
|
|
|
scaleSlider:SetBackdrop (frameCanvas.options.slider_backdrop)
|
|
scaleSlider:SetBackdropColor (unpack (frameCanvas.options.slider_backdrop_color))
|
|
scaleSlider:SetBackdropBorderColor (unpack(frameCanvas.options.slider_backdrop_border_color))
|
|
|
|
scaleSlider.thumb = scaleSlider:CreateTexture (nil, "OVERLAY")
|
|
scaleSlider.thumb:SetTexture ([[Interface\AddOns\Details\images\icons2]])
|
|
scaleSlider.thumb:SetTexCoord (478/512, 496/512, 104/512, 120/512)
|
|
scaleSlider.thumb:SetSize (20, 18)
|
|
scaleSlider.thumb:SetVertexColor (0.6, 0.6, 0.6, 0.95)
|
|
|
|
scaleSlider:SetThumbTexture (scaleSlider.thumb)
|
|
scaleSlider:SetOrientation ("horizontal")
|
|
scaleSlider:SetSize (width + 20, 20)
|
|
scaleSlider:SetPoint ("topleft", horizontalSlider, "bottomleft", 0, -2)
|
|
scaleSlider:SetMinMaxValues (frameCanvas.options.scale_min, frameCanvas.options.scale_max)
|
|
scaleSlider:SetValue (DF:GetRangeValue (frameCanvas.options.scale_min, frameCanvas.options.scale_max, 0.5))
|
|
|
|
scaleSlider:SetScript ("OnValueChanged", function (self)
|
|
local stepValue = ceil(self:GetValue() * 100)/100
|
|
if (stepValue ~= frameCanvas.currentScale) then
|
|
local current = stepValue
|
|
frameCanvas.currentScale = stepValue
|
|
frameCanvas:RefreshTimeLine()
|
|
end
|
|
end)
|
|
|
|
--create vertical slider
|
|
local verticalSlider = CreateFrame ("slider", nil, parent, "BackdropTemplate")
|
|
verticalSlider.bg = verticalSlider:CreateTexture (nil, "background")
|
|
verticalSlider.bg:SetAllPoints (true)
|
|
verticalSlider.bg:SetTexture (0, 0, 0, 0.5)
|
|
|
|
verticalSlider:SetBackdrop (frameCanvas.options.slider_backdrop)
|
|
verticalSlider:SetBackdropColor (unpack (frameCanvas.options.slider_backdrop_color))
|
|
verticalSlider:SetBackdropBorderColor (unpack(frameCanvas.options.slider_backdrop_border_color))
|
|
|
|
verticalSlider.thumb = verticalSlider:CreateTexture (nil, "OVERLAY")
|
|
verticalSlider.thumb:SetTexture ([[Interface\AddOns\Details\images\icons2]])
|
|
verticalSlider.thumb:SetTexCoord (482/512, 492/512, 104/512, 120/512)
|
|
verticalSlider.thumb:SetSize (12, 12)
|
|
verticalSlider.thumb:SetVertexColor (0.6, 0.6, 0.6, 0.95)
|
|
|
|
verticalSlider:SetThumbTexture (verticalSlider.thumb)
|
|
verticalSlider:SetOrientation ("vertical")
|
|
verticalSlider:SetSize (20, height - 2)
|
|
verticalSlider:SetPoint ("topleft", frameCanvas, "topright", 0, 0)
|
|
verticalSlider:SetMinMaxValues (0, scrollHeight)
|
|
verticalSlider:SetValue (0)
|
|
verticalSlider:SetScript ("OnValueChanged", function (self)
|
|
frameCanvas:SetVerticalScroll (self:GetValue())
|
|
end)
|
|
|
|
frameCanvas.verticalSlider = verticalSlider
|
|
|
|
--mouse scroll
|
|
frameCanvas:EnableMouseWheel (true)
|
|
frameCanvas:SetScript ("OnMouseWheel", function (self, delta)
|
|
local minValue, maxValue = horizontalSlider:GetMinMaxValues()
|
|
local currentHorizontal = horizontalSlider:GetValue()
|
|
|
|
if (IsShiftKeyDown() and delta < 0) then
|
|
local amountToScroll = frameBody:GetHeight() / 20
|
|
verticalSlider:SetValue (verticalSlider:GetValue() + amountToScroll)
|
|
|
|
elseif (IsShiftKeyDown() and delta > 0) then
|
|
local amountToScroll = frameBody:GetHeight() / 20
|
|
verticalSlider:SetValue (verticalSlider:GetValue() - amountToScroll)
|
|
|
|
elseif (IsControlKeyDown() and delta > 0) then
|
|
scaleSlider:SetValue (min (scaleSlider:GetValue() + 0.1, 1))
|
|
|
|
elseif (IsControlKeyDown() and delta < 0) then
|
|
scaleSlider:SetValue (max (scaleSlider:GetValue() - 0.1, 0.15))
|
|
|
|
elseif (delta < 0 and currentHorizontal < maxValue) then
|
|
local amountToScroll = frameBody:GetWidth() / 20
|
|
horizontalSlider:SetValue (currentHorizontal + amountToScroll)
|
|
|
|
elseif (delta > 0 and maxValue > 1) then
|
|
local amountToScroll = frameBody:GetWidth() / 20
|
|
horizontalSlider:SetValue (currentHorizontal - amountToScroll)
|
|
|
|
end
|
|
end)
|
|
|
|
--mouse drag
|
|
frameBody:SetScript ("OnMouseDown", function (self, button)
|
|
local x = GetCursorPosition()
|
|
self.MouseX = x
|
|
|
|
frameBody:SetScript ("OnUpdate", function (self, deltaTime)
|
|
local x = GetCursorPosition()
|
|
local deltaX = self.MouseX - x
|
|
local current = horizontalSlider:GetValue()
|
|
horizontalSlider:SetValue (current + (deltaX * 1.2) * ((IsShiftKeyDown() and 2) or (IsAltKeyDown() and 0.5) or 1))
|
|
self.MouseX = x
|
|
end)
|
|
end)
|
|
frameBody:SetScript ("OnMouseUp", function (self, button)
|
|
frameBody:SetScript ("OnUpdate", nil)
|
|
end)
|
|
|
|
return frameCanvas
|
|
end
|
|
|
|
|
|
--[=[
|
|
local f = CreateFrame ("frame", "TestFrame", UIParent)
|
|
f:SetPoint ("center")
|
|
f:SetSize (900, 420)
|
|
f:SetBackdrop({bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", tile = true, tileSize = 16, insets = {left = 1, right = 1, top = 0, bottom = 1}})
|
|
|
|
local scroll = DF:CreateTimeLineFrame (f, "$parentTimeLine", {width = 880, height = 400})
|
|
scroll:SetPoint ("topleft", f, "topleft", 0, 0)
|
|
|
|
--need fake data to test fills
|
|
scroll:SetData ({
|
|
length = 360,
|
|
defaultColor = {1, 1, 1, 1},
|
|
lines = {
|
|
{text = "player 1", icon = "", timeline = {
|
|
--each table here is a block shown in the line
|
|
--is an indexed table with: [1] time [2] length [3] color (if false, use the default) [4] text [5] icon [6] tooltip: if number = spellID tooltip, if table is text lines
|
|
{1, 10}, {13, 11}, {25, 7}, {36, 5}, {55, 18}, {76, 30}, {105, 20}, {130, 11}, {155, 11}, {169, 7}, {199, 16}, {220, 18}, {260, 10}, {290, 23}, {310, 30}, {350, 10}
|
|
}
|
|
}, --end of line 1
|
|
},
|
|
})
|
|
|
|
|
|
f:Hide()
|
|
|
|
--scroll.body:SetScale (0.5)
|
|
|
|
--]=]
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> error message box
|
|
|
|
function DF:ShowErrorMessage (errorMessage, titleText)
|
|
|
|
if (not DF.ErrorMessagePanel) then
|
|
local f = CreateFrame ("frame", "DetailsFrameworkErrorMessagePanel", UIParent, "BackdropTemplate")
|
|
f:SetSize (400, 120)
|
|
f:SetFrameStrata ("FULLSCREEN")
|
|
f:SetPoint ("center", UIParent, "center", 0, 100)
|
|
f:EnableMouse (true)
|
|
f:SetMovable (true)
|
|
f:RegisterForDrag ("LeftButton")
|
|
f:SetScript ("OnDragStart", function() f:StartMoving() end)
|
|
f:SetScript ("OnDragStop", function() f:StopMovingOrSizing() end)
|
|
f:SetScript ("OnMouseDown", function (self, button) if (button == "RightButton") then f:Hide() end end)
|
|
tinsert (UISpecialFrames, "DetailsFrameworkErrorMessagePanel")
|
|
DF.ErrorMessagePanel = f
|
|
|
|
DF:CreateTitleBar (f, "Details! Framework Error!")
|
|
DF:ApplyStandardBackdrop (f)
|
|
|
|
local errorLabel = f:CreateFontString (nil, "overlay", "GameFontNormal")
|
|
errorLabel:SetPoint ("top", f, "top", 0, -25)
|
|
errorLabel:SetJustifyH ("center")
|
|
errorLabel:SetSize (360, 66)
|
|
f.errorLabel = errorLabel
|
|
|
|
local button_text_template = DF:GetTemplate ("font", "OPTIONS_FONT_TEMPLATE")
|
|
local options_dropdown_template = DF:GetTemplate ("dropdown", "OPTIONS_DROPDOWN_TEMPLATE")
|
|
|
|
local closeButton = DF:CreateButton (f, nil, 60, 20, "close", nil, nil, nil, nil, nil, nil, options_dropdown_template)
|
|
closeButton:SetPoint ("bottom", f, "bottom", 0, 5)
|
|
f.closeButton = closeButton
|
|
|
|
closeButton:SetClickFunction (function()
|
|
f:Hide()
|
|
end)
|
|
|
|
f.ShowAnimation = DF:CreateAnimationHub (f, function()
|
|
f:SetBackdropBorderColor (0, 0, 0, 0)
|
|
f.TitleBar:SetBackdropBorderColor (0, 0, 0, 0)
|
|
end, function()
|
|
f:SetBackdropBorderColor (0, 0, 0, 1)
|
|
f.TitleBar:SetBackdropBorderColor (0, 0, 0, 1)
|
|
end)
|
|
DF:CreateAnimation (f.ShowAnimation, "scale", 1, .075, .2, .2, 1.1, 1.1, "center", 0, 0)
|
|
DF:CreateAnimation (f.ShowAnimation, "scale", 2, .075, 1, 1, .90, .90, "center", 0, 0)
|
|
|
|
f.FlashTexture = f:CreateTexture (nil, "overlay")
|
|
f.FlashTexture:SetColorTexture (1, 1, 1, 1)
|
|
f.FlashTexture:SetAllPoints()
|
|
|
|
f.FlashAnimation = DF:CreateAnimationHub (f.FlashTexture, function() f.FlashTexture:Show() end, function() f.FlashTexture:Hide() end)
|
|
DF:CreateAnimation (f.FlashAnimation, "alpha", 1, .075, 0, .05)
|
|
DF:CreateAnimation (f.FlashAnimation, "alpha", 2, .075, .1, 0)
|
|
|
|
f:Hide()
|
|
end
|
|
|
|
DF.ErrorMessagePanel:Show()
|
|
DF.ErrorMessagePanel.errorLabel:SetText (errorMessage)
|
|
DF.ErrorMessagePanel.TitleLabel:SetText (titleText)
|
|
DF.ErrorMessagePanel.ShowAnimation:Play()
|
|
DF.ErrorMessagePanel.FlashAnimation:Play()
|
|
end
|
|
|
|
--[[
|
|
DF:SetPointOffsets(frame, xOffset, yOffset)
|
|
|
|
Set an offset into the already existing offset of the frame
|
|
If passed xOffset:1 and yOffset:1 and the frame has 1 -1, the new offset will be 2 -2
|
|
This function is great to create a 1 knob for distance
|
|
|
|
@frame: a frame to have the offsets changed
|
|
@xOffset: the amount to apply into the x offset
|
|
@yOffset: the amount to apply into the y offset
|
|
--]]
|
|
function DF:SetPointOffsets(frame, xOffset, yOffset)
|
|
for i = 1, frame:GetNumPoints() do
|
|
local anchor1, anchorTo, anchor2, x, y = frame:GetPoint(i)
|
|
x = x or 0
|
|
y = y or 0
|
|
|
|
if (x >= 0) then
|
|
xOffset = x + xOffset
|
|
|
|
elseif (x < 0) then
|
|
xOffset = x - xOffset
|
|
end
|
|
|
|
if (y >= 0) then
|
|
yOffset = y + yOffset
|
|
|
|
elseif (y < 0) then
|
|
yOffset = y - yOffset
|
|
end
|
|
|
|
frame:SetPoint(anchor1, anchorTo, anchor2, xOffset, yOffset)
|
|
end
|
|
end
|
|
|
|
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
--> list box
|
|
|
|
DF.ListboxFunctions = {
|
|
scrollRefresh = function(self, data, offset, totalLines)
|
|
for i = 1, totalLines do
|
|
local index = i + offset
|
|
local lineData = data[index] --what is shown in the textentries, array
|
|
|
|
if (lineData) then
|
|
local line = self:GetLine(i)
|
|
line.dataIndex = index
|
|
line.deleteButton:SetClickFunction(DF.ListboxFunctions.deleteEntry, data, index)
|
|
line.indexText:SetText(index)
|
|
|
|
local amountEntries = #lineData
|
|
for o = 1, amountEntries do
|
|
--data
|
|
local textEntry = line.widgets[o]
|
|
textEntry.dataTable = lineData
|
|
textEntry.dataTableIndex = o
|
|
local text = lineData[o]
|
|
textEntry:SetText(text)
|
|
end
|
|
end
|
|
end
|
|
end,
|
|
|
|
addEntry = function(self)
|
|
local frameCanvas = self:GetParent()
|
|
local data = frameCanvas.data
|
|
local newEntry = {}
|
|
for i = 1, frameCanvas.headerLength do
|
|
tinsert(newEntry, "")
|
|
end
|
|
tinsert(data, newEntry)
|
|
frameCanvas.scrollBox:Refresh()
|
|
end,
|
|
|
|
deleteEntry = function(self, button, data, index)
|
|
tremove(data, index)
|
|
--get the line, get the scrollframe
|
|
self:GetParent():GetParent():Refresh()
|
|
end,
|
|
|
|
createScrollLine = function(self, index)
|
|
local listBox = self:GetParent()
|
|
local line = CreateFrame("frame", self:GetName().. "line_" .. index, self, "BackdropTemplate")
|
|
|
|
line:SetPoint("topleft", self, "topleft", 1, -((index-1)*(self.lineHeight+1)) - 1)
|
|
line:SetSize(self:GetWidth() - 28, self.lineHeight) -- -28 space for the scrollbar
|
|
|
|
local options = listBox.options
|
|
line:SetBackdrop(options.line_backdrop)
|
|
line:SetBackdropColor(unpack(options.line_backdrop_color))
|
|
line:SetBackdropBorderColor(unpack(options.line_backdrop_border_color))
|
|
|
|
DF:Mixin(line, DF.HeaderFunctions)
|
|
|
|
line.widgets = {}
|
|
|
|
for i = 1, (listBox.headerLength+2) do --+2 to add the delete button and index
|
|
local headerColumn = listBox.headerTable[i]
|
|
|
|
if (headerColumn.isDelete) then
|
|
local deleteButton = DF:CreateButton(line, DF.ListboxFunctions.deleteEntry, 20, self.lineHeight, "X", listBox.data, index, nil, nil, nil, nil, DF:GetTemplate ("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate ("font", "ORANGE_FONT_TEMPLATE"))
|
|
line.deleteButton = deleteButton
|
|
line:AddFrameToHeaderAlignment(deleteButton)
|
|
|
|
elseif (headerColumn.isIndex) then
|
|
local indexText = DF:CreateLabel(line)
|
|
line.indexText = indexText
|
|
line:AddFrameToHeaderAlignment(indexText)
|
|
|
|
elseif (headerColumn.text) then
|
|
local template = DF.table.copy({}, DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
|
|
template.backdropcolor = {.1, .1, .1, .7}
|
|
template.backdropbordercolor = {.2, .2, .2, .6}
|
|
|
|
local textEntry = DF:CreateTextEntry(line, function()end, headerColumn.width, self.lineHeight, nil, nil, nil, template)
|
|
textEntry:SetHook("OnEditFocusGained", function() textEntry:HighlightText(0) end)
|
|
textEntry:SetHook("OnEditFocusLost", function()
|
|
textEntry:HighlightText(0, 0)
|
|
local text = textEntry.text
|
|
local dataTable = textEntry.dataTable
|
|
dataTable[textEntry.dataTableIndex] = text
|
|
end)
|
|
tinsert(line.widgets, textEntry)
|
|
line:AddFrameToHeaderAlignment(textEntry)
|
|
end
|
|
end
|
|
|
|
line:AlignWithHeader(listBox.header, "left")
|
|
return line
|
|
end,
|
|
|
|
SetData = function(frameCanvas, newData)
|
|
if (type(newData) ~= "table") then
|
|
error("ListBox:SetData received an invalid newData on parameter 2.")
|
|
return
|
|
end
|
|
|
|
frameCanvas.data = newData
|
|
frameCanvas.scrollBox:SetData(newData)
|
|
frameCanvas.scrollBox:Refresh()
|
|
end,
|
|
}
|
|
|
|
local listbox_options = {
|
|
width = 800,
|
|
height = 600,
|
|
auto_width = true,
|
|
line_height = 16,
|
|
line_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
|
|
line_backdrop_color = {.1, .1, .1, .6},
|
|
line_backdrop_border_color = {0, 0, 0, .5},
|
|
}
|
|
|
|
--@parent: parent frame
|
|
--@name: name of the frame to be created
|
|
--@data: table with current data to fill the column, this table are also used for values changed or added
|
|
--@options: table with options to overwrite the default setting from 'listbox_options'
|
|
--@header: a table to create a header widget
|
|
--@header_options: a table with options to overwrite the default header options
|
|
function DF:CreateListBox(parent, name, data, options, headerTable, headerOptions)
|
|
|
|
options = options or {}
|
|
name = name or "ListboxUnamed_" .. (math.random(100000, 1000000))
|
|
|
|
--canvas
|
|
local frameCanvas = CreateFrame("scrollframe", name, parent, "BackdropTemplate")
|
|
DF:Mixin(frameCanvas, DF.ListboxFunctions)
|
|
DF:Mixin(frameCanvas, DF.OptionsFunctions)
|
|
DF:Mixin(frameCanvas, DF.LayoutFrame)
|
|
frameCanvas.headerTable = headerTable
|
|
|
|
if (not data or type(data) ~= "table") then
|
|
error("CreateListBox() parameter 3 'data' must be a table.")
|
|
end
|
|
|
|
frameCanvas.data = data
|
|
frameCanvas.lines = {}
|
|
DF:ApplyStandardBackdrop(frameCanvas)
|
|
frameCanvas:BuildOptionsTable(listbox_options, options)
|
|
|
|
--> header
|
|
--check for default values in the header
|
|
headerTable = headerTable or {
|
|
{text = "Spell Id", width = 70},
|
|
{text = "Spell Name", width = 70},
|
|
}
|
|
headerOptions = headerOptions or {
|
|
padding = 2,
|
|
}
|
|
|
|
--each header is an entry in the data, if the header has 4 indexes the data has sub tables with 4 indexes as well
|
|
frameCanvas.headerLength = #headerTable
|
|
|
|
--add the detele line column into the header frame
|
|
tinsert(headerTable, 1, {text = "#", width = 20, isIndex = true}) --isDelete signals the createScrollLine() to make the delete button for the line
|
|
tinsert(headerTable, {text = "Delete", width = 50, isDelete = true}) --isDelete signals the createScrollLine() to make the delete button for the line
|
|
|
|
local header = DF:CreateHeader(frameCanvas, headerTable, headerOptions)
|
|
--set the header point
|
|
header:SetPoint("topleft", frameCanvas, "topleft", 5, -5)
|
|
frameCanvas.header = header
|
|
|
|
--> auto size
|
|
if (frameCanvas.options.auto_width) then
|
|
local width = 10 --padding 5 on each side
|
|
width = width + 20 --scrollbar reserved space
|
|
local headerPadding = headerOptions.padding or 0
|
|
|
|
for _, header in pairs(headerTable) do
|
|
if (header.width) then
|
|
width = width + header.width + headerPadding
|
|
end
|
|
end
|
|
|
|
frameCanvas.options.width = width
|
|
frameCanvas:SetWidth(width)
|
|
end
|
|
|
|
local width = frameCanvas.options.width
|
|
local height = frameCanvas.options.height
|
|
|
|
frameCanvas:SetSize(frameCanvas.options.width, height)
|
|
|
|
--> scroll frame
|
|
local lineHeight = frameCanvas.options.line_height
|
|
--calc the size of the space occupied by the add button, header etc
|
|
local lineAmount = floor((height - 60) / lineHeight)
|
|
|
|
-- -12 is padding: 5 on top, 7 bottom, 2 header scrollbar blank space | -24 to leave space to the add button
|
|
local scrollBox = DF:CreateScrollBox(frameCanvas, "$parentScrollbox", frameCanvas.scrollRefresh, data, width-4, height - header:GetHeight() - 12 - 24, lineAmount, lineHeight)
|
|
scrollBox:SetPoint("topleft", header, "bottomleft", 0, -2)
|
|
scrollBox:SetPoint("topright", header, "bottomright", 0, -2) -- -20 for the scrollbar
|
|
DF:ReskinSlider(scrollBox)
|
|
scrollBox.lineHeight = lineHeight
|
|
scrollBox.lineAmount = lineAmount
|
|
frameCanvas.scrollBox = scrollBox
|
|
|
|
for i = 1, lineAmount do
|
|
scrollBox:CreateLine(frameCanvas.createScrollLine)
|
|
end
|
|
|
|
scrollBox:Refresh()
|
|
|
|
--> add line button
|
|
local addLineButton = DF:CreateButton(frameCanvas, DF.ListboxFunctions.addEntry, 80, 20, "Add", nil, nil, nil, nil, nil, nil, DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"), DF:GetTemplate("font", "ORANGE_FONT_TEMPLATE"))
|
|
addLineButton:SetPoint("topleft", scrollBox, "bottomleft", 0, -4)
|
|
|
|
return frameCanvas
|
|
end
|
|
|
|
--[=[ -- test case
|
|
|
|
local pframe = ListBoxTest or CreateFrame("frame", "ListBoxTest", UIParent)
|
|
pframe:SetSize(900, 700)
|
|
pframe:SetPoint("left")
|
|
|
|
local data = {{254154, "spell name 1", 45}, {299154, "spell name 2", 05}, {354154, "spell name 3", 99}}
|
|
local headerTable = {
|
|
{text = "spell id", width = 120},
|
|
{text = "spell name", width = 180},
|
|
{text = "number", width = 90},
|
|
}
|
|
|
|
local listbox = DetailsFramework:CreateListBox(pframe, "$parentlistbox", data, nil, headerTable, nil)
|
|
listbox:SetPoint("topleft", pframe, "topleft", 10, -10)
|
|
|
|
--]=]
|
|
|
|
|