framework update

This commit is contained in:
Tercio Jose
2023-07-25 20:19:41 -03:00
parent 94ae59dfa9
commit 13670e8b44
52 changed files with 164 additions and 38183 deletions
+119 -43
View File
@@ -211,27 +211,7 @@ detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.ScriptHookMixin)
--texture
local smember_texture = function(object, value)
if (type(value) == "table") then
local value1, value2, value3, value4 = unpack(value)
if (value1) then
object.button:SetNormalTexture(value1)
end
if (value2) then
object.button:SetHighlightTexture(value2, "ADD")
end
if (value3) then
object.button:SetPushedTexture(value3)
end
if (value4) then
object.button:SetDisabledTexture(value4)
end
else
object.button:SetNormalTexture(value)
object.button:SetHighlightTexture(value, "ADD")
object.button:SetPushedTexture(value)
object.button:SetDisabledTexture(value)
end
return
return detailsFramework:SetButtonTexture(object, value, 0, 1, 0, 1)
end
--locked
@@ -1120,7 +1100,14 @@ end
return colorPickButton
end
function detailsFramework:SetRegularButtonTexture(button, texture, left, right, top, bottom)
---set the texture of all 4 textures of a button to the same texture
---@param button button
---@param texture textureid|texturepath
---@param left coordleft|table|nil
---@param right coordright|nil
---@param top coordtop|nil
---@param bottom coordbottom|nil
function detailsFramework:SetButtonTexture(button, texture, left, right, top, bottom)
if (type(left) == "table") then
left, right, top, bottom = unpack(left)
end
@@ -1132,23 +1119,54 @@ end
local atlas
if (type(texture) == "string") then
atlas = C_Texture.GetAtlasInfo(texture)
end
end
local normalTexture = button:GetNormalTexture()
local pushedTexture = button:GetPushedTexture()
local highlightTexture = button:GetHightlightTexture()
local disabledTexture = button:GetDisabledTexture()
local normalTexture = button:GetNormalTexture()
local pushedTexture = button:GetPushedTexture()
local highlightTexture = button:GetHightlightTexture()
local disabledTexture = button:GetDisabledTexture()
if (type(texture) == "table") then
local normalTexturePath, pushedTexturePath, highlightTexturePath, disabledTexturePath = unpack(texture)
---@cast right number
---@cast top number
---@cast bottom number
if (normalTexturePath) then
normalTexture:SetTexture(normalTexturePath)
normalTexture:SetTexCoord(left, right, top, bottom)
end
if (pushedTexturePath) then
pushedTexture:SetTexture(pushedTexturePath)
pushedTexture:SetTexCoord(left, right, top, bottom)
end
if (highlightTexturePath) then
highlightTexture:SetTexture(highlightTexturePath)
highlightTexture:SetTexCoord(left, right, top, bottom)
end
if (disabledTexturePath) then
disabledTexture:SetTexture(disabledTexturePath)
disabledTexture:SetTexCoord(left, right, top, bottom)
end
elseif (atlas) then
normalTexture:SetAtlas(atlas)
pushedTexture:SetAtlas(atlas)
highlightTexture:SetAtlas(atlas)
disabledTexture:SetAtlas(atlas)
if (atlas) then
normalTexture:SetAtlas(texture)
pushedTexture:SetAtlas(texture)
highlightTexture:SetAtlas(texture)
disabledTexture:SetAtlas(texture)
else
normalTexture:SetTexture(texture)
pushedTexture:SetTexture(texture)
highlightTexture:SetTexture(texture)
disabledTexture:SetTexture(texture)
---@cast right number
---@cast top number
---@cast bottom number
normalTexture:SetTexCoord(left, right, top, bottom)
pushedTexture:SetTexCoord(left, right, top, bottom)
highlightTexture:SetTexCoord(left, right, top, bottom)
@@ -1156,17 +1174,23 @@ end
end
end
function detailsFramework:SetRegularButtonVertexColor(button, ...)
local r, g, b, a = detailsFramework:ParseColor(...)
---set the vertex color of all 4 textures of a button to the same color
---@param button button
---@param red any
---@param green number|nil
---@param blue number|nil
---@param alpha number|nil
function detailsFramework:SetButtonVertexColor(button, red, green, blue, alpha)
red, green, blue, alpha = detailsFramework:ParseColor(red, green, blue, alpha)
local normalTexture = button:GetNormalTexture()
local pushedTexture = button:GetPushedTexture()
local highlightTexture = button:GetHightlightTexture()
local disabledTexture = button:GetDisabledTexture()
normalTexture:SetVertexColor(r, g, b, a)
pushedTexture:SetVertexColor(r, g, b, a)
highlightTexture:SetVertexColor(r, g, b, a)
disabledTexture:SetVertexColor(r, g, b, a)
normalTexture:SetVertexColor(red, green, blue, alpha)
pushedTexture:SetVertexColor(red, green, blue, alpha)
highlightTexture:SetVertexColor(red, green, blue, alpha)
disabledTexture:SetVertexColor(red, green, blue, alpha)
end
@@ -1187,10 +1211,12 @@ end
---@field rightTextureSelectedName string
---@field middleTextureSelectedName string
---@field bIsSelected boolean
---@field SetText fun(self: df_tabbutton, text: string)
---@field SetSelected fun(self: df_tabbutton, selected: boolean)
---@field IsSelected fun(self: df_tabbutton): boolean
---@field Reset fun(self: df_tabbutton)
---@field SetText fun(self: df_tabbutton, text: string) --set the tab text
---@field SetSelected fun(self: df_tabbutton, selected: boolean) --highlight the tab textures to indicate the tab is selected
---@field SetShowCloseButton fun(self: df_tabbutton, show: boolean) --set if the close button can be shown or not
---@field GetFontString fun(self: df_tabbutton) : fontstring --get the fontstring used to display the tab text
---@field IsSelected fun(self: df_tabbutton): boolean --get a boolean representing if the tab is selected
---@field Reset fun(self: df_tabbutton) --set all textures to their default values, set the text to an empty string, set the selected state to false
detailsFramework.TabButtonMixin = {
---set the text of the tab button
@@ -1214,6 +1240,13 @@ detailsFramework.TabButtonMixin = {
self.bIsSelected = selected
end,
---set if the close button can be shown or not
---@param self df_tabbutton
---@param show boolean
SetShowCloseButton = function(self, show)
self.CloseButton:SetShown(show)
end,
---get a boolean representing if the tab is selected
---@param self df_tabbutton
---@return boolean
@@ -1232,6 +1265,12 @@ detailsFramework.TabButtonMixin = {
self.SelectedTexture:Hide()
end,
---get the fontstring used to display the tab text
---@param self df_tabbutton
---@return fontstring
GetFontString = function(self)
return self.Text
end,
}
---create a button which can be used as a tab button, has textures for left, right, middle and a text
@@ -1255,6 +1294,9 @@ function detailsFramework:CreateTabButton(parent, frameName)
tabButton.SelectedTexture:Hide()
tabButton.Text = tabButton:CreateFontString(nil, "overlay", "GameFontNormal")
tabButton.CloseButton = detailsFramework:CreateCloseButton(tabButton, "$parentCloseButton")
tabButton.CloseButton:SetSize(10, 10)
tabButton.CloseButton:SetAlpha(0.6)
tabButton.CloseButton:Hide()
tabButton.Text:SetPoint("center", tabButton, "center", 0, 0)
tabButton.CloseButton:SetPoint("topright", tabButton, "topright", 0, 0)
@@ -1294,6 +1336,38 @@ function detailsFramework:CreateTabButton(parent, frameName)
return tabButton
end
--[=[
--example:
local frame = CreateFrame("frame", "MyTestFrameForTabutton", UIParent)
frame:SetSize(650, 100)
frame:SetPoint("center", UIParent, "center", 0, 0)
DetailsFramework:ApplyStandardBackdrop(frame)
frame.TabButtons = {}
local tabOnClickCallback = function(self)
for _, tab in ipairs(frame.TabButtons) do
tab:SetSelected(false)
end
self:SetSelected(true)
end
for i = 1, 5 do
local tabButton = DetailsFramework:CreateTabButton(frame, "$parentTabButton" .. i)
tabButton:SetPoint("bottomleft", frame, "topleft", (i-1) * 130, 0)
tabButton:SetText("Tab " .. i)
tabButton:SetWidth(128)
table.insert(frame.TabButtons, tabButton)
tabButton:SetScript("OnClick", tabOnClickCallback)
end
--select a tab to be the default selected (if wanted)
frame.TabButtons[1]:SetSelected(true)
--set shown state of the close button (if wanted)
frame.TabButtons[2]:SetShowCloseButton(true)
--]=]
------------------------------------------------------------------------------------------------------------
--close button
@@ -1301,9 +1375,11 @@ detailsFramework.CloseButtonMixin = {
OnClick = function(self)
self:GetParent():Hide()
end,
OnEnter = function(self)
self:GetNormalTexture():SetVertexColor(1, 0, 0)
end,
OnLeave = function(self)
self:GetNormalTexture():SetVertexColor(1, 1, 1)
end,
@@ -1318,7 +1394,7 @@ detailsFramework.CloseButtonMixin = {
---@param parent frame
---@param frameName string|nil
---@return df_closebutton
function detailsFramework:CreateCloseButton(parent, frameName) --make documentation
function detailsFramework:CreateCloseButton(parent, frameName)
---@type df_closebutton
local closeButton = CreateFrame("button", frameName, parent, "UIPanelCloseButton")
closeButton:SetFrameLevel(parent:GetFrameLevel() + 1)
+2 -2
View File
@@ -392,7 +392,7 @@
---@field RegisterForClicks fun(self: button, button1: nil|buttontype, button2: nil|buttontype, button3: nil|buttontype, button4: nil|buttontype)
---@field GetNormalTexture fun(self: button) : texture
---@field GetPushedTexture fun(self: button) : texture
---@field GetHighlightTexture fun(self: button) : texture
---@field GetHightlightTexture fun(self: button) : texture
---@field GetDisabledTexture fun(self: button) : texture
---@class statusbar : frame
@@ -471,7 +471,7 @@
---@class texture : region
---@field SetDrawLayer fun(self: texture, layer: drawlayer, subLayer: number|nil)
---@field SetTexture fun(self: texture, path: string, horizontalWrap: texturewrap|nil, verticalWrap: texturewrap|nil, filter: texturefilter|nil)
---@field SetTexture fun(self: texture, path: textureid|texturepath, horizontalWrap: texturewrap|nil, verticalWrap: texturewrap|nil, filter: texturefilter|nil)
---@field SetAtlas fun(self: texture, atlas: string)
---@field SetColorTexture fun(self: texture, r: red|number, g: green|number, b: blue|number, a: alpha|number|nil)
---@field SetDesaturated fun(self: texture, desaturate: boolean)
+43
View File
@@ -199,6 +199,7 @@
breath_targets = {},
flyaway = {},
flyaway_timer = {},
shield = {},
}
local empower_cache = {}
@@ -1257,6 +1258,31 @@
end
end
if (spellId == 360828 and augmentation_cache.shield[sourceSerial]) then --shield
---actor buffed with the shield -> list of evokers whose buffed
---@type table<serial, evokerinfo[]>
local currentlyBuffedWithShield = augmentation_cache.shield[sourceSerial]
for i, evokerInfo in ipairs(currentlyBuffedWithShield) do
---@cast evokerInfo evokerinfo
---@type serial, actorname, controlflags
local evokerSourceSerial, evokerSourceName, evokerSourceFlags = unpack(evokerInfo)
---@type actor
local evokerActor = damage_cache[evokerSourceSerial]
if (not evokerActor) then
evokerActor = _current_damage_container:PegarCombatente(evokerSourceSerial, evokerSourceName, evokerSourceFlags, true)
end
if (evokerActor) then
local damageSplitted = amount / #currentlyBuffedWithShield
evokerActor.total_extra = evokerActor.total_extra + damageSplitted
end
end
end
if (spellId == 404908 and augmentation_cache.prescience[sourceSerial]) then --fate mirror
---actor buffed with prescience -> list of evokers whose buffed
---@type table<serial, evokerinfo[]>
@@ -2610,6 +2636,12 @@
table.insert(breathTargets, eonsBreathInfo)
end
end
elseif (spellId == 360827) then
augmentation_cache.shield[targetSerial] = augmentation_cache.shield[targetSerial] or {}
---@type evokerinfo
local evokerInfo = {sourceSerial, sourceName, sourceFlags, amount}
table.insert(augmentation_cache.shield[targetSerial], evokerInfo)
end
if (buffs_makeyourown[spellId]) then
@@ -3025,6 +3057,16 @@
end
end
end
elseif (spellid == 360827) then
if (augmentation_cache.shield[targetSerial]) then
for index, evokerInfo in ipairs(augmentation_cache.shield[targetSerial]) do
if (evokerInfo[1] == sourceSerial) then
table.remove(augmentation_cache.shield[targetSerial], index)
break
end
end
end
end
if (buffs_makeyourown[spellid]) then
@@ -6425,6 +6467,7 @@ local SPELL_POWER_PAIN = SPELL_POWER_PAIN or (PowerEnum and PowerEnum.Pain) or 1
Details:Destroy(augmentation_cache.ebon_might) --~roskash
Details:Destroy(augmentation_cache.prescience)
Details:Destroy(augmentation_cache.breath_targets)
Details:Destroy(augmentation_cache.shield)
cacheAnything.track_hunter_frenzy = Details.combat_log.track_hunter_frenzy
@@ -1,11 +0,0 @@
background.blp
border_1.blp
border_2.blp
border_3.blp
cooltip_background.blp
feedback_sites.blp
icons.blp
mail.blp
*.json
CHANGES.txt
@@ -1,66 +0,0 @@
DFPixelUtil = {};
function DFPixelUtil.GetPixelToUIUnitFactor()
local physicalWidth, physicalHeight = GetPhysicalScreenSize();
return 768.0 / physicalHeight;
end
function DFPixelUtil.GetNearestPixelSize(uiUnitSize, layoutScale, minPixels)
if uiUnitSize == 0 and (not minPixels or minPixels == 0) then
return 0;
end
local uiUnitFactor = DFPixelUtil.GetPixelToUIUnitFactor();
local numPixels = Round((uiUnitSize * layoutScale) / uiUnitFactor);
local rawNumPixels = numPixels;
if minPixels then
if uiUnitSize < 0.0 then
if numPixels > -minPixels then
numPixels = -minPixels;
end
else
if numPixels < minPixels then
numPixels = minPixels;
end
end
end
return numPixels * uiUnitFactor / layoutScale;
end
function DFPixelUtil.SetWidth(region, width, minPixels)
region:SetWidth(DFPixelUtil.GetNearestPixelSize(width, region:GetEffectiveScale(), minPixels));
end
function DFPixelUtil.SetHeight(region, height, minPixels)
region:SetHeight(DFPixelUtil.GetNearestPixelSize(height, region:GetEffectiveScale(), minPixels));
end
function DFPixelUtil.SetSize(region, width, height, minWidthPixels, minHeightPixels)
DFPixelUtil.SetWidth(region, width, minWidthPixels);
DFPixelUtil.SetHeight(region, height, minHeightPixels);
end
function DFPixelUtil.SetPoint(region, point, relativeTo, relativePoint, offsetX, offsetY, minOffsetXPixels, minOffsetYPixels)
region:SetPoint(point, relativeTo, relativePoint,
DFPixelUtil.GetNearestPixelSize(offsetX, region:GetEffectiveScale(), minOffsetXPixels),
DFPixelUtil.GetNearestPixelSize(offsetY, region:GetEffectiveScale(), minOffsetYPixels)
);
end
function DFPixelUtil.SetStatusBarValue(statusBar, value)
local width = statusBar:GetWidth();
if width and width > 0.0 then
local min, max = statusBar:GetMinMaxValues();
local percent = ClampedPercentageBetween(value, min, max);
if percent == 0.0 or percent == 1.0 then
statusBar:SetValue(value);
else
local numPixels = DFPixelUtil.GetNearestPixelSize(statusBar:GetWidth() * percent, statusBar:GetEffectiveScale());
local roundedValue = Lerp(min, max, numPixels / width);
statusBar:SetValue(roundedValue);
end
else
statusBar:SetValue(value);
end
end
@@ -1,5 +0,0 @@
## Interface: 100100
## Title: Lib: LibDFramework-1.0
## Notes: Base Framework for many Addons
load.xml
@@ -1,132 +0,0 @@
local DF = _G ["DetailsFramework"]
local _
if (not DF or not DetailsFrameworkCanLoad) then
return
end
--runs when the addon received addon_loaded
local addonPreLoad = function(addonFrame, event, ...)
--check if the saved variables table is created, if not create one
_G[addonFrame.__savedVarsName] = _G[addonFrame.__savedVarsName] or {}
if (addonFrame.__savedVarsDefaultTemplate) then
--load saved vars for this character
DF.SavedVars.LoadSavedVarsForPlayer(addonFrame)
end
if (addonFrame.OnLoad) then
DF:Dispatch(addonFrame.OnLoad, addonFrame, ...)
end
end
--runs when the addon received player_login
local addonInit = function(addonFrame, event, ...)
if (addonFrame.OnInit) then
DF:Dispatch(addonFrame.OnInit, addonFrame, ...)
end
end
--when the player logout or reloadUI
local addonUnload = function(addonFrame, event, ...)
--close saved tables
DF.SavedVars.CloseSavedTable(addonFrame.db)
end
local addonEvents = {
["ADDON_LOADED"] = addonPreLoad,
["PLAYER_LOGIN"] = addonInit,
["PLAYER_LOGOUT"] = addonUnload,
}
local addonOnEvent = function(addonFrame, event, ...)
local func = addonEvents[event]
if (func) then
func(addonFrame, event, ...)
else
--might be a registered event from the user
if (addonFrame[event]) then
DF:CoreDispatch(addonFrame.__name, addonFrame[event], addonFrame, event, ...)
end
end
end
local getAddonName = function(addonFrame)
return addonFrame:GetName()
end
function DF:CreateNewAddOn(addonName, globalSavedVariablesName, savedVarsTemplate)
local newAddon = CreateFrame("frame", addonName, UIParent)
newAddon.__name = addonName
newAddon.__savedVarsName = globalSavedVariablesName
newAddon.__savedVarsDefaultTemplate = savedVarsTemplate
newAddon.GetAddonName = getAddonName
newAddon:RegisterEvent("ADDON_LOADED")
newAddon:RegisterEvent("PLAYER_LOGIN")
newAddon:RegisterEvent("PLAYER_LOGOUT")
newAddon:SetScript("OnEvent", addonOnEvent)
return newAddon
end
--old create addon
function DF:CreateAddOn (name, global_saved, global_table, options_table, broker)
local addon = LibStub("AceAddon-3.0"):NewAddon (name, "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "DetailsFramework-1.0", "AceComm-3.0")
_G [name] = addon
addon.__name = name
function addon:OnInitialize()
if (global_saved) then
if (broker and broker.Minimap and not global_table.Minimap) then
DF:Msg(name, "broker.Minimap is true but no global.Minimap declared.")
end
self.db = LibStub("AceDB-3.0"):New (global_saved, global_table or {}, true)
end
if (options_table) then
LibStub("AceConfig-3.0"):RegisterOptionsTable (name, options_table)
addon.OptionsFrame1 = LibStub("AceConfigDialog-3.0"):AddToBlizOptions (name, name)
LibStub("AceConfig-3.0"):RegisterOptionsTable (name .. "-Profiles", LibStub("AceDBOptions-3.0"):GetOptionsTable (self.db))
addon.OptionsFrame2 = LibStub("AceConfigDialog-3.0"):AddToBlizOptions (name .. "-Profiles", "Profiles", name)
end
if (broker) then
local broker_click_function = broker.OnClick
if (not broker_click_function and options_table) then
broker_click_function = function()
InterfaceOptionsFrame_OpenToCategory (name)
InterfaceOptionsFrame_OpenToCategory (name)
end
end
local databroker = LibStub("LibDataBroker-1.1"):NewDataObject (name, {
type = broker.type or "launcher",
icon = broker.icon or [[Interface\PvPRankBadges\PvPRank15]],
text = broker.text or "",
OnTooltipShow = broker.OnTooltipShow,
OnClick = broker_click_function
})
if (databroker and broker.Minimap and global_table.Minimap) then
LibStub("LibDBIcon-1.0"):Register (name, databroker, addon.db.profile.Minimap)
end
end
if (addon.OnInit) then
xpcall(addon.OnInit, geterrorhandler(), addon)
end
end
return addon
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,3 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
<Script file="button.lua"/>
</Ui>
@@ -1,109 +0,0 @@
--documentation: see the header of the file charts.lua
--1º example: making a simple chart, just copy and paste this code into a lua file and run it
do
local ChartFrameTest = ChartFrameExample1 or DetailsFramework:CreateGraphicLineFrame(UIParent, "ChartFrameExample1")
ChartFrameTest:SetPoint("left", UIParent, "left", 10, 0) --set the position of the chart
ChartFrameTest:SetSize(800, 600) --set the size of the chart
DetailsFramework:ApplyStandardBackdrop(ChartFrameTest) --apply a backdrop to this example hence see the frame size
--set the data (required)
local data = {1, 2, 30, 25, 6, 5, 4, 8, 7, 4, 1, 12, 15, 24, 18, 17, 14, 15, 8, 4, 14, 42, 22, 25, 30, 35, 39, 8, 7, 4, 1, 2, 5, 4, 8, 7, 4, 12, 12, 4}
local smoothnessLevel = 1 --(optional, default: 1)
ChartFrameTest:SetData(data, smoothnessLevel)
--draw the chart
ChartFrameTest:Plot()
end
--2º example: setting the color, thickness and scale of the line:
do
local ChartFrameTest = ChartFrameExample2 or DetailsFramework:CreateGraphicLineFrame(UIParent, "ChartFrameExample2")
ChartFrameTest:SetPoint("left", UIParent, "left", 10, 0) --set the position of the chart
ChartFrameTest:SetSize(800, 600) --set the size of the chart
DetailsFramework:ApplyStandardBackdrop(ChartFrameTest) --apply a backdrop to this example hence see the frame size
--set the line thickness (optional, default: 2)
local lineThickness = 3
ChartFrameTest:SetLineThickness(lineThickness)
--set the chart color (optional, default: "white")
local lineColor = {r = 1, g = 1, b = 0} --set it to "yellow"
ChartFrameTest:SetColor(lineColor) --using {r = 1, g = 1, b = 0}
ChartFrameTest:SetColor("yellow") --using the color name
ChartFrameTest:SetColor(1, 1, 0) --passing the rgb directly
ChartFrameTest:SetColor({1, 1, 0}) --using an index table
--set the data (required)
local data = {1, 2, 30, 25, 6, 5, 4, 8, 7, 4, 1, 12, 15, 24 ,18, 17 ,14, 15, 8 , 4, 14, 42, 22, 25, 30, 35, 39, 8, 7, 4, 1, 2, 5, 4 ,8, 7 ,4, 12, 12 , 4}
local smoothnessLevel = 1 --(optional, default: 1)
ChartFrameTest:SetData(data, smoothnessLevel)
--height modifier, if for some reason need to scale the chart height
local heightScale = 1 --(optional, default: 1)
--draw the chart
ChartFrameTest:Plot(heightScale)
end
--3º example: setting the axes lines and labels
do
local ChartFrameTest = ChartFrameExample3 or DetailsFramework:CreateGraphicLineFrame(UIParent, "ChartFrameExample3")
ChartFrameTest:SetPoint("left", UIParent, "left", 10, 0)
ChartFrameTest:SetSize(800, 600)
DetailsFramework:ApplyStandardBackdrop(ChartFrameTest)
--create guide lines in the left and bottom of the chart
local xOffset = 48 --pixels from the left border of the chart
local yOffset = 28 --pixels from the bottom border of the chart
local whichSide = "left" --which side of vertical line should be placed
local thickness = 1
local amountYLabels = 10 --amounf of texts indicating the scale of the chart
local amountXLabels = 10
local r, g, b, a = 1, 1, 1, 1
ChartFrameTest:CreateAxesLines(xOffset, yOffset, whichSide, thickness, amountYLabels, amountXLabels, r, g, b, a)
--the labels in the bottom line can be 'time', 'number' or 'value'
ChartFrameTest:SetXAxisDataType("time")
--set the data to be used in the bottom line labels, how the data is formatted depends on the type set above
ChartFrameTest:SetXAxisData(10) --with type 'time' the chart interprets this as seconds and shows 1:00 to 10:00
ChartFrameTest:SetXAxisDataType("number")
ChartFrameTest:SetXAxisData(600) --the chart interprets this as a 'number' type and displays it as 60, 120, 180.
ChartFrameTest:SetXAxisDataType("value")
ChartFrameTest:SetXAxisData("hello", "world", 1, 2, 3, 4, "chart", 0, 1, 0) --and 'value' show the values passed
--setting the data, doesn't matter if it is set at the top or right before Plot()
local data = {1, 2, 30, 25, 6, 5, 4, 8, 7, 4, 1, 12, 15, 24 ,18, 17 ,14, 15, 8 , 4, 14, 42, 22, 25, 30, 35, 39, 8, 7, 4, 1, 2, 5, 4 ,8, 7 ,4, 12, 12 , 4}
ChartFrameTest:SetData(data) --smoothnessLevel is absent here, it'll use 1 as default
ChartFrameTest:Plot()
end
--4º example: a multi line chart is a chart which supports multiple lines, each line can have a different color, name, smoothnessLevel and thickness
do
local ChartFrameTest = ChartFrameExample4 or DetailsFramework:CreateGraphicMultiLineFrame(UIParent, "ChartFrameExample4")
ChartFrameTest:SetPoint("left", UIParent, "left", 10, 0)
ChartFrameTest:SetSize(800, 600)
DetailsFramework:ApplyStandardBackdrop(ChartFrameTest)
--when using multi-line, the Reset() function instructs the chart to discard the previous data as new data is about to be added
ChartFrameTest:Reset()
--smoothnessLevel, name, red, green, blue, alpha
local smoothnessLevel = 2 --(optional, default: 0)
local line1Name, line2Name, line3Name = "Line 1", "Line 2", "Line 3" --show the line name at the top right corner (optional, default none)
local line1Color, line2Color, line3Color = "lime", "purple", "orange" --(optional, default "white")
--add data into the chart (it plots a line for each data added when :Plot() is called)
local data1 = {1, 2, 30, 25, 6, 5, 4, 8, 7, 4, 1, 12, 15, 24 ,18, 17 ,14, 15, 8 , 4, 14, 42, 22, 25, 30, 35, 39, 8, 7, 4, 1, 2, 5, 4}
ChartFrameTest:AddData(data1, smoothnessLevel, line1Name, line1Color)
local data2 = {3, 5, 20, 25, 6, 5, 15, 18, 12, 14, 11, 8, 7, 8 ,7, 4 ,1, 25, 26 , 30, 28, 20, 22, 25, 20, 15, 10, 8, 7, 4, 1, 2, 5, 4}
ChartFrameTest:AddData(data2, smoothnessLevel, line2Name, line2Color)
local data3 = {5, 7, 15, 30, 6, 2, 10, 13, 10, 5, 11, 8, 7, 5, 3, 1, 1, 8, 10 , 12, 15, 20, 25, 25, 20, 17, 12, 7, 7, 6, 4, 5, 6, 5}
ChartFrameTest:AddData(data3, smoothnessLevel, line3Name, line3Color)
ChartFrameTest:Plot()
end
File diff suppressed because it is too large Load Diff
@@ -1,184 +0,0 @@
do
local DF = _G ["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
DF.alias_text_colors = DF.alias_text_colors or {}
local defaultColors = {
["HUNTER"] = {0.67, 0.83, 0.45},
["WARLOCK"] = {0.58, 0.51, 0.79},
["PRIEST"] = {1.0, 1.0, 1.0},
["PALADIN"] = {0.96, 0.55, 0.73},
["MAGE"] = {0.41, 0.8, 0.94},
["ROGUE"] = {1.0, 0.96, 0.41},
["DRUID"] = {1.0, 0.49, 0.04},
["SHAMAN"] = {0.0, 0.44, 0.87},
["WARRIOR"] = {0.78, 0.61, 0.43},
["DEATHKNIGHT"] = {0.77, 0.12, 0.23},
["MONK"] = {0.0, 1.00, 0.59},
["DEMONHUNTER"] = {0.64, 0.19, 0.79},
["EVOKER"] = {0.20, 0.58, 0.50},
["dark1"] = {0.1215, 0.1176, 0.1294},
["dark2"] = {0.2215, 0.2176, 0.2294},
["dark3"] = {0.3215, 0.3176, 0.3294},
["aliceblue"] = {0.941176, 0.972549, 1, 1},
["antiquewhite"] = {0.980392, 0.921569, 0.843137, 1},
["aqua"] = {0, 1, 1, 1},
["aquamarine"] = {0.498039, 1, 0.831373, 1},
["azure"] = {0.941176, 1, 1, 1},
["beige"] = {0.960784, 0.960784, 0.862745, 1},
["bisque"] = {1, 0.894118, 0.768627, 1},
["black"] = {0, 0, 0, 1},
["blanchedalmond"] = {1, 0.921569, 0.803922, 1},
["blue"] = {0, 0, 1, 1},
["blueviolet"] = {0.541176, 0.168627, 0.886275, 1},
["brown"] = {0.647059, 0.164706, 0.164706, 1},
["burlywood"] = {0.870588, 0.721569, 0.529412, 1},
["cadetblue"] = {0.372549, 0.619608, 0.627451, 1},
["chartreuse"] = {0.498039, 1, 0, 1},
["chocolate"] = {0.823529, 0.411765, 0.117647, 1},
["coral"] = {1, 0.498039, 0.313725, 1},
["cornflowerblue"] = {0.392157, 0.584314, 0.929412, 1},
["cornsilk"] = {1, 0.972549, 0.862745, 1},
["crimson"] = {0.862745, 0.0784314, 0.235294, 1},
["cyan"] = {0, 1, 1, 1},
["darkblue"] = {0, 0, 0.545098, 1},
["darkcyan"] = {0, 0.545098, 0.545098, 1},
["darkgoldenrod"] = {0.721569, 0.52549, 0.0431373, 1},
["darkgray"] = {0.662745, 0.662745, 0.662745, 1},
["darkgreen"] = {0, 0.392157, 0, 1},
["darkkhaki"] = {0.741176, 0.717647, 0.419608, 1},
["darkmagenta"] = {0.545098, 0, 0.545098, 1},
["darkolivegreen"] = {0.333333, 0.419608, 0.184314, 1},
["darkorange"] = {1, 0.54902, 0, 1},
["darkorchid"] = {0.6, 0.196078, 0.8, 1},
["darkred"] = {0.545098, 0, 0, 1},
["darksalmon"] = {0.913725, 0.588235, 0.478431, 1},
["darkseagreen"] = {0.560784, 0.737255, 0.560784, 1},
["darkslateblue"] = {0.282353, 0.239216, 0.545098, 1},
["darkslategray"] = {0.184314, 0.309804, 0.309804, 1},
["darkturquoise"] = {0, 0.807843, 0.819608, 1},
["darkviolet"] = {0.580392, 0, 0.827451, 1},
["deeppink"] = {1, 0.0784314, 0.576471, 1},
["deepskyblue"] = {0, 0.74902, 1, 1},
["dimgray"] = {0.411765, 0.411765, 0.411765, 1},
["dimgrey"] = {0.411765, 0.411765, 0.411765, 1},
["dodgerblue"] = {0.117647, 0.564706, 1, 1},
["firebrick"] = {0.698039, 0.133333, 0.133333, 1},
["firebrickdark"] = {0.258039, 0.033333, 0.033333, 1},
["floralwhite"] = {1, 0.980392, 0.941176, 1},
["forestgreen"] = {0.133333, 0.545098, 0.133333, 1},
["fuchsia"] = {1, 0, 1, 1},
["gainsboro"] = {0.862745, 0.862745, 0.862745, 1},
["ghostwhite"] = {0.972549, 0.972549, 1, 1},
["gold"] = {1, 0.843137, 0, 1},
["goldenrod"] = {0.854902, 0.647059, 0.12549, 1},
["gray"] = {0.501961, 0.501961, 0.501961, 1},
["green"] = {0, 0.501961, 0, 1},
["greenyellow"] = {0.678431, 1, 0.184314, 1},
["honeydew"] = {0.941176, 1, 0.941176, 1},
["hotpink"] = {1, 0.411765, 0.705882, 1},
["indianred"] = {0.803922, 0.360784, 0.360784, 1},
["indigo"] = {0.294118, 0, 0.509804, 1},
["ivory"] = {1, 1, 0.941176, 1},
["khaki"] = {0.941176, 0.901961, 0.54902, 1},
["lavender"] = {0.901961, 0.901961, 0.980392, 1},
["lavenderblush"] = {1, 0.941176, 0.960784, 1},
["lawngreen"] = {0.486275, 0.988235, 0, 1},
["lemonchiffon"] = {1, 0.980392, 0.803922, 1},
["lightblue"] = {0.678431, 0.847059, 0.901961, 1},
["lightcoral"] = {0.941176, 0.501961, 0.501961, 1},
["lightcyan"] = {0.878431, 1, 1, 1},
["lightgoldenrodyellow"] = {0.980392, 0.980392, 0.823529, 1},
["lightgray"] = {0.827451, 0.827451, 0.827451, 1},
["lightgreen"] = {0.564706, 0.933333, 0.564706, 1},
["lightpink"] = {1, 0.713725, 0.756863, 1},
["lightsalmon"] = {1, 0.627451, 0.478431, 1},
["lightseagreen"] = {0.12549, 0.698039, 0.666667, 1},
["lightskyblue"] = {0.529412, 0.807843, 0.980392, 1},
["lightslategray"] = {0.466667, 0.533333, 0.6, 1},
["lightsteelblue"] = {0.690196, 0.768627, 0.870588, 1},
["lightyellow"] = {1, 1, 0.878431, 1},
["lime"] = {0, 1, 0, 1},
["limegreen"] = {0.196078, 0.803922, 0.196078, 1},
["linen"] = {0.980392, 0.941176, 0.901961, 1},
["magenta"] = {1, 0, 1, 1},
["maroon"] = {0.501961, 0, 0, 1},
["mediumaquamarine"] = {0.4, 0.803922, 0.666667, 1},
["mediumblue"] = {0, 0, 0.803922, 1},
["mediumorchid"] = {0.729412, 0.333333, 0.827451, 1},
["mediumpurple"] = {0.576471, 0.439216, 0.858824, 1},
["mediumseagreen"] = {0.235294, 0.701961, 0.443137, 1},
["mediumslateblue"] = {0.482353, 0.407843, 0.933333, 1},
["mediumspringgreen"] = {0, 0.980392, 0.603922, 1},
["mediumturquoise"] = {0.282353, 0.819608, 0.8, 1},
["mediumvioletred"] = {0.780392, 0.0823529, 0.521569, 1},
["midnightblue"] = {0.0980392, 0.0980392, 0.439216, 1},
["mintcream"] = {0.960784, 1, 0.980392, 1},
["mistyrose"] = {1, 0.894118, 0.882353, 1},
["moccasin"] = {1, 0.894118, 0.709804, 1},
["navajowhite"] = {1, 0.870588, 0.678431, 1},
["navy"] = {0, 0, 0.501961, 1},
["none"] ={0, 0, 0, 0},
["oldlace"] = {0.992157, 0.960784, 0.901961, 1},
["olive"] = {0.501961, 0.501961, 0, 1},
["olivedrab"] = {0.419608, 0.556863, 0.137255, 1},
["orange"] = {1, 0.647059, 0, 1},
["orangered"] = {1, 0.270588, 0, 1},
["orchid"] = {0.854902, 0.439216, 0.839216, 1},
["palegoldenrod"] = {0.933333, 0.909804, 0.666667, 1},
["palegreen"] = {0.596078, 0.984314, 0.596078, 1},
["paleturquoise"] = {0.686275, 0.933333, 0.933333, 1},
["palevioletred"] = {0.858824, 0.439216, 0.576471, 1},
["papayawhip"] = {1, 0.937255, 0.835294, 1},
["peachpuff"] = {1, 0.854902, 0.72549, 1},
["peru"] = {0.803922, 0.521569, 0.247059, 1},
["pink"] = {1, 0.752941, 0.796078, 1},
["plum"] = {0.866667, 0.627451, 0.866667, 1},
["powderblue"] = {0.690196, 0.878431, 0.901961, 1},
["purple"] = {0.501961, 0, 0.501961, 1},
["red"] = {1, 0, 0, 1},
["rosybrown"] = {0.737255, 0.560784, 0.560784, 1},
["royalblue"] = {0.254902, 0.411765, 0.882353, 1},
["saddlebrown"] = {0.545098, 0.270588, 0.0745098, 1},
["salmon"] = {0.980392, 0.501961, 0.447059, 1},
["sandybrown"] = {0.956863, 0.643137, 0.376471, 1},
["seagreen"] = {0.180392, 0.545098, 0.341176, 1},
["seashell"] = {1, 0.960784, 0.933333, 1},
["sienna"] = {0.627451, 0.321569, 0.176471, 1},
["silver"] = {0.752941, 0.752941, 0.752941, 1},
["skyblue"] = {0.529412, 0.807843, 0.921569, 1},
["slateblue"] = {0.415686, 0.352941, 0.803922, 1},
["slategray"] = {0.439216, 0.501961, 0.564706, 1},
["snow"] = {1, 0.980392, 0.980392, 1},
["springgreen"] = {0, 1, 0.498039, 1},
["steelblue"] = {0.27451, 0.509804, 0.705882, 1},
["tan"] = {0.823529, 0.705882, 0.54902, 1},
["teal"] = {0, 0.501961, 0.501961, 1},
["thistle"] = {0.847059, 0.74902, 0.847059, 1},
["tomato"] = {1, 0.388235, 0.278431, 1},
["transparent"] ={0, 0, 0, 0},
["turquoise"] = {0.25098, 0.878431, 0.815686, 1},
["violet"] = {0.933333, 0.509804, 0.933333, 1},
["wheat"] = {0.960784, 0.870588, 0.701961, 1},
["white"] = {1, 1, 1, 1},
["whitesmoke"] = {0.960784, 0.960784, 0.960784, 1},
["yellow"] = {1, 1, 0, 1},
["yellowgreen"] = {0.603922, 0.803922, 0.196078, 1}
}
function DF:GetDefaultColorList()
return defaultColors
end
for colorName, colorTable in pairs(defaultColors) do
DF.alias_text_colors [colorName] = colorTable
end
end
@@ -1,565 +0,0 @@
local detailsFramework = _G ["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local _
local DF = detailsFramework
local CreateFrame = CreateFrame
local wipe = wipe
local unpack = unpack
---@class df_framecontainer : frame, dfframecontainermixin, df_optionsmixin
---@field bIsSizing boolean
---@field options table
---@field currentWidth number
---@field currentHeight number
---@field bottomLeftResizer framecontainerresizer
---@field bottomRightResizer framecontainerresizer
---@field topLeftResizer framecontainerresizer
---@field topRightResizer framecontainerresizer
---@field topResizer framecontainerresizer
---@field bottomResizer framecontainerresizer
---@field leftResizer framecontainerresizer
---@field rightResizer framecontainerresizer
---@field cornerResizers framecontainerresizer[]
---@field sideResizers framecontainerresizer[]
---@field components table<frame, boolean>
---@field moverFrame frame
---@field movableChildren table<frame, boolean>
---@field settingChangedCallback fun(frameContainer: df_framecontainer, settingName: string, settingValue: any)
---@field OnSizeChanged fun(frameContainer: df_framecontainer)
---@field OnResizerMouseDown fun(resizerButton: button, mouseButton: string)
---@field OnResizerMouseUp fun(resizerButton: button, mouseButton: string)
---@field HideResizer fun(frameContainer: df_framecontainer)
---@field ShowResizer fun(frameContainer: df_framecontainer)
---@field OnInitialize fun(frameContainer: df_framecontainer)
---@field SetResizeLocked fun(frameContainer: df_framecontainer, isLocked: boolean)
---@field SetMovableLocked fun(frameContainer: df_framecontainer, isLocked: boolean)
---@field CheckResizeLockedState fun(frameContainer: df_framecontainer)
---@field CheckMovableLockedState fun(frameContainer: df_framecontainer)
---@field CreateMover fun(frameContainer: df_framecontainer)
---@field CreateResizers fun(frameContainer: df_framecontainer)
---@field RegisterChildForDrag fun(frameContainer: df_framecontainer, child: frame)
---@field UnregisterChildForDrag fun(frameContainer: df_framecontainer, child: frame)
---@field RefreshChildrenState fun(frameContainer: df_framecontainer)
---@field OnChildDragStart fun(frameContainer: df_framecontainer, child: frame)
---@field OnChildDragStop fun(frameContainer: df_framecontainer, child: frame)
---@field SetSettingChangedCallback fun(frameContainer: df_framecontainer, callback: fun(frameContainer: df_framecontainer, settingName: string, settingValue: any))
---@field SendSettingChangedCallback fun(frameContainer: df_framecontainer, settingName: string, settingValue: any)
---@class framecontainerresizer : button
---@field sizingFrom string
---@class dfframecontainermixin
detailsFramework.FrameContainerMixin = {
--methods
---run when the user click on the resizer
---@param resizerButton framecontainerresizer
---@param mouseButton string
OnResizerMouseDown = function(resizerButton, mouseButton)
if (mouseButton ~= "LeftButton") then
return
end
---@type df_framecontainer
local frameContainer = resizerButton:GetParent() --Cannot assign `frame` to `df_framecontainer`. .. but df_framecontainer is inherited from frame
if (frameContainer.bIsSizing) then
return
end
frameContainer.bIsSizing = true
frameContainer:StartSizing(resizerButton.sizingFrom)
end,
---run when the user click on the resizer
---@param resizerButton framecontainerresizer
---@param mouseButton string
OnResizerMouseUp = function(resizerButton, mouseButton)
---@type df_framecontainer
local frameContainer = resizerButton:GetParent() --Cannot assign `frame` to `df_framecontainer`. .. but df_framecontainer is inherited from frame
if (not frameContainer.bIsSizing) then
return
end
frameContainer:StopMovingOrSizing()
frameContainer.bIsSizing = false
end,
---hide resizer
---@param frameContainer df_framecontainer
HideResizer = function(frameContainer)
for i = 1, #frameContainer.cornerResizers do
frameContainer.cornerResizers[i]:Hide()
end
for i = 1, #frameContainer.sideResizers do
frameContainer.sideResizers[i]:Hide()
end
end,
---show resizer
---@param frameContainer df_framecontainer
ShowResizer = function(frameContainer)
--corner resizers
if (frameContainer.options.use_bottomleft_resizer) then
frameContainer.bottomLeftResizer:Show()
end
if (frameContainer.options.use_bottomright_resizer) then
frameContainer.bottomRightResizer:Show()
end
if (frameContainer.options.use_topleft_resizer) then
frameContainer.topRightResizer:Show()
end
if (frameContainer.options.use_topright_resizer) then
frameContainer.topRightResizer:Show()
end
--side resizers
if (frameContainer.options.use_top_resizer) then
frameContainer.topResizer:Show()
end
if (frameContainer.options.use_bottom_resizer) then
frameContainer.bottomResizer:Show()
end
if (frameContainer.options.use_left_resizer) then
frameContainer.leftResizer:Show()
end
if (frameContainer.options.use_right_resizer) then
frameContainer.rightResizer:Show()
end
end,
---check the lock state and show or hide the resizer, set the frame as movable or not, resizeable or not
---@param frameContainer df_framecontainer
CheckResizeLockedState = function(frameContainer)
if (frameContainer.options.is_locked) then
frameContainer:HideResizer()
frameContainer:SetResizable(false)
else
frameContainer:ShowResizer()
frameContainer:SetResizable(true)
end
end,
---check if the framecontainer can be moved and show or hide the mover
---@param frameContainer df_framecontainer
CheckMovableLockedState = function(frameContainer)
if (frameContainer.options.is_movement_locked) then
frameContainer:SetMovable(false)
frameContainer:EnableMouse(false)
frameContainer.moverFrame:Hide()
else
frameContainer:SetMovable(true)
frameContainer:EnableMouse(true)
frameContainer.moverFrame:Show()
end
end,
---set the lock state
---@param frameContainer df_framecontainer
---@param isLocked boolean
SetResizeLocked = function(frameContainer, isLocked)
frameContainer.options.is_locked = isLocked
frameContainer:SendSettingChangedCallback("is_locked", isLocked)
frameContainer:CheckResizeLockedState()
end,
---set the state of the mover frame
---@param frameContainer df_framecontainer
---@param isLocked boolean
SetMovableLocked = function(frameContainer, isLocked)
frameContainer.options.is_movement_locked = isLocked
frameContainer:SendSettingChangedCallback("is_movement_locked", isLocked)
frameContainer:CheckMovableLockedState()
end,
---create a mover to move the frame
---@param frameContainer df_framecontainer
CreateMover = function(frameContainer)
local mover = CreateFrame("button", nil, frameContainer)
frameContainer.moverFrame = mover
mover:SetAllPoints(frameContainer)
mover:EnableMouse(false)
mover:SetMovable(true)
mover:SetScript("OnMouseDown", function(self, mouseButton)
if (mouseButton ~= "LeftButton" or frameContainer.options.is_movement_locked) then
return
end
frameContainer:StartMoving()
end)
mover:SetScript("OnMouseUp", function(self, mouseButton)
if (mouseButton ~= "LeftButton" or frameContainer.options.is_movement_locked) then
return
end
frameContainer:StopMovingOrSizing()
end)
end,
---create four corner resizer and four side resizer
---@param frameContainer df_framecontainer
CreateResizers = function(frameContainer)
local parent = frameContainer:GetParent()
--create resizers for the container corners
local bottomLeftResizer, bottomRightResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "BottomLeftResizer", parent:GetName() .. "BottomRightResizer")
frameContainer.bottomLeftResizer = bottomLeftResizer
frameContainer.bottomRightResizer = bottomRightResizer
local topLeftResizer, topRightResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "TopLeftResizer", parent:GetName() .. "TopRightResizer")
frameContainer.topLeftResizer = topLeftResizer
frameContainer.topRightResizer = topRightResizer
local topResizer, bottomResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "TopResizer", parent:GetName() .. "BottomResizer")
frameContainer.topResizer = topResizer
frameContainer.bottomResizer = bottomResizer
local leftResizer, rightResizer = detailsFramework:CreateResizeGrips(frameContainer, nil, parent:GetName() .. "LeftResizer", parent:GetName() .. "RightResizer")
frameContainer.leftResizer = leftResizer
frameContainer.rightResizer = rightResizer
frameContainer.cornerResizers = {
bottomLeftResizer,
bottomRightResizer,
topLeftResizer,
topRightResizer,
}
frameContainer.sideResizers = {
topResizer,
bottomResizer,
leftResizer,
rightResizer,
}
--add all resizers to the frameContainer.components table
for i = 1, #frameContainer.cornerResizers do
frameContainer.components[frameContainer.cornerResizers[i]] = true
end
for i = 1, #frameContainer.sideResizers do
frameContainer.components[frameContainer.sideResizers[i]] = true
end
--hide all resizers
frameContainer:HideResizer()
end,
---run when the container is created
---@param frameContainer df_framecontainer
OnInitialize = function(frameContainer) --õninit ~init ~oninit
--set the default members
frameContainer.bIsSizing = false
frameContainer:SetSize(frameContainer.options.width, frameContainer.options.height)
--iterate among the corner resizers and set the mouse down and up scripts
for i = 1, #frameContainer.cornerResizers do
frameContainer.cornerResizers[i]:SetScript("OnMouseDown", frameContainer.OnResizerMouseDown)
frameContainer.cornerResizers[i]:SetScript("OnMouseUp", frameContainer.OnResizerMouseUp)
end
local sideResizeThickness = 2
--iterate among the side resizers and set the mouse down and up scripts; set the texture color; clear all points; set the thickness
for i = 1, #frameContainer.sideResizers do
frameContainer.sideResizers[i]:SetScript("OnMouseDown", frameContainer.OnResizerMouseDown)
frameContainer.sideResizers[i]:SetScript("OnMouseUp", frameContainer.OnResizerMouseUp)
frameContainer.sideResizers[i]:GetNormalTexture():SetColorTexture(1, 1, 1, 0.6)
frameContainer.sideResizers[i]:GetHighlightTexture():SetColorTexture(detailsFramework:ParseColors("aqua"))
frameContainer.sideResizers[i]:GetPushedTexture():SetColorTexture(1, 1, 1, 1)
frameContainer.sideResizers[i]:ClearAllPoints()
--can use SetSize here because the width or height are set by the point, e.g. 'topleft' to 'topright' overwrite the width set here
frameContainer.sideResizers[i]:SetSize(sideResizeThickness, sideResizeThickness)
end
--flip the corner resizers texturess
frameContainer.topLeftResizer:GetNormalTexture():SetTexCoord(1, 0, 1, 0)
frameContainer.topLeftResizer:GetHighlightTexture():SetTexCoord(1, 0, 1, 0)
frameContainer.topLeftResizer:GetPushedTexture():SetTexCoord(1, 0, 1, 0)
frameContainer.topRightResizer:GetNormalTexture():SetTexCoord(0, 1, 1, 0)
frameContainer.topRightResizer:GetHighlightTexture():SetTexCoord(0, 1, 1, 0)
frameContainer.topRightResizer:GetPushedTexture():SetTexCoord(0, 1, 1, 0)
frameContainer.topLeftResizer:ClearAllPoints()
frameContainer.topLeftResizer:SetPoint("topleft", frameContainer, "topleft", 0, 0)
frameContainer.topRightResizer:ClearAllPoints()
frameContainer.topRightResizer:SetPoint("topright", frameContainer, "topright", 0, 0)
--resize from for the corner resizers
frameContainer.bottomLeftResizer.sizingFrom = "bottomleft"
frameContainer.bottomRightResizer.sizingFrom = "bottomright"
frameContainer.topLeftResizer.sizingFrom = "topleft"
frameContainer.topRightResizer.sizingFrom = "topright"
--resize from for the side resizers
frameContainer.topResizer.sizingFrom = "top"
frameContainer.bottomResizer.sizingFrom = "bottom"
frameContainer.leftResizer.sizingFrom = "left"
frameContainer.rightResizer.sizingFrom = "right"
--set the side resizer points
frameContainer.topResizer:SetPoint("topleft", frameContainer, "topleft", 0, 2)
frameContainer.topResizer:SetPoint("topright", frameContainer, "topright", 0, 2)
frameContainer.bottomResizer:SetPoint("bottomleft", frameContainer, "bottomleft", 0, -2)
frameContainer.bottomResizer:SetPoint("bottomright", frameContainer, "bottomright", 0, -2)
frameContainer.leftResizer:SetPoint("topleft", frameContainer, "topleft", -2, 0)
frameContainer.leftResizer:SetPoint("bottomleft", frameContainer, "bottomleft", -2, 0)
frameContainer.rightResizer:SetPoint("topright", frameContainer, "topright", 2, 0)
frameContainer.rightResizer:SetPoint("bottomright", frameContainer, "bottomright", 2, 0)
if (frameContainer.options.is_locked) then
frameContainer:HideResizer()
else
frameContainer:ShowResizer()
end
frameContainer:CheckResizeLockedState()
frameContainer:CheckMovableLockedState()
if (frameContainer.SetMinResize) then --old versions of the game uses this method
frameContainer:SetMinResize(50, 50)
frameContainer:SetMaxResize(1000,1000)
else
frameContainer:SetResizeBounds(50, 50, 1000, 1000) --new versions has this method
end
end,
---run when the container has its size changed
---@param frameContainer df_framecontainer
OnSizeChanged = function(frameContainer)
---@type frame[]
local children = {frameContainer:GetChildren()}
---@type number
local childrenAmount = #children
--get the container size before its size was changed and calculate the percent of the difference between the old size and the new size
--adding +1 to the width and height difference to prevent the child from shrinking to 0, so it is scaled by 1
---@type number
local widthDifference = 1 + (frameContainer:GetWidth() - frameContainer.currentWidth) / frameContainer.currentWidth
---@type number
local heightDifference = 1 + (frameContainer:GetHeight() - frameContainer.currentHeight) / frameContainer.currentHeight
for i = 1, childrenAmount do
---@type frame
local child = children[i]
--if the child is a component, skip it
if (not frameContainer.components[child]) then
child:SetWidth(child:GetWidth() * widthDifference)
child:SetHeight(child:GetHeight() * heightDifference)
end
end
--update the current size of the container
frameContainer.currentWidth = frameContainer:GetWidth()
frameContainer.currentHeight = frameContainer:GetHeight()
frameContainer:SendSettingChangedCallback("width", frameContainer.currentWidth)
frameContainer:SendSettingChangedCallback("height", frameContainer.currentHeight)
end,
OnChildDragStop = function(child)
child:StopMovingOrSizing()
child:SetScript("OnUpdate", nil)
end,
---@param child frame
OnChildDragStart = function(child)
---@type df_framecontainer
local frameContainer = child:GetParent()
---get the coordinates for the frame container, which is called 'boundingBox' for convenience
---@type objectcoordinates
local boundingBox = detailsFramework:GetObjectCoordinates(frameContainer)
child:StartMoving()
--save the current point of the child, so it can be restored if the child is dragged outside the container
local childPoints = {}
for pointIndex = 1, child:GetNumPoints() do
childPoints[pointIndex] = {child:GetPoint(pointIndex)}
end
child:SetScript("OnUpdate", function(self)
---@type objectcoordinates
local childPos = detailsFramework:GetObjectCoordinates(self)
--check if the borders of the rectangle 'rec' collided with the borders of the rectangle 'bbox'
if ((childPos.left < boundingBox.left or childPos.right > boundingBox.right) or (childPos.top > boundingBox.top or childPos.bottom < boundingBox.bottom)) then
child:ClearAllPoints()
for pointIndex = 1, #childPoints do
child:SetPoint(unpack(childPoints[pointIndex]))
end
else
wipe(childPoints)
for pointIndex = 1, child:GetNumPoints() do
childPoints[pointIndex] = {child:GetPoint(pointIndex)}
end
end
end)
end,
---check if the children can be moved and set the properties on thisFrame
---@param frameContainer df_framecontainer
RefreshChildrenState = function(frameContainer)
frameContainer:EnableMouse(true)
if (frameContainer.options.can_move_children) then
for child, _ in pairs(frameContainer.movableChildren) do
child:EnableMouse(true)
child:SetMovable(true)
child:RegisterForDrag("LeftButton")
child:SetScript("OnDragStart", detailsFramework.FrameContainerMixin.OnChildDragStart)
child:SetScript("OnDragStop", detailsFramework.FrameContainerMixin.OnChildDragStop)
end
else
for child, _ in pairs(frameContainer.movableChildren) do
child:EnableMouse(false)
child:SetMovable(false)
child:RegisterForDrag("")
child:SetScript("OnDragStart", nil)
child:SetScript("OnDragStop", nil)
end
end
end,
---@param frameContainer df_framecontainer
---@param child frame
RegisterChildForDrag = function(frameContainer, child)
frameContainer.movableChildren[child] = true
frameContainer:RefreshChildrenState()
child:SetFrameStrata(frameContainer:GetFrameStrata())
child:SetFrameLevel(frameContainer:GetFrameLevel() + 1)
end,
---@param frameContainer df_framecontainer
---@param child frame
UnregisterChildForDrag = function(frameContainer, child)
frameContainer.movableChildren[child] = nil
frameContainer:RefreshChildrenState()
end,
---@param frameContainer df_framecontainer
---@param callback function
SetSettingChangedCallback = function(frameContainer, callback)
frameContainer.settingChangedCallback = callback
end,
---send a callback to the setting changed callback
---@param frameContainer df_framecontainer
---@param key string
---@param value any
SendSettingChangedCallback = function(frameContainer, key, value)
if (type(frameContainer.settingChangedCallback) == "function") then
detailsFramework:Dispatch(frameContainer.settingChangedCallback, frameContainer, key, value)
end
end,
}
---these are the default settings for the frame container; these keys can be accessed by df_framecontainer.options[key]
---@type table<string, any>
local frameContainerOptions = {
--default settings
width = 300,
height = 150,
is_locked = true, --can or not be resized
is_movement_locked = true, --can or not be moved
can_move_children = true,
use_topleft_resizer = false,
use_topright_resizer = false,
use_bottomleft_resizer = false,
use_bottomright_resizer = false,
use_top_resizer = false,
use_bottom_resizer = false,
use_left_resizer = false,
use_right_resizer = false,
}
---create a frame container, which is a frame that envelops another frame, and can be moved, resized, etc.
---@param parent frame
---@param options table|nil
---@param frameName string|nil
---@return df_framecontainer
function DF:CreateFrameContainer(parent, options, frameName)
---@type df_framecontainer
local frameContainer = CreateFrame("frame", frameName or ("$parentFrameContainer" .. math.random(10000, 99999)), parent, "BackdropTemplate")
frameContainer.components = {}
frameContainer.movableChildren = {}
frameContainer:EnableMouse(false)
detailsFramework:Mixin(frameContainer, detailsFramework.FrameContainerMixin)
detailsFramework:Mixin(frameContainer, detailsFramework.OptionsFunctions)
frameContainer:CreateResizers()
frameContainer:CreateMover()
frameContainer:BuildOptionsTable(frameContainerOptions, options)
frameContainer:OnInitialize()
frameContainer.currentWidth = frameContainer:GetWidth()
frameContainer.currentHeight = frameContainer:GetHeight()
frameContainer:SetScript("OnSizeChanged", frameContainer.OnSizeChanged)
return frameContainer
end
function DF:CreateFrameContainerTest(parent, options, frameName)
local container = DF:CreateFrameContainer(parent, options, frameName)
container:SetSize(400, 400)
container:SetPoint("center", _G.UIParent, "center", 0, 0)
detailsFramework:ApplyStandardBackdrop(container)
local verticalLastBox = nil
for i = 1, 4 do
local lastBox = nil
for o = 1, 4 do
local frame = CreateFrame("frame", "$parentFrame" .. i .. o, container, "BackdropTemplate")
container:RegisterChildForDrag(frame)
frame:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
frame:SetBackdropColor(0, 0, 0, 0.5)
frame:SetBackdropBorderColor(1, 1, 1, 0.5)
frame:SetSize(98, 98)
if (lastBox) then
frame:SetPoint("TOPLEFT", lastBox, "topright", 1, 0)
else
if (verticalLastBox) then
frame:SetPoint("TOPLEFT", verticalLastBox, "bottomleft", 0, -1)
verticalLastBox = frame
else
local x = 1 + (o - 1) * 99
local y = -10 - (i - 1) * 99
frame:SetPoint("TOPLEFT", container, "TOPLEFT", x, y)
verticalLastBox = frame
end
end
lastBox = frame
end
end
C_Timer.After(2, function()
--container:SetResizeLocked(true)
end)
end
--C_Timer.After(2, function()
-- DetailsFramework:CreateFrameContainerTest(UIParent)
--end)
--[=[
/run DetailsFramework:CreateFrameContainerTest(UIParent)
C_Timer.After(2, function()
DetailsFramework:CreateFrameContainerTest(UIParent)
end)
--]=]
File diff suppressed because it is too large Load Diff
@@ -1,5 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
<Script file="cooltip.lua"/>
</Ui>
@@ -1,14 +0,0 @@
---@class detailsframework
---@field OptionsFunctions df_optionsmixin
---@field RoundedCornerPanelMixin df_roundedcornermixin
---@field GetDefaultBackdropColor fun(self:table) : red, green, blue, alpha return a standard backdrop color
---@field Msg fun(self:table, message:string, ...) show a message in the chat frame
---@field MsgWarning fun(self:table, message:string, ...) show a warning message in the chat frame
---@field CreateCloseButton fun(self:table, parent:frame, frameName:string|nil) : df_closebutton
---@field CreateTabButton fun(self:table, parent:frame, frameName:string|nil) : df_tabbutton
---@field CreateRoundedPanel fun(self:table, parent:frame, frameName:string|nil, optionsTable:df_roundedpanel_options|nil) : df_roundedpanel
---@field CreateScaleBar fun(self:table, parent:frame, config:table<scale,number>) : df_scalebar
---@field AddRoundedCornersToFrame fun(self:table, frame:frame, optionsTable:df_roundedpanel_preset|nil)
---@field ParseColors fun(self:table, red:any, green:number|nil, blue:number|nil, alpha:number|nil) : red, green, blue, alpha
---@field Mixin fun(self:table, target:table, ...) : table
File diff suppressed because it is too large Load Diff
@@ -1,4 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
<Script file="dropdown.lua"/>
</Ui>
@@ -1,18 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
<Script file="Libs\LibStub\LibStub.lua"/>
<Include file="Libs\CallbackHandler-1.0\CallbackHandler-1.0.lua"/>
<Include file="Libs\LibSharedMedia-3.0\lib.xml"/>
<Include file="Libs\AceGUI-3.0\AceGUI-3.0.xml"/>
<Include file="Libs\AceDBOptions-3.0\AceDBOptions-3.0.xml"/>
<Include file="Libs\AceLocale-3.0\AceLocale-3.0.xml" />
<Include file="Libs\AceAddon-3.0\AceAddon-3.0.xml" />
<Include file="Libs\AceDB-3.0\AceDB-3.0.xml" />
<Include file="Libs\AceTimer-3.0\AceTimer-3.0.xml" />
<Include file="Libs\AceConfig-3.0\AceConfig-3.0.xml"/>
<Include file="Libs\AceEvent-3.0\AceEvent-3.0.xml"/>
<Include file="Libs\AceComm-3.0\AceComm-3.0.xml" />
<Include file="Libs\AceConsole-3.0\AceConsole-3.0.xml"/>
<Include file="Libs\AceSerializer-3.0\AceSerializer-3.0.xml"/>
<Script file="Libs\LibDataBroker-1.1\LibDataBroker-1.1.lua"/>
<Script file="Libs\LibDBIcon-1.0\LibDBIcon-1.0.lua"/>
</Ui>
@@ -1,116 +0,0 @@
local detailsFramework = _G ["DetailsFramework"]
if (not detailsFramework) then
return
end
local IS_WOW_PROJECT_MAINLINE = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE
local IS_WOW_PROJECT_NOT_MAINLINE = WOW_PROJECT_ID ~= WOW_PROJECT_MAINLINE
local IS_WOW_PROJECT_CLASSIC_ERA = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC
detailsFramework.CastInfo = detailsFramework.CastInfo or {}
--NOTE: This NEEDs a chance to run, as Plater is depending on this working and LibCC is not bundled neccessarily in other addons.
-- for classic era use LibClassicCasterino:
--in vanilla wow, other addons might load the framework before an addon with libCasterino loads
--check here if libCasterino is loaded, if is, check if the framework is already using libCasterino, if not, make it use
function detailsFramework:LoadLCC(LibCC)
local fCast = CreateFrame("frame")
local getCastBar = function(unitId)
local plateFrame = C_NamePlate.GetNamePlateForUnit (unitId)
if (not plateFrame) then
return
end
local castBar = plateFrame.unitFrame and plateFrame.unitFrame.castBar
if (not castBar) then
return
end
return castBar
end
local triggerCastEvent = function(castBar, event, unitId, ...)
if (castBar and castBar.OnEvent) then
return castBar.OnEvent (castBar, event, unitId)
end
end
local funcCast = function(event, unitId, ...)
local castBar = getCastBar (unitId)
if (castBar) then
return triggerCastEvent (castBar, event, unitId)
end
end
fCast.UNIT_SPELLCAST_START = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
fCast.UNIT_SPELLCAST_STOP = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
fCast.UNIT_SPELLCAST_DELAYED = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
fCast.UNIT_SPELLCAST_FAILED = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
fCast.UNIT_SPELLCAST_INTERRUPTED = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
fCast.UNIT_SPELLCAST_CHANNEL_START = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
fCast.UNIT_SPELLCAST_CHANNEL_UPDATE = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
fCast.UNIT_SPELLCAST_CHANNEL_STOP = function(self, event, unitId, ...)
return triggerCastEvent (getCastBar (unitId), event, unitId)
end
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_START", funcCast)
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_DELAYED", funcCast) -- only for player
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_STOP", funcCast)
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_FAILED", funcCast)
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_INTERRUPTED", funcCast)
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_CHANNEL_START", funcCast)
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_CHANNEL_UPDATE", funcCast) -- only for player
LibCC.RegisterCallback(fCast,"UNIT_SPELLCAST_CHANNEL_STOP", funcCast)
detailsFramework.CastInfo.UnitCastingInfo = function(unit)
return LibCC:UnitCastingInfo (unit)
end
detailsFramework.CastInfo.UnitChannelInfo = function(unit)
return LibCC:UnitChannelInfo (unit)
end
end
if IS_WOW_PROJECT_CLASSIC_ERA then
local LibCC = LibStub("LibClassicCasterino", true)
if (LibCC and not _G.DetailsFrameworkLCCLoaded) then
detailsFramework:LoadLCC(LibCC)
_G.DetailsFrameworkLCCLoaded = true
elseif not LibCC then
detailsFramework.CastInfo.UnitCastingInfo = CastingInfo
detailsFramework.CastInfo.UnitChannelInfo = ChannelInfo
end
else -- end classic era
detailsFramework.CastInfo.UnitCastingInfo = UnitCastingInfo
detailsFramework.CastInfo.UnitChannelInfo = UnitChannelInfo
end
if (not DetailsFrameworkCanLoad) then
return
end
@@ -1,600 +0,0 @@
---@class detailsframework
local detailsFramework = _G.DetailsFramework
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local CreateFrame = CreateFrame
local defaultRed, defaultGreen, defaultBlue = detailsFramework:GetDefaultBackdropColor()
--local defaultColorTable = {defaultRed, defaultGreen, defaultBlue, 1}
local defaultColorTable = {0.98, 0.98, 0.98, 1}
local defaultBorderColorTable = {0.1, 0.1, 0.1, 1}
---@type edgenames[]
local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"}
---@class blz_backdrop : table
---@field TopLeftCorner texture
---@field TopRightCorner texture
---@field BottomLeftCorner texture
---@field BottomRightCorner texture
---@field TopEdge texture
---@field BottomEdge texture
---@field LeftEdge texture
---@field RightEdge texture
---@field Center texture
---@class cornertextures : table
---@field TopLeft texture
---@field TopRight texture
---@field BottomLeft texture
---@field BottomRight texture
---@class edgetextures : table
---@field Top texture
---@field Bottom texture
---@field Left texture
---@field Right texture
---@class df_roundedpanel_preset : table
---@field border_color any
---@field color any
---@field roundness number
---@class df_roundedpanel_options : table
---@field width number
---@field height number
---@field use_titlebar boolean
---@field use_scalebar boolean
---@field title string
---@field scale number
---@field roundness number
---@field color any
---@field border_color any
---@field corner_texture texturepath|textureid
---@class df_roundedcornermixin : table
---@field RoundedCornerConstructor fun(self:df_roundedpanel) --called from CreateRoundedPanel
---@field SetColor fun(self:df_roundedpanel, red: any, green: number|nil, blue: number|nil, alpha: number|nil)
---@field SetBorderCornerColor fun(self:df_roundedpanel, red: any, green: number|nil, blue: number|nil, alpha: number|nil)
---@field SetRoundness fun(self:df_roundedpanel, slope: number)
---@field GetCornerSize fun(self:df_roundedpanel) : width, height
---@field OnSizeChanged fun(self:df_roundedpanel) --called when the frame size changes
---@field CreateBorder fun(self:df_roundedpanel) --called from SetBorderCornerColor if the border is not created yet
---@field CalculateBorderEdgeSize fun(self:df_roundedpanel, alignment: "vertical"|"horizontal"): number --calculate the size of the border edge texture
---@field SetTitleBarColor fun(self:df_roundedpanel, red: any, green: number|nil, blue: number|nil, alpha: number|nil)
---@class df_roundedpanel : frame, df_roundedcornermixin, df_optionsmixin, df_titlebar
---@field bHasBorder boolean
---@field bHasTitleBar boolean
---@field options df_roundedpanel_options
---@field cornerRoundness number
---@field CornerTextures cornertextures
---@field CenterTextures texture[]
---@field BorderCornerTextures cornertextures
---@field BorderEdgeTextures edgetextures
---@field TitleBar df_roundedpanel
---@field TopLeft texture corner texture
---@field TopRight texture corner texture
---@field BottomLeft texture corner texture
---@field BottomRight texture corner texture
---@field TopEdgeBorder texture border edge
---@field BottomEdgeBorder texture border edge
---@field LeftEdgeBorder texture border edge
---@field RightEdgeBorder texture border edge
---@field TopLeftBorder texture border corner
---@field TopRightBorder texture border corner
---@field BottomLeftBorder texture border corner
---@field BottomRightBorder texture border corner
---@field TopHorizontalEdge texture texture connecting the top corners
---@field BottomHorizontalEdge texture texture connecting the bottom corners
---@field CenterBlock texture texture connecting the bottom left of the topleft corner with the top right of the bottom right corner
---@param self df_roundedpanel
---@param textures cornertextures
---@param width number|nil
---@param height number|nil
---@param xOffset number|nil
---@param yOffset number|nil
---@param bIsBorder boolean|nil
local setCornerPoints = function(self, textures, width, height, xOffset, yOffset, bIsBorder)
for cornerName, thisTexture in pairs(textures) do
thisTexture:SetSize(width or 16, height or 16)
thisTexture:SetTexture(self.options.corner_texture)
--set the mask
if (not thisTexture.MaskTexture and bIsBorder) then
thisTexture.MaskTexture = self:CreateMaskTexture(nil, "background")
thisTexture.MaskTexture:SetSize(74, 64)
thisTexture:AddMaskTexture(thisTexture.MaskTexture)
thisTexture.MaskTexture:SetTexture([[Interface\Azerite\AzeriteGoldRingRank2]]) --1940690
--thisTexture.MaskTexture:Hide()
end
xOffset = xOffset or 0
yOffset = yOffset or 0
--todo: adjust the other corners setpoint offset
--todo (done): use mask when the alpha is below 0.98, disable the mask when the alpha is above 0.98
if (cornerName == "TopLeft") then
thisTexture:SetTexCoord(0, 0.5, 0, 0.5)
thisTexture:SetPoint(cornerName, self, cornerName, -xOffset, yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18-xOffset, 16+yOffset)
end
elseif (cornerName == "TopRight") then
thisTexture:SetTexCoord(0.5, 1, 0, 0.5)
thisTexture:SetPoint(cornerName, self, cornerName, xOffset, yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18+xOffset, 16+yOffset)
end
elseif (cornerName == "BottomLeft") then
thisTexture:SetTexCoord(0, 0.5, 0.5, 1)
thisTexture:SetPoint(cornerName, self, cornerName, -xOffset, -yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18-xOffset, 16-yOffset)
end
elseif (cornerName == "BottomRight") then
thisTexture:SetTexCoord(0.5, 1, 0.5, 1)
thisTexture:SetPoint(cornerName, self, cornerName, xOffset, -yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18+xOffset, 16-yOffset)
end
end
end
end
detailsFramework.RoundedCornerPanelMixin = {
RoundedCornerConstructor = function(self)
self.CornerTextures = {}
self.CenterTextures = {}
self.BorderCornerTextures = {}
self.BorderEdgeTextures = {}
self.cornerRoundness = 0
for i = 1, #cornerNames do
---@type texture
local newCornerTexture = self:CreateTexture(nil, "border", nil, 0)
self.CornerTextures[cornerNames[i]] = newCornerTexture
self[cornerNames[i]] = newCornerTexture
end
--create the top texture which connects the top corners with a horizontal line
---@type texture
local topHorizontalEdge = self:CreateTexture(nil, "border", nil, 0)
topHorizontalEdge:SetPoint("topleft", self.CornerTextures["TopLeft"], "topright", 0, 0)
topHorizontalEdge:SetPoint("bottomleft", self.CornerTextures["TopLeft"], "bottomright", 0, 0)
topHorizontalEdge:SetPoint("topright", self.CornerTextures["TopRight"], "topleft", 0, 0)
topHorizontalEdge:SetPoint("bottomright", self.CornerTextures["TopRight"], "bottomleft", 0, 0)
topHorizontalEdge:SetColorTexture(unpack(defaultColorTable))
--create the bottom texture which connects the bottom corners with a horizontal line
---@type texture
local bottomHorizontalEdge = self:CreateTexture(nil, "border", nil, 0)
bottomHorizontalEdge:SetPoint("topleft", self.CornerTextures["BottomLeft"], "topright", 0, 0)
bottomHorizontalEdge:SetPoint("bottomleft", self.CornerTextures["BottomLeft"], "bottomright", 0, 0)
bottomHorizontalEdge:SetPoint("topright", self.CornerTextures["BottomRight"], "topleft", 0, 0)
bottomHorizontalEdge:SetPoint("bottomright", self.CornerTextures["BottomRight"], "bottomleft", 0, 0)
bottomHorizontalEdge:SetColorTexture(unpack(defaultColorTable))
--create the center block which connects the bottom left of the topleft corner with the top right of the bottom right corner
---@type texture
local centerBlock = self:CreateTexture(nil, "border", nil, 0)
centerBlock:SetPoint("topleft", self.CornerTextures["TopLeft"], "bottomleft", 0, 0)
centerBlock:SetPoint("bottomleft", self.CornerTextures["BottomLeft"], "topleft", 0, 0)
centerBlock:SetPoint("topright", self.CornerTextures["BottomRight"], "topright", 0, 0)
centerBlock:SetPoint("bottomright", self.CornerTextures["BottomRight"], "topright", 0, 0)
centerBlock:SetColorTexture(unpack(defaultColorTable))
self.CenterTextures[#self.CenterTextures+1] = topHorizontalEdge
self.CenterTextures[#self.CenterTextures+1] = bottomHorizontalEdge
self.CenterTextures[#self.CenterTextures+1] = centerBlock
self.TopHorizontalEdge = topHorizontalEdge
self.BottomHorizontalEdge = bottomHorizontalEdge
self.CenterBlock = centerBlock
---@type width
local width = self.options.width
---@type height
local height = self.options.height
self:SetSize(width, height)
--fill the corner and edge textures table
setCornerPoints(self, self.CornerTextures)
end,
---return the width and height of the corner textures
---@param self df_roundedpanel
---@return number, number
GetCornerSize = function(self)
return self.CornerTextures["TopLeft"]:GetSize()
end,
---set how rounded the corners should be
---@param self df_roundedpanel
---@param roundness number
SetRoundness = function(self, roundness)
self.cornerRoundness = roundness
self:OnSizeChanged()
end,
---adjust the size of the corner textures and the border edge textures
---@param self df_roundedpanel
OnSizeChanged = function(self)
--if the frame has a titlebar, need to adjust the size of the titlebar
if (self.bHasTitleBar) then
self.TitleBar:SetWidth(self:GetWidth() - 14)
end
--if the frame height is below 32, need to recalculate the size of the corners
---@type height
local frameHeight = self:GetHeight()
if (frameHeight < 32) then
local newCornerSize = frameHeight / 2
--set the new size of the corners on all corner textures
for _, thisTexture in pairs(self.CornerTextures) do
thisTexture:SetSize(newCornerSize-self.cornerRoundness, newCornerSize)
end
--check if the frame has border and set the size of the border corners as well
if (self.bHasBorder) then
for _, thisTexture in pairs(self.BorderCornerTextures) do
thisTexture:SetSize(newCornerSize, newCornerSize)
end
--hide the left and right edges as the corner textures already is enough to fill the frame
self.BorderEdgeTextures["Left"]:Hide()
self.BorderEdgeTextures["Right"]:Hide()
local horizontalEdgesNewSize = self:CalculateBorderEdgeSize("horizontal")
self.BorderEdgeTextures["Top"]:SetSize(horizontalEdgesNewSize, 1)
self.BorderEdgeTextures["Bottom"]:SetSize(horizontalEdgesNewSize, 1)
end
self.CenterBlock:Hide()
else
if (self.bHasBorder) then
self.BorderEdgeTextures["Left"]:Show()
self.BorderEdgeTextures["Right"]:Show()
end
---@type width, height
local cornerWidth, cornerHeight = 16, 16
self.CenterBlock:Show()
for _, thisTexture in pairs(self.CornerTextures) do
thisTexture:SetSize(cornerWidth-self.cornerRoundness, cornerHeight-self.cornerRoundness)
end
if (self.bHasBorder) then
for _, thisTexture in pairs(self.BorderCornerTextures) do
thisTexture:SetSize(cornerWidth-self.cornerRoundness, cornerHeight-self.cornerRoundness)
thisTexture.MaskTexture:SetSize(74-(self.cornerRoundness*0.75), 64-self.cornerRoundness)
end
local horizontalEdgesNewSize = self:CalculateBorderEdgeSize("horizontal")
self.BorderEdgeTextures["Top"]:SetSize(horizontalEdgesNewSize, 1)
self.BorderEdgeTextures["Bottom"]:SetSize(horizontalEdgesNewSize, 1)
local verticalEdgesNewSize = self:CalculateBorderEdgeSize("vertical")
self.BorderEdgeTextures["Left"]:SetSize(1, verticalEdgesNewSize)
self.BorderEdgeTextures["Right"]:SetSize(1, verticalEdgesNewSize)
end
end
end,
---get the size of the edge texture
---@param self df_roundedpanel
---@param alignment "vertical"|"horizontal"
---@return number edgeSize
CalculateBorderEdgeSize = function(self, alignment)
---@type string
local borderCornerName = next(self.BorderCornerTextures)
if (not borderCornerName) then
return 0
end
---@type texture
local borderTexture = self.BorderCornerTextures[borderCornerName]
alignment = alignment:lower()
if (alignment == "vertical") then
return self:GetHeight() - (borderTexture:GetHeight() * 2) + 2
elseif (alignment == "horizontal") then
return self:GetWidth() - (borderTexture:GetHeight() * 2) + 2
end
error("df_roundedpanel:CalculateBorderEdgeSize(self, alignment) alignment must be 'vertical' or 'horizontal'")
end,
---@param self df_roundedpanel
CreateBorder = function(self)
local r, g, b, a = 0, 0, 0, 0.8
--create the corner edges
for i = 1, #cornerNames do
---@type texture
local newBorderTexture = self:CreateTexture(nil, "background", nil, 0)
self.BorderCornerTextures[cornerNames[i]] = newBorderTexture
newBorderTexture:SetColorTexture(unpack(defaultColorTable))
newBorderTexture:SetVertexColor(r, g, b, a)
self[cornerNames[i] .. "Border"] = newBorderTexture
end
setCornerPoints(self, self.BorderCornerTextures, 16, 16, 1, 1, true)
--create the top, left, bottom and right edges, the edge has 1pixel width and connects the corners
---@type texture
local topEdge = self:CreateTexture(nil, "background", nil, 0)
topEdge:SetPoint("bottom", self, "top", 0, 0)
self.BorderEdgeTextures["Top"] = topEdge
---@type texture
local leftEdge = self:CreateTexture(nil, "background", nil, 0)
leftEdge:SetPoint("right", self, "left", 0, 0)
self.BorderEdgeTextures["Left"] = leftEdge
---@type texture
local bottomEdge = self:CreateTexture(nil, "background", nil, 0)
bottomEdge:SetPoint("top", self, "bottom", 0, 0)
self.BorderEdgeTextures["Bottom"] = bottomEdge
---@type texture
local rightEdge = self:CreateTexture(nil, "background", nil, 0)
rightEdge:SetPoint("left", self, "right", 0, 0)
self.BorderEdgeTextures["Right"] = rightEdge
---@type width
local horizontalEdgeSize = self:CalculateBorderEdgeSize("horizontal")
---@type height
local verticalEdgeSize = self:CalculateBorderEdgeSize("vertical")
--set the edges size
topEdge:SetSize(horizontalEdgeSize, 1)
leftEdge:SetSize(1, verticalEdgeSize)
bottomEdge:SetSize(horizontalEdgeSize, 1)
rightEdge:SetSize(1, verticalEdgeSize)
for edgeName, thisTexture in pairs(self.BorderEdgeTextures) do
---@cast thisTexture texture
thisTexture:SetColorTexture(unpack(defaultColorTable))
thisTexture:SetVertexColor(r, g, b, a)
end
self.TopEdgeBorder = topEdge
self.BottomEdgeBorder = bottomEdge
self.LeftEdgeBorder = leftEdge
self.RightEdgeBorder = rightEdge
self.bHasBorder = true
end,
---@param self df_roundedpanel
---@param red any
---@param green number|nil
---@param blue number|nil
---@param alpha number|nil
SetTitleBarColor = function(self, red, green, blue, alpha)
if (self.bHasTitleBar) then
red, green, blue, alpha = detailsFramework:ParseColors(red, green, blue, alpha)
self.TitleBar:SetColor(red, green, blue, alpha)
end
end,
---@param self df_roundedpanel
---@param red any
---@param green number|nil
---@param blue number|nil
---@param alpha number|nil
SetBorderCornerColor = function(self, red, green, blue, alpha)
if (not self.bHasBorder) then
self:CreateBorder()
end
red, green, blue, alpha = detailsFramework:ParseColors(red, green, blue, alpha)
for _, thisTexture in pairs(self.BorderCornerTextures) do
thisTexture:SetVertexColor(red, green, blue, alpha)
end
for _, thisTexture in pairs(self.BorderEdgeTextures) do
thisTexture:SetVertexColor(red, green, blue, alpha)
end
end,
---@param self df_roundedpanel
---@param red any
---@param green number|nil
---@param blue number|nil
---@param alpha number|nil
SetColor = function(self, red, green, blue, alpha)
red, green, blue, alpha = detailsFramework:ParseColors(red, green, blue, alpha)
for _, thisTexture in pairs(self.CornerTextures) do
thisTexture:SetVertexColor(red, green, blue, alpha)
end
for _, thisTexture in pairs(self.CenterTextures) do
thisTexture:SetVertexColor(red, green, blue, alpha)
end
if (self.bHasBorder) then
if (alpha < 0.98) then
--if using borders, the two border textures overlaps making the alpha be darker than it should
for _, thisTexture in pairs(self.BorderCornerTextures) do
thisTexture.MaskTexture:Show()
end
else
for _, thisTexture in pairs(self.BorderCornerTextures) do
thisTexture.MaskTexture:Hide()
end
end
end
end,
}
local defaultOptions = {
width = 200,
height = 200,
use_titlebar = false,
use_scalebar = false,
title = "",
scale = 1,
roundness = 0,
color = defaultColorTable,
border_color = defaultColorTable,
corner_texture = [[Interface\CHARACTERFRAME\TempPortraitAlphaMaskSmall]],
}
local defaultPreset = {
border_color = {.1, .1, .1, 0.834},
color = {defaultRed, defaultGreen, defaultBlue},
roundness = 3,
}
---create a regular panel with rounded corner
---@param parent frame
---@param name string|nil
---@param optionsTable table|nil
---@return df_roundedpanel
function detailsFramework:CreateRoundedPanel(parent, name, optionsTable)
---@type df_roundedpanel
local newRoundedPanel = CreateFrame("frame", name, parent, "BackdropTemplate")
newRoundedPanel:EnableMouse(true)
newRoundedPanel.__dftype = "df_roundedpanel"
newRoundedPanel.__rcorners = true
detailsFramework:Mixin(newRoundedPanel, detailsFramework.RoundedCornerPanelMixin)
detailsFramework:Mixin(newRoundedPanel, detailsFramework.OptionsFunctions)
newRoundedPanel:BuildOptionsTable(defaultOptions, optionsTable or {})
newRoundedPanel:RoundedCornerConstructor()
newRoundedPanel:SetScript("OnSizeChanged", newRoundedPanel.OnSizeChanged)
if (newRoundedPanel.options.use_titlebar) then
---@type df_roundedpanel
local titleBar = detailsFramework:CreateRoundedPanel(newRoundedPanel, "$parentTitleBar", {height = 26})
titleBar:SetPoint("top", newRoundedPanel, "top", 0, -7)
newRoundedPanel.TitleBar = titleBar
titleBar:SetRoundness(5)
newRoundedPanel.bHasTitleBar = true
end
if (newRoundedPanel.options.use_scalebar) then
detailsFramework:CreateScaleBar(newRoundedPanel.TitleBar or newRoundedPanel, newRoundedPanel.options)
newRoundedPanel:SetScale(newRoundedPanel.options.scale)
end
newRoundedPanel:SetRoundness(newRoundedPanel.options.roundness)
newRoundedPanel:SetColor(newRoundedPanel.options.color)
newRoundedPanel:SetBorderCornerColor(newRoundedPanel.options.border_color)
return newRoundedPanel
end
local applyPreset = function(frame, preset)
if (preset.border_color) then
frame:SetBorderCornerColor(preset.border_color)
end
if (preset.color) then
frame:SetColor(preset.color)
end
if (preset.roundness) then
frame:SetRoundness(preset.roundness)
else
frame:SetRoundness(1)
end
end
---set a frame to have rounded corners following the settings passed by the preset table
---@param frame frame
---@param preset df_roundedpanel_preset|nil
function detailsFramework:AddRoundedCornersToFrame(frame, preset)
frame = frame and frame.widget or frame
assert(frame and frame.GetObjectType and frame.SetPoint, "AddRoundedCornersToFrame(frame): frame must be a frame object.")
if (frame.GetBackdropBorderColor) then
local red, green, blue, alpha = frame:GetBackdropBorderColor()
if (alpha and alpha > 0) then
detailsFramework:MsgWarning("AddRoundedCornersToFrame() applyed to a frame with a backdrop border.")
detailsFramework:Msg(debugstack(2, 1, 0))
end
end
---@cast frame +df_roundedcornermixin
detailsFramework:Mixin(frame, detailsFramework.RoundedCornerPanelMixin)
if (not frame["BuildOptionsTable"]) then
---@cast frame +df_optionsmixin
detailsFramework:Mixin(frame, detailsFramework.OptionsFunctions)
end
frame:BuildOptionsTable(defaultOptions, {})
frame.options.width = frame:GetWidth()
frame.options.height = frame:GetHeight()
frame:RoundedCornerConstructor()
frame:HookScript("OnSizeChanged", frame.OnSizeChanged)
frame.__rcorners = true
--handle preset
if (preset and type(preset) == "table") then
applyPreset(frame, preset)
else
applyPreset(frame, defaultPreset)
end
end
---test case:
C_Timer.After(1, function() if true then return end
local DF = DetailsFramework
local parent = UIParent
local name = "NewRoundedCornerFrame"
local optionsTable = {
use_titlebar = true,
use_scalebar = true,
title = "Test",
scale = 1.0,
}
---@type df_roundedpanel
local frame = _G[name] or DF:CreateRoundedPanel(parent, name, optionsTable)
frame:SetSize(800, 600)
frame:SetPoint("center", parent, "center", 0, 0)
frame:SetColor(.1, .1, .1, 1)
frame:SetTitleBarColor(.2, .2, .2, .5)
frame:SetBorderCornerColor(.2, .2, .2, .5)
frame:SetRoundness(0)
local radiusSlider = DF:CreateSlider(frame, 120, 14, 0, 15, 1, frame.cornerRoundness, false, "RadiusBar", nil, nil, DF:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE"))
radiusSlider:SetHook("OnValueChange", function(self, fixedValue, value)
value = floor(value)
if (frame.cornerRoundness == value) then
return
end
frame:SetRoundness(value)
end)
local radiusText = frame:CreateFontString(nil, "overlay", "GameFontNormal")
radiusText:SetText("Radius:")
radiusText:SetPoint("bottomleft", radiusSlider.widget, "topleft", 0, 0)
radiusSlider:SetPoint(10, -100)
end)
File diff suppressed because it is too large Load Diff
@@ -1,686 +0,0 @@
local detailsFramework = DetailsFramework
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local unpack = unpack
local CreateFrame = CreateFrame
local geterrorhandler = geterrorhandler
local wipe = wipe
--definitions
---@class df_headercolumndata : {key: string, name: string, icon: string, texcoord: table, text: string, canSort: boolean, selected: boolean, width: number, height: number, align: string, offset: number}
---@class df_headerchild : uiobject
---@field FramesToAlign table
---@class df_headerframe : frame, df_headermixin, df_optionsmixin
---@field columnHeadersCreated df_headercolumnframe[]
---@field options table
---@field HeaderTable df_headercolumndata[]
---@field columnSelected number
---@class df_headermixin : table
---@field NextHeader number
---@field HeaderWidth number
---@field HeaderHeight number
---@field OnColumnSettingChangeCallback function
---@field GetColumnWidth fun(self: df_headerframe, columnId: number) : number
---@field SetHeaderTable fun(self: df_headerframe, table)
---@field GetSelectedColumn fun(self: df_headerframe) : number, string, string, string
---@field Refresh fun(self: df_headerframe)
---@field UpdateSortArrow fun(self: df_headerframe, columnHeader: df_headercolumnframe, defaultShown: boolean|nil, defaultOrder: string|nil)
---@field UpdateColumnHeader fun(self: df_headerframe, columnHeader: df_headercolumnframe, headerIndex)
---@field ResetColumnHeaderBackdrop fun(self: df_headerframe, columnHeader: df_headercolumnframe)
---@field SetBackdropColorForSelectedColumnHeader fun(self: df_headerframe, columnHeader: df_headercolumnframe)
---@field ClearColumnHeader fun(self: df_headerframe, columnHeader: df_headercolumnframe)
---@field GetNextHeader fun(self: df_headerframe) : df_headercolumnframe
---@field SetColumnSettingChangedCallback fun(self: df_headerframe, func: function) : boolean
---@class df_headercolumnframe : button
---@field Icon texture
---@field Text fontstring
---@field Arrow texture
---@field Separator texture
---@field resizerButton df_headerresizer
---@field bIsRezising boolean
---@field bInUse boolean
---@field columnData table
---@field order string
---@field columnIndex number
---@field columnAlign string
---@field XPosition number
---@field columnOffset number
---@field key string used to sort the values
---@class df_headerresizer : button
---@field texture texture
--mixed functions
---@class df_headerfunctions : table
detailsFramework.HeaderFunctions = {
---comment
---@param self df_headerchild
---@param frame uiobject
AddFrameToHeaderAlignment = function(self, frame)
self.FramesToAlign = self.FramesToAlign or {}
table.insert(self.FramesToAlign, frame)
end,
---comment
---@param self df_headerchild
ResetFramesToHeaderAlignment = function(self)
wipe(self.FramesToAlign)
end,
SetFramesToHeaderAlignment = function(self, ...)
---@cast self df_headerchild
wipe(self.FramesToAlign)
self.FramesToAlign = {...}
end,
GetFramesFromHeaderAlignment = function(self, frame)
return self.FramesToAlign or {}
end,
---@param self uiobject
---@param headerFrame df_headerframe
---@param anchor string
AlignWithHeader = function(self, headerFrame, anchor)
local columnHeaderFrames = headerFrame.columnHeadersCreated
anchor = anchor or "topleft"
---@cast self df_headerchild
for i = 1, #self.FramesToAlign do
---@type uiobject
local uiObject = self.FramesToAlign[i]
uiObject:ClearAllPoints()
---@type df_headercolumnframe
local columnHeader = columnHeaderFrames[i]
if (columnHeader) then
local offset = 0
if (columnHeader.columnAlign == "right") then
offset = columnHeader:GetWidth()
end
if (uiObject:GetObjectType() == "FontString") then
---@cast uiObject fontstring
if (columnHeader.columnAlign == "right") then
uiObject:SetJustifyH("right")
elseif (columnHeader.columnAlign == "left") then
uiObject:SetJustifyH("left")
elseif (columnHeader.columnAlign == "center") then
uiObject:SetJustifyH("center")
end
end
uiObject:SetPoint(columnHeader.columnAlign, self, anchor, columnHeader.XPosition + columnHeader.columnOffset + offset, 0)
end
end
end,
---comment
---@param columnHeader df_headercolumnframe
---@param buttonClicked string
OnClick = function(columnHeader, buttonClicked)
--get the header main frame
local headerFrame = columnHeader:GetParent()
---@cast headerFrame df_headerframe
--if this header does not have a clickable header, just ignore
if (not headerFrame.columnSelected) then
return
end
--check if this column has 'canSort' key, otherwise ignore the click
if (not columnHeader.columnData.canSort) then
return
end
--get the latest column header selected
---@type df_headercolumnframe
local previousColumnHeader = headerFrame.columnHeadersCreated[headerFrame.columnSelected]
previousColumnHeader.Arrow:Hide()
headerFrame:ResetColumnHeaderBackdrop(previousColumnHeader)
headerFrame:SetBackdropColorForSelectedColumnHeader(columnHeader)
if (headerFrame.columnSelected == columnHeader.columnIndex) then
columnHeader.order = columnHeader.order ~= "ASC" and "ASC" or "DESC"
end
headerFrame.columnOrder = columnHeader.order
--set the new column header selected
headerFrame.columnSelected = columnHeader.columnIndex
headerFrame:UpdateSortArrow(columnHeader)
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, columnHeader, columnHeader.columnIndex, columnHeader.order)
if (not okay) then
print("DF: Header onClick callback error:", errortext)
end
end
end,
---comment
---@param self button
---@param buttonClicked string
OnMouseDown = function(self, buttonClicked)
if (buttonClicked == "LeftButton") then
end
end,
---comment
---@param self button
---@param buttonClicked string
OnMouseUp = function(self, buttonClicked)
if (buttonClicked == "LeftButton") then
end
end,
}
---@class df_headermixin : table
detailsFramework.HeaderMixin = {
---@param self df_headerframe
---@param columnId number
---@return number
GetColumnWidth = function(self, columnId)
return self.HeaderTable[columnId].width
end,
---@param self df_headerframe
---@param newTable table
SetHeaderTable = function(self, newTable)
self.columnHeadersCreated = self.columnHeadersCreated or {}
self.HeaderTable = newTable
self.NextHeader = 1
self.HeaderWidth = 0
self.HeaderHeight = 0
self:Refresh()
end,
---@param self df_headerframe
---@param func function
---@return boolean
SetColumnSettingChangedCallback = function(self, func)
if (type(func) ~= "function") then
self.OnColumnSettingChangeCallback = nil
return false
end
self.OnColumnSettingChangeCallback = func
return true
end,
--return which header is current selected and the the order ASC DESC
---@param self df_headerframe
---@return number, string, string, string
GetSelectedColumn = function(self)
---@type number
local columnSelected = self.columnSelected
---@type df_headercolumnframe
local columnHeader = self.columnHeadersCreated[columnSelected or 1]
return columnSelected, columnHeader.order, columnHeader.key, columnHeader.columnData.name
end,
--clean up and rebuild the header following the header options
--@self: main header frame
---@param self df_headerframe
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.bInUse = false
columnHeader:Hide()
end
local previousColumnHeader
local growDirection = string.lower(self.options.grow_direction)
--amount of headers to be updated
local headerSize = #self.HeaderTable
--update header frames
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,
---@param self df_headerframe
---@param columnHeader df_headercolumnframe
---@param defaultShown boolean
---@param defaultOrder string
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,
---@param self df_headerframe
---@param columnHeader df_headercolumnframe
---@param headerIndex number
UpdateColumnHeader = function(self, columnHeader, headerIndex)
--this is the data to update the columnHeader
local columnData = self.HeaderTable[headerIndex]
columnHeader.key = columnData.key or "total"
if (columnData.icon) then
columnHeader.Icon:SetTexture(columnData.icon)
if (columnData.texcoord) then
columnHeader.Icon:SetTexCoord(unpack(columnData.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 (columnData.text) then
columnHeader.Text:SetText(columnData.text)
--text options
detailsFramework:SetFontColor(columnHeader.Text, self.options.text_color)
detailsFramework:SetFontSize(columnHeader.Text, self.options.text_size)
detailsFramework:SetFontOutline(columnHeader.Text, self.options.text_shadow)
--point
if (not columnData.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 (columnData.canSort) then
columnHeader.order = "DESC"
columnHeader.Arrow:SetTexture(self.options.arrow_up_texture)
else
columnHeader.Arrow:Hide()
end
if (columnData.selected) then
columnHeader.Arrow:Show()
columnHeader.Arrow:SetAlpha(.843)
self:UpdateSortArrow(columnHeader, true, columnHeader.order)
self.columnSelected = headerIndex
else
if (columnData.canSort) then
self:UpdateSortArrow(columnHeader, false, columnHeader.order)
end
end
--size
if (columnData.width) then
columnHeader:SetWidth(columnData.width)
end
if (columnData.height) then
columnHeader:SetHeight(columnData.height)
end
columnHeader.XPosition = self.HeaderWidth -- + self.options.padding
columnHeader.YPosition = self.HeaderHeight -- + self.options.padding
columnHeader.columnAlign = columnData.align or "left"
columnHeader.columnOffset = columnData.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
local bShowColumnHeaderReziser = self.options.reziser_shown
if (bShowColumnHeaderReziser) then
local resizerButton = columnHeader.resizerButton
resizerButton:Show()
resizerButton.texture:SetVertexColor(unpack(self.options.reziser_color))
resizerButton:SetWidth(self.options.reziser_width)
resizerButton:SetHeight(columnHeader:GetHeight())
else
columnHeader.resizerButton:Hide()
end
columnHeader:Show()
columnHeader.bInUse = true
columnHeader.columnData = columnData
end,
---reset column header backdrop
---@param self df_headerframe
---@param columnHeader df_headercolumnframe
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,
---@param self df_headerframe
---@param columnHeader df_headercolumnframe
SetBackdropColorForSelectedColumnHeader = function(self, columnHeader)
columnHeader:SetBackdropColor(unpack(self.options.header_backdrop_color_selected))
end,
---clear the column header
---@param self df_headerframe
---@param columnHeader df_headercolumnframe
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
---@param self df_headerframe
GetNextHeader = function(self)
local nextHeader = self.NextHeader
local columnHeader = self.columnHeadersCreated[nextHeader]
if (not columnHeader) then
--create a new column header
---@type df_headercolumnframe
columnHeader = CreateFrame("button", "$parentHeaderIndex" .. nextHeader, self, "BackdropTemplate")
columnHeader:SetScript("OnClick", detailsFramework.HeaderFunctions.OnClick)
columnHeader:SetMovable(true)
columnHeader:SetResizable(true)
--header icon
detailsFramework:CreateImage(columnHeader, "", self.options.header_height, self.options.header_height, "ARTWORK", nil, "Icon", "$parentIcon")
--header separator
detailsFramework:CreateImage(columnHeader, "", 1, 1, "ARTWORK", nil, "Separator", "$parentSeparator")
--header name text
detailsFramework:CreateLabel(columnHeader, "", self.options.text_size, self.options.text_color, "GameFontNormal", "Text", "$parentText", "ARTWORK")
--header selected and order icon
detailsFramework:CreateImage(columnHeader, self.options.arrow_up_texture, 12, 12, "ARTWORK", nil, "Arrow", "$parentArrow")
---rezise button
---@type df_headerresizer
local resizerButton = CreateFrame("button", "$parentResizer", columnHeader)
resizerButton:SetWidth(4)
resizerButton:SetFrameLevel(columnHeader:GetFrameLevel()+2)
resizerButton:SetPoint("topright", columnHeader, "topright", -1, -1)
resizerButton:SetPoint("bottomright", columnHeader, "bottomright", -1, 1)
resizerButton:EnableMouse(true)
resizerButton:RegisterForClicks("LeftButtonDown", "LeftButtonUp")
columnHeader.resizerButton = resizerButton
resizerButton:SetScript("OnEnter", function()
resizerButton.texture:SetVertexColor(1, 1, 1, 0.9)
end)
resizerButton:SetScript("OnLeave", function()
resizerButton.texture:SetVertexColor(unpack(self.options.reziser_color))
end)
resizerButton:SetScript("OnMouseDown", function() --move this to a single function
if (not columnHeader.bIsRezising) then
--get the string length to know the min size
local textLength = columnHeader.Text:GetStringWidth() + 6
columnHeader:SetResizeBounds(math.max(textLength, self.options.reziser_min_width), columnHeader:GetHeight(), self.options.reziser_max_width, columnHeader:GetHeight())
columnHeader.bIsRezising = true
columnHeader:StartSizing("right")
end
end)
resizerButton:SetScript("OnMouseUp", function()
if (columnHeader.bIsRezising) then
columnHeader.bIsRezising = false
columnHeader:StopMovingOrSizing()
--callback or modify into a passed by table?
if (self.OnColumnSettingChangeCallback) then --need to get the header name
local columnName = columnHeader.columnData.name
xpcall(self.OnColumnSettingChangeCallback, geterrorhandler(), self, "width", columnName, columnHeader:GetWidth())
end
end
end)
resizerButton:SetScript("OnHide", function()
if (columnHeader.bIsRezising) then
columnHeader:StopMovingOrSizing()
columnHeader.bIsRezising = false
end
end)
resizerButton.texture = resizerButton:CreateTexture(nil, "overlay")
resizerButton.texture:SetAllPoints()
resizerButton.texture:SetColorTexture(1, 1, 1, 1)
local xOffset = self.options.reziser_shown and -5 or -1
columnHeader.Arrow:SetPoint("right", columnHeader, "right", xOffset, 0)
columnHeader.Separator:Hide()
columnHeader.Arrow:Hide()
self:UpdateSortArrow(columnHeader, false, "DESC")
table.insert(self.columnHeadersCreated, columnHeader)
columnHeader = columnHeader
end
self:ClearColumnHeader(columnHeader)
self.NextHeader = self.NextHeader + 1
return columnHeader
end,
---return a header button by passing its name (.name on the column table)
---@param self df_headerframe
---@param columnName string
---@return df_headercolumnframe|nil
GetHeaderColumnByName = function(self, columnName)
for _, headerColumnFrame in ipairs(self.columnHeadersCreated) do
if (headerColumnFrame.columnData.name == columnName) then
return headerColumnFrame
end
end
end,
NextHeader = 1,
HeaderWidth = 0,
HeaderHeight = 0,
}
--default options
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,
reziser_shown = false, --make sure to set the callback function with: header:SetOnColumnResizeScript(callbackFunction)
reziser_width = 2,
reziser_color = {1, 0.6, 0, 0.6},
reziser_min_width = 16,
reziser_max_width = 200,
--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,
}
---create a df_headerframe, alias 'header'.
---a header is a frame that can hold multiple columns which are also frames, each column is a df_headercolumnframe, these columns are arranged in horizontal form.
---a header is used to organize columns giving them a name/title, a way to sort and align them.
---each column is placed on the right side of the previous column.
---@param parent frame
---@param headerTable table
---@param options table|nil
---@param frameName string|nil
---@return df_headerframe
function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
---create the header frame which is returned by this function
---@type df_headerframe
local newHeader = CreateFrame("frame", frameName or "$parentHeaderLine", parent, "BackdropTemplate")
detailsFramework:Mixin(newHeader, detailsFramework.OptionsFunctions)
detailsFramework:Mixin(newHeader, detailsFramework.HeaderMixin)
newHeader:BuildOptionsTable(default_header_options, options)
--set the backdrop and backdrop color following the values in the options table
newHeader:SetBackdrop(newHeader.options.backdrop)
newHeader:SetBackdropColor(unpack(newHeader.options.backdrop_color))
newHeader:SetBackdropBorderColor(unpack(newHeader.options.backdrop_border_color))
newHeader:SetHeaderTable(headerTable)
return newHeader
end
--[=[example:
C_Timer.After(1, function()
local parent = UIParent
--declare the columns the headerFrame will have
---@type df_headercolumndata[]
local headerTable = {
{name = "playername", text = "Player Name", width = 120, align = "left", canSort = true},
{name = "damage", text = "Damage Done", width = 80, align = "right", canSort = true},
{name = "points", text = "Total Points", width = 80, align = "right", canSort = false},
}
local frameName = "MyAddOnOptionsFrame"
local options = {}
local headerFrame = DetailsFramework:CreateHeader(parent, headerTable, options, frameName)
headerFrame:SetPoint("center", parent, "center", 10, -10)
end)
--]=]
@@ -1,123 +0,0 @@
local DF = _G ["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
local _
local rawset = rawset --lua local
local rawget = rawget --lua local
local APIHelpFunctions = false
local HelpMetaFunctions = {}
local get_members_function_index = {}
HelpMetaFunctions.__index = function(_table, _member_requested)
local func = get_members_function_index [_member_requested]
if (func) then
return func (_table, _member_requested)
end
local fromMe = rawget (_table, _member_requested)
if (fromMe) then
return fromMe
end
return HelpMetaFunctions [_member_requested]
end
local set_members_function_index = {}
HelpMetaFunctions.__newindex = function(_table, _key, _value)
local func = set_members_function_index [_key]
if (func) then
return func (_table, _value)
else
return rawset (_table, _key, _value)
end
end
function HelpMetaFunctions:AddHelp (width, height, x, y, buttonX, buttonY, text, anchor)
self.helpTable [#self.helpTable + 1] = {
HighLightBox = {x = x, y = y, width = width, height = height},
ButtonPos = { x = buttonX, y = buttonY},
ToolTipDir = anchor or "RIGHT",
ToolTipText = text
}
end
function HelpMetaFunctions: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
function HelpMetaFunctions:ShowHelp()
if (not HelpPlate_IsShowing (self.helpTable)) then
HelpPlate_Show (self.helpTable, self.frame, self.button, true)
else
HelpPlate_Hide (true)
end
end
local nameCounter = 1
function DF:NewHelp (parent, width, height, x, y, buttonWidth, buttonHeight, name)
local help = {}
if (parent.dframework) then
parent = parent.widget
end
local helpButton = CreateFrame("button", name or "DetailsFrameworkHelpButton"..nameCounter, parent, "MainHelpPlateButton")
nameCounter = nameCounter + 1
if (not APIHelpFunctions) then
APIHelpFunctions = true
local idx = getmetatable(helpButton).__index
for funcName, funcAddress in pairs(idx) do
if (not HelpMetaFunctions [funcName]) then
HelpMetaFunctions [funcName] = function(object, ...)
local x = loadstring ( "return _G."..object.button:GetName()..":"..funcName.."(...)")
return x (...)
end
end
end
end
if (buttonWidth and buttonHeight) then
helpButton:SetWidth(buttonWidth)
helpButton:SetHeight(buttonHeight)
helpButton.I:SetWidth(buttonWidth*0.8)
helpButton.I:SetHeight(buttonHeight*0.8)
helpButton.Ring:SetWidth(buttonWidth)
helpButton.Ring:SetHeight(buttonHeight)
helpButton.Ring:SetPoint("center", buttonWidth*.2, -buttonWidth*.2)
end
help.helpTable = {
FramePos = {x = x, y = y},
FrameSize = {width = width, height = height}
}
help.frame = parent
help.button = helpButton
help.widget = helpButton
help.I = helpButton.I
help.Ring = helpButton.Ring
helpButton:SetScript("OnClick", function()
help:ShowHelp()
end)
setmetatable(help, HelpMetaFunctions)
return help
end
@@ -1,487 +0,0 @@
local detailsFramework = DetailsFramework
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local unpack = unpack
local CreateFrame = CreateFrame
local PixelUtil = PixelUtil
detailsFramework.IconMixin = {
---create a new icon frame
---@param self frame the parent frame
---@param iconName string the name of the icon frame
---@return frame
CreateIcon = function(self, iconName)
local iconFrame = CreateFrame("frame", iconName, self, "BackdropTemplate")
iconFrame.Texture = iconFrame:CreateTexture(nil, "artwork")
PixelUtil.SetPoint(iconFrame.Texture, "topleft", iconFrame, "topleft", 1, -1)
PixelUtil.SetPoint(iconFrame.Texture, "bottomright", iconFrame, "bottomright", -1, 1)
iconFrame.Border = iconFrame:CreateTexture(nil, "background")
iconFrame.Border:SetAllPoints()
iconFrame.Border:SetColorTexture(0, 0, 0)
iconFrame:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1})
iconFrame:SetBackdropBorderColor(0, 0, 0, 0)
iconFrame:EnableMouse(false)
local cooldownFrame = CreateFrame("cooldown", "$parentCooldown", iconFrame, "CooldownFrameTemplate, BackdropTemplate")
cooldownFrame:SetAllPoints()
cooldownFrame:EnableMouse(false)
cooldownFrame:SetFrameLevel(iconFrame:GetFrameLevel()+1)
iconFrame.Cooldown = cooldownFrame
iconFrame.CountdownText = cooldownFrame:CreateFontString(nil, "overlay", "GameFontNormal")
iconFrame.CountdownText:SetPoint("center", iconFrame, "center", 0, 0)
iconFrame.CountdownText:Hide()
iconFrame.StackText = iconFrame:CreateFontString(nil, "overlay", "GameFontNormal")
iconFrame.StackText:SetPoint("center", iconFrame, "bottomright", 0, 0)
iconFrame.StackText:Hide()
iconFrame.Desc = iconFrame:CreateFontString(nil, "overlay", "GameFontNormal")
iconFrame.Desc:SetPoint("bottom", iconFrame, "top", 0, 2)
iconFrame.Desc:Hide()
return iconFrame
end,
GetIcon = function(self)
local iconFrame = self.IconPool[self.NextIcon]
if (not iconFrame) then
local newIconFrame = self:CreateIcon("$parentIcon" .. self.NextIcon)
newIconFrame.parentIconRow = self
newIconFrame.Cooldown:SetHideCountdownNumbers(self.options.surpress_blizzard_cd_timer)
newIconFrame.Cooldown.noCooldownCount = self.options.surpress_tulla_omni_cc
newIconFrame.CountdownText:ClearAllPoints()
newIconFrame.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)
newIconFrame.StackText:ClearAllPoints()
newIconFrame.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)
newIconFrame.Desc:ClearAllPoints()
newIconFrame.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)
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 or 1
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
detailsFramework:SetFontColor(iconFrame.CountdownText, self.options.text_color)
self.NextIcon = self.NextIcon + 1
return iconFrame
end,
--adds only if not existing already in the cache
AddSpecificIcon = function(self, identifierKey, spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff)
if (not identifierKey or identifierKey == "") then
return
end
if (not self.AuraCache[identifierKey]) then
local icon = self:SetIcon(spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff or false)
icon.identifierKey = identifierKey
self.AuraCache[identifierKey] = true
end
end,
SetIcon = function(self, spellId, borderColor, startTime, duration, forceTexture, descText, count, debuffType, caster, canStealOrPurge, spellName, isBuff, modRate)
local actualSpellName, _, spellIcon = GetSpellInfo(spellId)
if forceTexture then
spellIcon = forceTexture
end
spellName = spellName or actualSpellName or "unknown_aura"
modRate = modRate or 1
if (spellIcon) then
local iconFrame = self:GetIcon()
iconFrame.Texture:SetTexture(spellIcon)
iconFrame.Texture:SetTexCoord(unpack(self.options.texcoord))
if (borderColor) then
iconFrame:SetBackdropBorderColor(detailsFramework:ParseColors(borderColor))
else
iconFrame:SetBackdropBorderColor(0, 0, 0 ,0)
end
if (startTime) then
CooldownFrame_Set(iconFrame.Cooldown, startTime, duration, true, true, modRate)
if (self.options.show_text) then
iconFrame.CountdownText:Show()
local now = GetTime()
iconFrame.timeRemaining = (startTime + duration - now) / modRate
iconFrame.expirationTime = startTime + duration
local formattedTime = (iconFrame.timeRemaining > 0) and self.options.decimal_timer and iconFrame.parentIconRow.FormatCooldownTimeDecimal(iconFrame.timeRemaining) or iconFrame.parentIconRow.FormatCooldownTime(iconFrame.timeRemaining) or ""
iconFrame.CountdownText:SetText(formattedTime)
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)
detailsFramework:SetFontSize(iconFrame.CountdownText, self.options.text_size)
detailsFramework:SetFontFace (iconFrame.CountdownText, self.options.text_font)
detailsFramework:SetFontOutline (iconFrame.CountdownText, self.options.text_outline)
if self.options.on_tick_cooldown_update then
iconFrame.lastUpdateCooldown = now
iconFrame:SetScript("OnUpdate", self.OnIconTick)
else
iconFrame:SetScript("OnUpdate", nil)
end
else
iconFrame:SetScript("OnUpdate", nil)
iconFrame.CountdownText:Hide()
end
iconFrame.Cooldown:SetReverse(self.options.cooldown_reverse)
iconFrame.Cooldown:SetDrawSwipe(self.options.cooldown_swipe_enabled)
iconFrame.Cooldown:SetEdgeTexture(self.options.cooldown_edge_texture)
iconFrame.Cooldown:SetHideCountdownNumbers(self.options.surpress_blizzard_cd_timer)
else
iconFrame.timeRemaining = nil
iconFrame.expirationTime = nil
iconFrame:SetScript("OnUpdate", nil)
iconFrame.CountdownText:Hide()
end
if (descText and self.options.desc_text) then
iconFrame.Desc:Show()
iconFrame.Desc:SetText(descText.text)
iconFrame.Desc:SetTextColor(detailsFramework: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)
detailsFramework:SetFontSize(iconFrame.Desc, descText.text_size or self.options.desc_text_size)
detailsFramework:SetFontFace(iconFrame.Desc, self.options.desc_text_font)
detailsFramework: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(detailsFramework:ParseColors(self.options.stack_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)
detailsFramework:SetFontSize(iconFrame.StackText, self.options.stack_text_size)
detailsFramework:SetFontFace(iconFrame.StackText, self.options.stack_text_font)
detailsFramework: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
iconFrame.isBuff = isBuff
iconFrame.spellName = spellName
iconFrame.identifierKey = nil -- only used for "specific" add/remove
--add the spell into the cache
self.AuraCache[spellId or -1] = true
self.AuraCache[spellName] = true
self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or canStealOrPurge
self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or debuffType == "" --yes, enrages are empty-string...
--show the frame
self:Show()
return iconFrame
end
end,
OnIconTick = function(self, deltaTime)
local now = GetTime()
if (self.lastUpdateCooldown + 0.05) <= now then
self.timeRemaining = self.expirationTime - now
if self.timeRemaining > 0 then
if self.parentIconRow.options.decimal_timer then
self.CountdownText:SetText(self.parentIconRow.FormatCooldownTimeDecimal(self.timeRemaining))
else
self.CountdownText:SetText(self.parentIconRow.FormatCooldownTime(self.timeRemaining))
end
else
self.CountdownText:SetText("")
end
self.lastUpdateCooldown = now
end
end,
FormatCooldownTime = function(formattedTime)
if (formattedTime >= 3600) then
formattedTime = math.floor(formattedTime / 3600) .. "h"
elseif (formattedTime >= 60) then
formattedTime = math.floor(formattedTime / 60) .. "m"
else
formattedTime = math.floor(formattedTime)
end
return formattedTime
end,
FormatCooldownTimeDecimal = function(formattedTime)
if formattedTime < 10 then
return ("%.1f"):format(formattedTime)
elseif formattedTime < 60 then
return ("%d"):format(formattedTime)
elseif formattedTime < 3600 then
return ("%d:%02d"):format(formattedTime/60%60, formattedTime%60)
elseif formattedTime < 86400 then
return ("%dh %02dm"):format(formattedTime/(3600), formattedTime/60%60)
else
return ("%dd %02dh"):format(formattedTime/86400, (formattedTime/3600) - (math.floor(formattedTime/86400) * 24))
end
end,
RemoveSpecificIcon = function(self, identifierKey)
if (not identifierKey or identifierKey == "") then
return
end
table.wipe(self.AuraCache)
local iconPool = self.IconPool
local countStillShown = 0
for i = 1, self.NextIcon -1 do
local iconFrame = iconPool[i]
if (iconFrame.identifierKey and iconFrame.identifierKey == identifierKey) then
iconFrame:Hide()
iconFrame:ClearAllPoints()
iconFrame.identifierKey = nil
else
self.AuraCache[iconFrame.spellId] = true
self.AuraCache[iconFrame.spellName] = true
self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or iconFrame.canStealOrPurge
self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or iconFrame.debuffType == "" --yes, enrages are empty-string...
countStillShown = countStillShown + 1
end
end
self:AlignAuraIcons()
end,
ClearIcons = function(self, resetBuffs, resetDebuffs)
resetBuffs = resetBuffs ~= false
resetDebuffs = resetDebuffs ~= false
table.wipe(self.AuraCache)
local iconPool = self.IconPool
for i = 1, self.NextIcon -1 do
local iconFrame = iconPool[i]
if (iconFrame.isBuff == nil) then
iconFrame:Hide()
iconFrame:ClearAllPoints()
elseif (resetBuffs and iconFrame.isBuff) then
iconFrame:Hide()
iconFrame:ClearAllPoints()
elseif (resetDebuffs and not iconFrame.isBuff) then
iconFrame:Hide()
iconFrame:ClearAllPoints()
else
self.AuraCache[iconFrame.spellId] = true
self.AuraCache[iconFrame.spellName] = true
self.AuraCache.canStealOrPurge = self.AuraCache.canStealOrPurge or iconFrame.canStealOrPurge
self.AuraCache.hasEnrage = self.AuraCache.hasEnrage or iconFrame.debuffType == "" --yes, enrages are empty-string...
end
end
self:AlignAuraIcons()
end,
AlignAuraIcons = function(self)
local iconPool = self.IconPool
local iconAmount = #iconPool
local countStillShown = 0
table.sort(iconPool, function(i1, i2) return i1:IsShown() and not i2:IsShown() end)
if iconAmount == 0 then
self:Hide()
else
--re-anchor not hidden
for i = 1, iconAmount do
local iconFrame = iconPool[i]
local anchor = self.options.anchor
local anchorTo = i == 1 and self or self.IconPool[i - 1]
local xPadding = i == 1 and self.options.left_padding or self.options.icon_padding or 1
local growDirection = self.options.grow_direction
countStillShown = countStillShown + (iconFrame:IsShown() and 1 or 0)
iconFrame:ClearAllPoints()
if (growDirection == 1) then --grow to right
if (i == 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 (i == 1) then
PixelUtil.SetPoint(iconFrame, "right", anchorTo, "right", xPadding, 0)
else
PixelUtil.SetPoint(iconFrame, "right", anchorTo, "left", xPadding, 0)
end
end
end
end
self.NextIcon = countStillShown + 1
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,
on_tick_cooldown_update = true,
decimal_timer = false,
cooldown_reverse = false,
cooldown_swipe_enabled = true,
cooldown_edge_texture = "Interface\\Cooldown\\edge",
}
function detailsFramework:CreateIconRow(parent, name, options)
local newIconRowFrame = CreateFrame("frame", name, parent, "BackdropTemplate")
newIconRowFrame.IconPool = {}
newIconRowFrame.NextIcon = 1
newIconRowFrame.AuraCache = {}
detailsFramework:Mixin(newIconRowFrame, detailsFramework.IconMixin)
detailsFramework:Mixin(newIconRowFrame, detailsFramework.OptionsFunctions)
newIconRowFrame:BuildOptionsTable(default_icon_row_options, options)
newIconRowFrame:SetSize(newIconRowFrame.options.icon_width, newIconRowFrame.options.icon_height + (newIconRowFrame.options.top_padding * 2))
newIconRowFrame:SetBackdrop(newIconRowFrame.options.backdrop)
newIconRowFrame:SetBackdropColor(unpack(newIconRowFrame.options.backdrop_color))
newIconRowFrame:SetBackdropBorderColor(unpack(newIconRowFrame.options.backdrop_border_color))
return newIconRowFrame
end
@@ -1,27 +0,0 @@
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
--namespace
detailsFramework.Items = {}
local containerAPIVersion = 1
if (detailsFramework.IsDragonflightAndBeyond()) then
containerAPIVersion = 2
end
function detailsFramework.Items.GetContainerItemInfo(containerIndex, slotIndex)
if (containerAPIVersion == 2 and C_Container and C_Container.GetContainerItemInfo) then
local itemInfo = C_Container.GetContainerItemInfo(containerIndex, slotIndex)
return itemInfo.iconFileID, itemInfo.stackCount, itemInfo.isLocked, itemInfo.quality, itemInfo.isReadable, itemInfo.hasLoot, itemInfo.hyperlink, itemInfo.isFiltered, itemInfo.hasNoValue, itemInfo.itemID, itemInfo.isBound
else
return GetContainerItemInfo(containerIndex, slotIndex)
end
end
function detailsFramework.Items.IsItemSoulbound(containerIndex, slotIndex)
local bIsBound = select(11, detailsFramework.Items.GetContainerItemInfo(containerIndex, slotIndex))
return bIsBound
end
@@ -1,382 +0,0 @@
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local _
local loadedAPILabelFunctions = false
do
local metaPrototype = {
WidgetType = "label",
dversion = detailsFramework.dversion,
}
--check if there's a metaPrototype already existing
if (_G[detailsFramework.GlobalWidgetControlNames["label"]]) then
--get the already existing metaPrototype
local oldMetaPrototype = _G[detailsFramework.GlobalWidgetControlNames ["label"]]
--check if is older
if ( (not oldMetaPrototype.dversion) or (oldMetaPrototype.dversion < detailsFramework.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[detailsFramework.GlobalWidgetControlNames ["label"]] = metaPrototype
end
end
local LabelMetaFunctions = _G[detailsFramework.GlobalWidgetControlNames ["label"]]
detailsFramework:Mixin(LabelMetaFunctions, detailsFramework.SetPointMixin)
detailsFramework:Mixin(LabelMetaFunctions, detailsFramework.ScriptHookMixin)
------------------------------------------------------------------------------------------------------------
--metatables
LabelMetaFunctions.__call = function(object, value)
return object.label:SetText(value)
end
------------------------------------------------------------------------------------------------------------
--members
--get text
local gmember_text = function(object)
return object.label:GetText()
end
--text width
local gmember_width = function(object)
return object.label:GetStringWidth()
end
--text height
local gmember_height = function(object)
return object.label:GetStringHeight()
end
--text color
local gmember_textcolor = function(object)
return object.label:GetTextColor()
end
--text font
local gmember_textfont = function(object)
local fontface = object.label:GetFont()
return fontface
end
--text size
local gmember_textsize = function(object)
local _, fontsize = object.label:GetFont()
return fontsize
end
LabelMetaFunctions.GetMembers = LabelMetaFunctions.GetMembers or {}
detailsFramework:Mixin(LabelMetaFunctions.GetMembers, detailsFramework.LayeredRegionMetaFunctionsGet)
detailsFramework:Mixin(LabelMetaFunctions.GetMembers, detailsFramework.DefaultMetaFunctionsGet)
LabelMetaFunctions.GetMembers["width"] = gmember_width
LabelMetaFunctions.GetMembers["height"] = gmember_height
LabelMetaFunctions.GetMembers["text"] = gmember_text
LabelMetaFunctions.GetMembers["fontcolor"] = gmember_textcolor
LabelMetaFunctions.GetMembers["fontface"] = gmember_textfont
LabelMetaFunctions.GetMembers["fontsize"] = gmember_textsize
LabelMetaFunctions.GetMembers["textcolor"] = gmember_textcolor --alias
LabelMetaFunctions.GetMembers["textfont"] = gmember_textfont --alias
LabelMetaFunctions.GetMembers["textsize"] = gmember_textsize --alias
LabelMetaFunctions.__index = function(object, key)
local func = LabelMetaFunctions.GetMembers[key]
if (func) then
return func(object, key)
end
local alreadyHaveKey = rawget(object, key)
if (alreadyHaveKey) then
return alreadyHaveKey
end
return LabelMetaFunctions[key]
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--text
local smember_text = function(object, value)
return object.label:SetText(value)
end
--text color
local smember_textcolor = function(object, value)
local value1, value2, value3, value4 = detailsFramework:ParseColors(value)
return object.label:SetTextColor(value1, value2, value3, value4)
end
--text font
local smember_textfont = function(object, value)
return detailsFramework:SetFontFace(object.label, value)
end
--text size
local smember_textsize = function(object, value)
return detailsFramework:SetFontSize(object.label, value)
end
--text align
local smember_textalign = function(object, value)
if (value == "<") then
value = "left"
elseif (value == ">") then
value = "right"
elseif (value == "|") then
value = "center"
end
return object.label:SetJustifyH(value)
end
--text valign
local smember_textvalign = function(object, value)
if (value == "^") then
value = "top"
elseif (value == "_") then
value = "bottom"
elseif (value == "|") then
value = "middle"
end
return object.label:SetJustifyV(value)
end
--field size width
local smember_width = function(object, value)
return object.label:SetWidth(value)
end
--field size height
local smember_height = function(object, value)
return object.label:SetHeight(value)
end
--outline (shadow)
local smember_outline = function(object, value)
detailsFramework:SetFontOutline(object.label, value)
end
--text rotation
local smember_rotation = function(object, rotation)
if (type(rotation) == "number") then
if (not object.__rotationAnimation) then
object.__rotationAnimation = detailsFramework:CreateAnimationHub(object.label)
object.__rotationAnimation.rotator = detailsFramework:CreateAnimation(object.__rotationAnimation, "rotation", 1, 0, 0)
object.__rotationAnimation.rotator:SetEndDelay(10^8)
object.__rotationAnimation.rotator:SetSmoothProgress(1)
end
object.__rotationAnimation.rotator:SetDegrees(rotation)
object.__rotationAnimation:Play()
object.__rotationAnimation:Pause()
end
end
LabelMetaFunctions.SetMembers = LabelMetaFunctions.SetMembers or {}
detailsFramework:Mixin(LabelMetaFunctions.SetMembers, detailsFramework.LayeredRegionMetaFunctionsSet)
detailsFramework:Mixin(LabelMetaFunctions.SetMembers, detailsFramework.DefaultMetaFunctionsSet)
LabelMetaFunctions.SetMembers["align"] = smember_textalign
LabelMetaFunctions.SetMembers["valign"] = smember_textvalign
LabelMetaFunctions.SetMembers["text"] = smember_text
LabelMetaFunctions.SetMembers["width"] = smember_width
LabelMetaFunctions.SetMembers["height"] = smember_height
LabelMetaFunctions.SetMembers["fontcolor"] = smember_textcolor
LabelMetaFunctions.SetMembers["color"] = smember_textcolor--alias
LabelMetaFunctions.SetMembers["fontface"] = smember_textfont
LabelMetaFunctions.SetMembers["fontsize"] = smember_textsize
LabelMetaFunctions.SetMembers["textcolor"] = smember_textcolor--alias
LabelMetaFunctions.SetMembers["textfont"] = smember_textfont--alias
LabelMetaFunctions.SetMembers["textsize"] = smember_textsize--alias
LabelMetaFunctions.SetMembers["shadow"] = smember_outline
LabelMetaFunctions.SetMembers["outline"] = smember_outline--alias
LabelMetaFunctions.SetMembers["rotation"] = smember_rotation
LabelMetaFunctions.__newindex = function(object, key, value)
local func = LabelMetaFunctions.SetMembers[key]
if (func) then
return func(object, value)
else
return rawset(object, key, value)
end
end
------------------------------------------------------------------------------------------------------------
--methods
---set the text of the label and truncate it is its width passes 'maxWidth' threshold
---@param self df_label
---@param text string
---@param maxWidth width
function LabelMetaFunctions:SetTextTruncated(text, maxWidth)
self.widget:SetText(text)
detailsFramework:TruncateText(self.widget, maxWidth)
end
---set the text color
---@param self df_label
---@param red any
---@param green number|nil
---@param blue number|nil
---@param alpha number|nil
function LabelMetaFunctions:SetTextColor(red, green, blue, alpha)
red, green, blue, alpha = detailsFramework:ParseColors(red, green, blue, alpha)
return self.label:SetTextColor(red, green, blue, alpha)
end
------------------------------------------------------------------------------------------------------------
--template
function LabelMetaFunctions:SetTemplate(template)
if (template.size) then
detailsFramework:SetFontSize(self.label, template.size)
end
if (template.color) then
local r, g, b, a = detailsFramework:ParseColors(template.color)
self:SetTextColor(r, g, b, a)
end
if (template.font) then
local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0")
local font = SharedMedia:Fetch("font", template.font)
detailsFramework:SetFontFace(self.label, font)
end
end
------------------------------------------------------------------------------------------------------------
--object constructor
---@class df_label
---@field widget fontstring widget and label points to the same fontstring
---@field label fontstring widget and label points to the same fontstring
---@field align justifyh
---@field valign justifyv
---@field text string
---@field width width
---@field height height
---@field fontcolor any
---@field color any
---@field fontface string
---@field fontsize number
---@field textcolor any
---@field textfont string
---@field textsize number
---@field shadow fontflags
---@field outline fontflags
---@field rotation number
---@field SetTemplate fun(self: df_label, template: table) set the fontstring visual by a template
---@field SetTextColor fun(self: df_label, red: any, green: number|nil, blue: number|nil, alpha: number|nil) set the button text color
---@field SetTextTruncated fun(self: df_label, text: string, maxWidth: width)
---create a new label object
---@param parent frame
---@param text string
---@param size number|nil
---@param color any|nil
---@param font string|nil
---@param member string|nil
---@param name string|nil
---@param layer drawlayer|nil
---@return df_label|nil
function detailsFramework:CreateLabel(parent, text, size, color, font, member, name, layer)
return detailsFramework:NewLabel(parent, nil, name, member, text, font, size, color, layer)
end
function detailsFramework:NewLabel(parent, container, name, member, text, font, size, color, layer)
if (not parent) then
return error("Details! Framework: parent not found.", 2)
end
if (not container) then
container = parent
end
if (not name) then
name = "DetailsFrameworkLabelNumber" .. detailsFramework.LabelNameCounter
detailsFramework.LabelNameCounter = detailsFramework.LabelNameCounter + 1
end
if (name:find("$parent")) then
local parentName = detailsFramework.GetParentName(parent)
name = name:gsub("$parent", parentName)
end
---@type df_label
local labelObject = {type = "label", dframework = true}
if (member) then
parent[member] = labelObject
end
if (parent.dframework) then
parent = parent.widget
end
if (container.dframework) then
container = container.widget
end
if (not font or font == "") then
font = "GameFontNormal"
end
labelObject.label = parent:CreateFontString(name, layer or "OVERLAY", font)
labelObject.widget = labelObject.label
labelObject.label.MyObject = labelObject
if (not loadedAPILabelFunctions) then
loadedAPILabelFunctions = true
local idx = getmetatable(labelObject.label).__index
for funcName, funcAddress in pairs(idx) do
if (not LabelMetaFunctions[funcName]) then
LabelMetaFunctions[funcName] = function(object, ...)
local x = loadstring( "return _G['"..object.label:GetName().."']:"..funcName.."(...)")
return x(...)
end
end
end
end
--if the text is a table, it means a language table has been passed
if (type(text) == "table") then
local locTable = text
if (detailsFramework.Language.IsLocTable(locTable)) then
detailsFramework.Language.SetTextWithLocTable(labelObject.widget, locTable)
else
labelObject.label:SetText(text)
end
else
labelObject.label:SetText(text)
end
labelObject.label:SetJustifyH("left")
if (color) then
local r, g, b, a = detailsFramework:ParseColors(color)
labelObject.label:SetTextColor(r, g, b, a)
end
if (size and type(size) == "number") then
detailsFramework:SetFontSize(labelObject.label, size)
end
labelObject.HookList = {}
setmetatable(labelObject, LabelMetaFunctions)
--if template has been passed as the third parameter
if (size and type(size) == "table") then
labelObject:SetTemplate(size)
end
return labelObject
end
File diff suppressed because it is too large Load Diff
@@ -1,41 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
<Script file ="DFPixelUtil.lua"/>
<Script file="fw.lua"/>
<Script file="mixins.lua"/>
<Script file="util.lua"/>
<Script file="header.lua"/>
<Script file="containers.lua"/>
<Script file="iteminfo.lua"/>
<Script file="addon.lua"/>
<Script file="colors.lua"/>
<Script file="help.lua"/>
<Script file="schedules.lua"/>
<Script file="label.lua"/>
<Script file="picture.lua"/>
<Script file="slider.lua"/>
<Script file="scrollbar.lua"/>
<Script file="spells.lua"/>
<Script file="math.lua"/>
<Script file="savedvars.lua"/>
<Script file="languages.lua"/>
<Script file="timebar.lua"/>
<Script file="charts.lua"/>
<Script file="scripting.lua"/>
<Script file="externals.lua"/>
<Script file="frames.lua"/>
<Include file="tutorial_alert.xml"/>
<Include file="split_bar.xml"/>
<Include file="textentry.xml"/>
<Include file="button.xml"/>
<Include file="cooltip.xml"/>
<Include file="dropdown.xml"/>
<Include file="normal_bar.xml"/>
<Include file="panel.xml"/>
<Script file="icon.lua"/>
<Script file="pictureedit.lua"/>
<Script file="auras.lua"/>
<Script file="tabcontainer.lua"/>
</Ui>
@@ -1,176 +0,0 @@
local DF = _G["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
local UnitExists = UnitExists
local atan2 = math.atan2
local pi = math.pi
local abs = math.abs
SMALL_FLOAT = 0.000001
--find distance between two players
function DF:GetDistance_Unit(unit1, unit2)
if (UnitExists(unit1) and UnitExists(unit2)) then
local u1X, u1Y = UnitPosition(unit1)
local u2X, u2Y = UnitPosition(unit2)
local dX = u2X - u1X
local dY = u2Y - u1Y
return ((dX*dX) + (dY*dY)) ^ .5
end
return 0
end
--find distance between two points
function DF:GetDistance_Point(x1, y1, x2, y2)
local dx = x2 - x1
local dy = y2 - y1
return ((dx * dx) + (dy * dy)) ^ .5
end
--find a rotation for an object from a point to another point
function DF:FindLookAtRotation(x1, y1, x2, y2)
return atan2 (y2 - y1, x2 - x1) + pi
end
--find the value scale between two given values. e.g: value of 500 in a range 0-100 result in 10 in a scale for 0-10
function DF:MapRangeClamped(inputX, inputY, outputX, outputY, value)
return DF:GetRangeValue(outputX, outputY, Clamp(DF:GetRangePercent(inputX, inputY, value), 0, 1))
end
--find the value scale between two given values. e.g: value of 75 in a range 0-100 result in 7.5 in a scale for 0-10
function DF:MapRangeUnclamped(inputX, inputY, outputX, outputY, value)
return DF:GetRangeValue(outputX, outputY, DF:GetRangePercent(inputX, inputY, value))
end
--find the normalized percent of the value in the range. e.g range of 200-400 and a value of 250 result in 0.25
function DF:GetRangePercent(minValue, maxValue, value)
return (value - minValue) / max((maxValue - minValue), SMALL_FLOAT)
end
--find the value in the range given from a normalized percent. e.g range of 200-400 and a percent of 0.8 result in 360
function DF:GetRangeValue(minValue, maxValue, percent)
return Lerp(minValue, maxValue, percent)
end
function DF:GetColorRangeValue(r1, g1, b1, r2, g2, b2, value)
local newR = DF:LerpNorm(r1, r2, value)
local newG = DF:LerpNorm(g1, g2, value)
local newB = DF:LerpNorm(b1, b2, value)
return newR, newG, newB
end
--dot product of two 2D Vectors
function DF:GetDotProduct(value1, value2)
return (value1.x * value2.x) + (value1.y * value2.y)
end
function DF:GetBezierPoint(value, point1, point2, point3)
local bP1 = Lerp(point1, point2, value)
local bP2 = Lerp(point2, point3, value)
return Lerp(bP1, bP2, value)
end
--normalized value 0-1 result in the value on the range given, e.g 200-400 range with a value of .5 result in 300
function DF:LerpNorm(minValue, maxValue, value)
return (minValue + value * (maxValue - minValue))
end
--change the color by the deltaTime
function DF:LerpLinearColor(deltaTime, interpSpeed, r1, g1, b1, r2, g2, b2)
deltaTime = deltaTime * interpSpeed
local r = r1 + (r2 - r1) * deltaTime
local g = g1 + (g2 - g1) * deltaTime
local b = b1 + (b2 - b1) * deltaTime
return r, g, b
end
--check if a number is near another number by a tolerance
function DF:IsNearlyEqual(value1, value2, tolerance)
tolerance = tolerance or SMALL_FLOAT
return abs(value1 - value2) <= tolerance
end
--check if a number is near zero
function DF:IsNearlyZero(value, tolerance)
tolerance = tolerance or SMALL_FLOAT
return abs(value) <= tolerance
end
--check if a number is within a two other numbers, if isInclusive is true, it'll include the max value
function DF:IsWithin(minValue, maxValue, value, isInclusive)
if (isInclusive) then
return ((value >= minValue) and (value <= maxValue))
else
return ((value >= minValue) and (value < maxValue))
end
end
--dont allow a number ot be lower or bigger than a certain range
function DF:Clamp(minValue, maxValue, value)
return value < minValue and minValue or value < maxValue and value or maxValue
end
--from http://lua-users.org/wiki/SimpleRound cut fractions on a float
function DF:Round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end
local BoundingBox = {}
BoundingBox.CoordinatesData = {
["topleft"] = {["x"] = 'number', ["y"] = 'number'},
["topright"] = {["x"] = 'number', ["y"] = 'number'},
["bottomleft"] = {["x"] = 'number', ["y"] = 'number'},
["bottomright"] = {["x"] = 'number', ["y"] = 'number'},
["center"] = {["x"] = 'number', ["y"] = 'number'},
["width"] = 'number',
["height"] = 'number',
}
---@class objectcoordinates
---@field topleft {["x"]: number, ["y"]: number}
---@field topright {["x"]: number, ["y"]: number}
---@field bottomleft {["x"]: number, ["y"]: number}
---@field bottomright {["x"]: number, ["y"]: number}
---@field center {["x"]: number, ["y"]: number}
---@field width number
---@field height number
---@field left number
---@field right number
---@field top number
---@field bottom number
---return the coordinates of the four corners of an object
---@param object uiobject
---@return objectcoordinates
function DF:GetObjectCoordinates(object)
local centerX, centerY = object:GetCenter()
local width = object:GetWidth()
local height = object:GetHeight()
local halfWidth = width / 2
local halfHeight = height / 2
return {
["width"] = width,
["height"] = height,
["left"] = centerX - halfWidth,
["right"] = centerX + halfWidth,
["top"] = centerY + halfHeight,
["bottom"] = centerY - halfHeight,
["center"] = {x = centerX, y = centerY},
["topleft"] = {x = centerX - halfWidth, y = centerY + halfHeight},
["topright"] = {x = centerX + halfWidth, y = centerY + halfHeight},
["bottomleft"] = {x = centerX - halfWidth, y = centerY - halfHeight},
["bottomright"] = {x = centerX + halfWidth, y = centerY - halfHeight},
}
end
function DF:ScaleBack()
end
@@ -1,977 +0,0 @@
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local _
local getFrame = function(frame)
return rawget(frame, "widget") or frame
end
detailsFramework.WidgetFunctions = {
GetCapsule = function(self)
return self.MyObject
end,
GetObject = function(self)
return self.MyObject
end,
}
detailsFramework.DefaultMetaFunctionsGet = {
parent = function(object)
return object:GetParent()
end,
shown = function(object)
return object:IsShown()
end,
}
detailsFramework.TooltipHandlerMixin = {
SetTooltip = function(self, tooltip)
if (tooltip) then
if (detailsFramework.Language.IsLocTable(tooltip)) then
--register the locTable as a tableKey
local locTable = tooltip
detailsFramework.Language.RegisterTableKeyWithLocTable(self, "have_tooltip", locTable)
else
self.have_tooltip = tooltip
end
else
self.have_tooltip = nil
end
end,
GetTooltip = function(self)
return self.have_tooltip
end,
ShowTooltip = function(self)
local tooltipText = self:GetTooltip()
if (type(tooltipText) == "function") then
local tooltipFunction = tooltipText
local gotTooltip, tooltipString = xpcall(tooltipFunction, geterrorhandler())
if (gotTooltip) then
tooltipText = tooltipString
end
end
if (tooltipText) then
GameCooltip:Preset(2)
GameCooltip:AddLine(tooltipText)
GameCooltip:ShowCooltip(getFrame(self), "tooltip")
end
end,
HideTooltip = function(self)
local tooltipText = self:GetTooltip()
if (tooltipText) then
if (GameCooltip:IsOwner(getFrame(self))) then
GameCooltip:Hide()
end
end
end,
}
detailsFramework.DefaultMetaFunctionsSet = {
parent = function(object, value)
return object:SetParent(value)
end,
show = function(object, value)
if (value) then
return object:Show()
else
return object:Hide()
end
end,
hide = function(object, value)
if (value) then
return object:Hide()
else
return object:Show()
end
end,
}
detailsFramework.DefaultMetaFunctionsSet.shown = detailsFramework.DefaultMetaFunctionsSet.show
detailsFramework.LayeredRegionMetaFunctionsSet = {
drawlayer = function(object, value)
object.image:SetDrawLayer(value)
end,
sublevel = function(object, value)
local drawLayer = object:GetDrawLayer()
object:SetDrawLayer(drawLayer, value)
end,
}
detailsFramework.LayeredRegionMetaFunctionsGet = {
drawlayer = function(object)
return object.image:GetDrawLayer()
end,
sublevel = function(object)
local _, subLevel = object.image:GetDrawLayer()
return subLevel
end,
}
detailsFramework.FrameMixin = {
SetFrameStrata = function(self, strata)
self = getFrame(self)
if (type(strata) == "table" and strata.GetObjectType) then
local UIObject = strata
self:SetFrameStrata(UIObject:GetFrameStrata())
else
self:SetFrameStrata(strata)
end
end,
SetFrameLevel = function(self, level, UIObject)
self = getFrame(self)
if (not UIObject) then
self:SetFrameLevel(level)
else
local framelevel = UIObject:GetFrameLevel(UIObject) + level
self:SetFrameLevel(framelevel)
end
end,
SetSize = function(self, width, height)
self = getFrame(self)
if (width) then
self:SetWidth(width)
end
if (height) then
self:SetHeight(height)
end
end,
SetBackdrop = function(self, ...)
self = getFrame(self)
self:SetBackdrop(...)
end,
SetBackdropColor = function(self, ...)
self = getFrame(self)
self:SetBackdropColor(...)
end,
SetBackdropBorderColor = function(self, ...)
self = getFrame(self)
self:SetBackdropBorderColor(...)
end,
}
local doublePoint = {
["lefts"] = true,
["rights"] = true,
["tops"] = true,
["bottoms"] = true,
["left-left"] = true,
["right-right"] = true,
["top-top"] = true,
["bottom-bottom"] = true,
["bottom-top"] = true,
["top-bottom"] = true,
["right-left"] = true,
["left-right"] = true,
}
detailsFramework.SetPointMixin = {
SetPoint = function(object, anchorName1, anchorObject, anchorName2, xOffset, yOffset)
if (doublePoint[anchorName1]) then
object:ClearAllPoints()
local anchorTo
if (anchorObject and type(anchorObject) == "table") then
xOffset, yOffset = anchorName2 or 0, xOffset or 0
anchorTo = getFrame(anchorObject)
else
xOffset, yOffset = anchorObject or 0, anchorName2 or 0
anchorTo = object:GetParent()
end
--offset always inset to inner
if (anchorName1 == "lefts") then
object:SetPoint("topleft", anchorTo, "topleft", xOffset, -yOffset)
object:SetPoint("bottomleft", anchorTo, "bottomleft", xOffset, yOffset)
elseif (anchorName1 == "rights") then
object:SetPoint("topright", anchorTo, "topright", xOffset, -yOffset)
object:SetPoint("bottomright", anchorTo, "bottomright", xOffset, yOffset)
elseif (anchorName1 == "tops") then
object:SetPoint("topleft", anchorTo, "topleft", xOffset, -yOffset)
object:SetPoint("topright", anchorTo, "topright", -xOffset, -yOffset)
elseif (anchorName1 == "bottoms") then
object:SetPoint("bottomleft", anchorTo, "bottomleft", xOffset, yOffset)
object:SetPoint("bottomright", anchorTo, "bottomright", -xOffset, yOffset)
elseif (anchorName1 == "left-left") then
object:SetPoint("left", anchorTo, "left", xOffset, yOffset)
elseif (anchorName1 == "right-right") then
object:SetPoint("right", anchorTo, "right", xOffset, yOffset)
elseif (anchorName1 == "top-top") then
object:SetPoint("top", anchorTo, "top", xOffset, yOffset)
elseif (anchorName1 == "bottom-bottom") then
object:SetPoint("bottom", anchorTo, "bottom", xOffset, yOffset)
elseif (anchorName1 == "bottom-top") then
object:SetPoint("bottomleft", anchorTo, "topleft", xOffset, yOffset)
object:SetPoint("bottomright", anchorTo, "topright", -xOffset, yOffset)
elseif (anchorName1 == "top-bottom") then
object:SetPoint("topleft", anchorTo, "bottomleft", xOffset, -yOffset)
object:SetPoint("topright", anchorTo, "bottomright", -xOffset, -yOffset)
elseif (anchorName1 == "right-left") then
object:SetPoint("topright", anchorTo, "topleft", xOffset, -yOffset)
object:SetPoint("bottomright", anchorTo, "bottomleft", xOffset, yOffset)
elseif (anchorName1 == "left-right") then
object:SetPoint("topleft", anchorTo, "topright", xOffset, -yOffset)
object:SetPoint("bottomleft", anchorTo, "bottomright", xOffset, yOffset)
end
return
end
xOffset = xOffset or 0
yOffset = yOffset or 0
anchorName1, anchorObject, anchorName2, xOffset, yOffset = detailsFramework:CheckPoints(anchorName1, anchorObject, anchorName2, xOffset, yOffset, object)
if (not anchorName1) then
error("SetPoint: Invalid parameter.")
return
end
if (not object.widget) then
local SetPoint = getmetatable(object).__index.SetPoint
return SetPoint(object, anchorName1, anchorObject, anchorName2, xOffset, yOffset)
else
return object.widget:SetPoint(anchorName1, anchorObject, anchorName2, xOffset, yOffset)
end
end,
}
---mixin for options
---@class df_optionsmixin
---@field options table
---@field SetOption fun(self, optionName: string, optionValue: any)
---@field GetOption fun(self, optionName: string):any
---@field GetAllOptions fun(self):table
---@field BuildOptionsTable fun(self, defaultOptions: table, userOptions: table)
detailsFramework.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
detailsFramework: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 {}
detailsFramework.table.deploy(self.options, userOptions or {})
detailsFramework.table.deploy(self.options, defaultOptions or {})
end
}
--payload mixin
detailsFramework.PayloadMixin = {
ClearPayload = function(self)
self.payload = {}
end,
SetPayload = function(self, ...)
self.payload = {...}
return self.payload
end,
AddPayload = function(self, ...)
local currentPayload = self.payload or {}
self.payload = currentPayload
for i = 1, select("#", ...) do
local value = select(i, ...)
currentPayload[#currentPayload+1] = value
end
return self.payload
end,
GetPayload = function(self)
return self.payload
end,
DumpPayload = function(self)
return unpack(self.payload)
end,
--does not copy wow objects, just pass them to the new table, tables strings and numbers are copied entirely
DuplicatePayload = function(self)
local duplicatedPayload = detailsFramework.table.duplicate({}, self.payload)
return duplicatedPayload
end,
}
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.ScriptHookMixin)
---
---@class DetailsFramework.ScriptHookMixin
detailsFramework.ScriptHookMixin = {
RunHooksForWidget = function(self, event, ...)
local hooks = self.HookList[event]
if (not hooks) then
print(self.widget:GetName(), "no hooks for", event)
return
end
for i, func in ipairs(hooks) do
local success, canInterrupt = xpcall(func, geterrorhandler(), ...)
if (not success) then
--error("Details! Framework: " .. event .. " hook for " .. self:GetName() .. ": " .. canInterrupt)
return false
elseif (canInterrupt) then
return true
end
end
end,
SetHook = function(self, hookType, func)
if (self.HookList[hookType]) then
if (type(func) == "function") then
local isRemoval = false
for i = #self.HookList[hookType], 1, -1 do
if (self.HookList[hookType][i] == func) then
table.remove(self.HookList[hookType], i)
isRemoval = true
break
end
end
if (not isRemoval) then
table.insert(self.HookList[hookType], func)
end
else
if (detailsFramework.debug) then
print(debugstack())
error("Details! Framework: invalid function for widget " .. self.WidgetType .. ".")
end
end
else
if (detailsFramework.debug) then
error("Details! Framework: unknown hook type for widget " .. self.WidgetType .. ": '" .. hookType .. "'.")
end
end
end,
HasHook = function(self, hookType, func)
if (self.HookList[hookType]) then
if (type(func) == "function") then
for i = #self.HookList[hookType], 1, -1 do
if (self.HookList[hookType][i] == func) then
return true
end
end
end
end
end,
ClearHooks = function(self)
for hookType, hookTable in pairs(self.HookList) do
table.wipe(hookTable)
end
end,
}
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.SortFunctions)
---add methods to be used on scrollframes
---@class df_scrollboxmixin
detailsFramework.ScrollBoxFunctions = {
---refresh the scrollbox by resetting all lines created with :CreateLine(), then calling the refresh_func which was set at :CreateScrollBox()
---@param self table
---@return table
Refresh = function(self)
--hide all frames and tag as not in use
self._LinesInUse = 0
for index, frame in ipairs(self.Frames) do
if (not self.DontHideChildrenOnPreRefresh) then
frame:Hide()
end
frame._InUse = nil
end
local offset = 0
if (self.IsFauxScroll) then
self:UpdateFaux(#self.data, self.LineAmount, self.LineHeight)
offset = self:GetOffsetFaux()
end
--call the refresh function
detailsFramework:CoreDispatch((self:GetName() or "ScrollBox") .. ":Refresh()", self.refresh_func, self, self.data, offset, self.LineAmount)
--hide all frames that are not in use
for index, frame in ipairs(self.Frames) do
if (not frame._InUse) then
frame:Hide()
else
frame:Show()
end
end
self:Show()
local frameName = self:GetName()
if (frameName) then
if (self.HideScrollBar) then
local scrollBar = _G[frameName .. "ScrollBar"]
if (scrollBar) then
scrollBar:Hide()
end
else
--[=[ --maybe in the future I visit this again
local scrollBar = _G[frameName .. "ScrollBar"]
local height = self:GetHeight()
local totalLinesRequired = #self.data
local linesShown = self._LinesInUse
local percent = linesShown / totalLinesRequired
local thumbHeight = height * percent
scrollBar.ThumbTexture:SetSize(12, thumbHeight)
print("thumbHeight:", thumbHeight)
--]=]
end
end
return self.Frames
end,
OnVerticalScroll = function(self, offset)
self:OnVerticalScrollFaux(offset, self.LineHeight, self.Refresh)
return true
end,
---create a line within the scrollbox
---@param self table is the scrollbox
---@param func function|nil function to create the line object, this function will receive the line index as argument and return a table with the line object
---@return table line object (table)
CreateLine = function(self, func)
if (not func) then
func = self.CreateLineFunc
end
local okay, newLine = pcall(func, self, #self.Frames+1)
if (okay) then
if (not newLine) then
error("ScrollFrame:CreateLine() function did not returned a line, use: 'return line'")
end
tinsert(self.Frames, newLine)
newLine.Index = #self.Frames
return newLine
else
error("ScrollFrame:CreateLine() error on creating a line: " .. newLine)
end
end,
CreateLines = function(self, callback, lineAmount)
for i = 1, lineAmount do
self:CreateLine(callback)
end
end,
GetLine = function(self, lineIndex)
local line = self.Frames[lineIndex]
if (line) then
line._InUse = true
end
self._LinesInUse = self._LinesInUse + 1
return line
end,
SetData = function(self, data)
self.data = data
end,
GetData = function(self)
return self.data
end,
GetFrames = function(self)
return self.Frames
end,
GetLines = function(self) --alias of GetFrames
return self.Frames
end,
GetNumFramesCreated = function(self)
return #self.Frames
end,
GetNumFramesShown = function(self)
return self.LineAmount
end,
SetNumFramesShown = function(self, newAmount)
--hide frames which won't be used
if (newAmount < #self.Frames) then
for i = newAmount+1, #self.Frames do
self.Frames[i]:Hide()
end
end
--set the new amount
self.LineAmount = newAmount
end,
SetFramesHeight = function(self, height)
self.LineHeight = height
self:OnSizeChanged()
self:Refresh()
end,
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,
--moved functions from blizzard faux scroll that are called from insecure code environment
--this reduces the amount of taints while using the faux scroll frame
GetOffsetFaux = function(self)
return self.offset or 0
end,
OnVerticalScrollFaux = function(self, value, itemHeight, updateFunction)
local scrollbar = self:GetChildFramesFaux();
scrollbar:SetValue(value);
self.offset = math.floor((value / itemHeight) + 0.5);
if (updateFunction) then
updateFunction(self)
end
end,
GetChildFramesFaux = function(frame)
local frameName = frame:GetName();
if frameName then
return _G[ frameName.."ScrollBar" ], _G[ frameName.."ScrollChildFrame" ], _G[ frameName.."ScrollBarScrollUpButton" ], _G[ frameName.."ScrollBarScrollDownButton" ];
else
return frame.ScrollBar, frame.ScrollChildFrame, frame.ScrollBar.ScrollUpButton, frame.ScrollBar.ScrollDownButton;
end
end,
UpdateFaux = function(frame, numItems, numToDisplay, buttonHeight, button, smallWidth, bigWidth, highlightFrame, smallHighlightWidth, bigHighlightWidth, alwaysShowScrollBar)
local scrollBar, scrollChildFrame, scrollUpButton, scrollDownButton = frame:GetChildFramesFaux();
-- If more than one screen full of items then show the scrollbar
local showScrollBar;
if ( numItems > numToDisplay or alwaysShowScrollBar ) then
frame:Show();
showScrollBar = 1;
else
scrollBar:SetValue(0);
frame:Hide();
end
if ( frame:IsShown() ) then
local scrollFrameHeight = 0;
local scrollChildHeight = 0;
if ( numItems > 0 ) then
scrollFrameHeight = (numItems - numToDisplay) * buttonHeight;
scrollChildHeight = numItems * buttonHeight;
if ( scrollFrameHeight < 0 ) then
scrollFrameHeight = 0;
end
scrollChildFrame:Show();
else
scrollChildFrame:Hide();
end
local maxRange = (numItems - numToDisplay) * buttonHeight;
if (maxRange < 0) then
maxRange = 0;
end
scrollBar:SetMinMaxValues(0, maxRange);
scrollBar:SetValueStep(buttonHeight);
scrollBar:SetStepsPerPage(numToDisplay-1);
scrollChildFrame:SetHeight(scrollChildHeight);
-- Arrow button handling
if ( scrollBar:GetValue() == 0 ) then
scrollUpButton:Disable();
else
scrollUpButton:Enable();
end
if ((scrollBar:GetValue() - scrollFrameHeight) == 0) then
scrollDownButton:Disable();
else
scrollDownButton:Enable();
end
-- Shrink because scrollbar is shown
if ( highlightFrame ) then
highlightFrame:SetWidth(smallHighlightWidth);
end
if ( button ) then
for i=1, numToDisplay do
_G[button..i]:SetWidth(smallWidth);
end
end
else
-- Widen because scrollbar is hidden
if ( highlightFrame ) then
highlightFrame:SetWidth(bigHighlightWidth);
end
if ( button ) then
for i=1, numToDisplay do
_G[button..i]:SetWidth(bigWidth);
end
end
end
return showScrollBar;
end,
}
--back compatibility, can be removed in the future (28/04/2023)
---@class DetailsFramework.ScrollBoxFunctions : df_scrollboxmixin
local SortMember = ""
local SortByMember = function(t1, t2)
return t1[SortMember] > t2[SortMember]
end
local SortByMemberReverse = function(t1, t2)
return t1[SortMember] < t2[SortMember]
end
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.SortFunctions)
---adds the method Sort() to a table, this method can be used to sort another table by a member, can't sort itself
---@class DetailsFramework.SortFunctions
detailsFramework.SortFunctions = {
---sort a table by a member
---@param self table
---@param tThisTable table
---@param sMemberName string
---@param bIsReverse boolean
Sort = function(self, tThisTable, sMemberName, bIsReverse)
SortMember = sMemberName
if (not bIsReverse) then
table.sort(tThisTable, SortByMember)
else
table.sort(tThisTable, SortByMemberReverse)
end
end
}
---@class df_data : table
---@field _dataInfo {data: table, dataCurrentIndex: number, callbacks: function[]}
---@field callbacks table<function, any[]>
---@field dataCurrentIndex number
---@field DataConstructor fun(self: df_data)
---@field AddDataChangeCallback fun(self: df_data, callback: function, ...: any)
---@field RemoveDataChangeCallback fun(self: df_data, callback: function)
---@field GetData fun(self: df_data)
---@field GetDataSize fun(self: df_data) : number
---@field GetDataFirstValue fun(self: df_data) : any
---@field GetDataLastValue fun(self: df_data) : any
---@field GetDataMinMaxValues fun(self: df_data) : number, number
---@field GetDataMinMaxValueFromSubTable fun(self: df_data, key: string) : number, number when data uses sub tables, get the min max values from a specific index or key, if the value stored is number, return the min and max values
---@field SetData fun(self: df_data, data: table, anyValue: any)
---@field SetDataRaw fun(self: df_data, data: table) set the data without triggering callback
---@field GetDataNextValue fun(self: df_data) : any
---@field ResetDataIndex fun(self: df_data)
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.DataMixin)
---add 'data' to a table, this table can be used to store data for the object
---@class DetailsFramework.DataMixin
detailsFramework.DataMixin = {
---initialize the data table
---@param self table
DataConstructor = function(self)
self._dataInfo = {
data = {},
dataCurrentIndex = 1,
callbacks = {},
}
end,
---when data is changed, functions registered with this function will be called
---@param self table
---@param func function
---@param ... unknown
AddDataChangeCallback = function(self, func, ...)
assert(type(func) == "function", "invalid function for AddDataChangeCallback.")
local allCallbacks = self._dataInfo.callbacks
allCallbacks[func] = {...}
end,
---remove a previous registered callback function
---@param self table
---@param func function
RemoveDataChangeCallback = function(self, func)
assert(type(func) == "function", "invalid function for RemoveDataChangeCallback.")
local allCallbacks = self._dataInfo.callbacks
allCallbacks[func] = nil
end,
---set the data without callback
---@param self table
---@param data table
SetDataRaw = function(self, data)
assert(type(data) == "table", "invalid table for SetData.")
self._dataInfo.data = data
self:ResetDataIndex()
end,
---set the data table
---@param self table
---@param data table
---@param anyValue any @any value to pass to the callback functions before the payload is added
SetData = function(self, data, anyValue)
assert(type(data) == "table", "invalid table for SetData.")
self._dataInfo.data = data
self:ResetDataIndex()
local allCallbacks = self._dataInfo.callbacks
for func, payload in pairs(allCallbacks) do
xpcall(func, geterrorhandler(), data, anyValue, unpack(payload))
end
end,
---get the data table
---@param self table
GetData = function(self)
return self._dataInfo.data
end,
---get the next value from the data table
---@param self table
---@return any
GetDataNextValue = function(self)
local currentValue = self._dataInfo.dataCurrentIndex
local value = self:GetData()[currentValue]
self._dataInfo.dataCurrentIndex = self._dataInfo.dataCurrentIndex + 1
return value
end,
---reset the data index, making GetDataNextValue() return the first value again
---@param self table
ResetDataIndex = function(self)
self._dataInfo.dataCurrentIndex = 1
end,
---get the size of the data table
---@param self table
---@return number
GetDataSize = function(self)
return #self:GetData()
end,
---get the first value from the data table
---@param self table
---@return any
GetDataFirstValue = function(self)
return self:GetData()[1]
end,
---get the last value from the data table
---@param self table
---@return any
GetDataLastValue = function(self)
local data = self:GetData()
return data[#data]
end,
---get the min and max values from the data table, if the value stored is number, return the min and max values
---could be used together with SetMinMaxValues from the df_value mixin
---@param self table
---@return number, number
GetDataMinMaxValues = function(self)
local minDataValue = 0
local maxDataValue = 0
local data = self:GetData()
for i = 1, #data do
local thisData = data[i]
if (thisData > maxDataValue) then
maxDataValue = thisData
elseif (thisData < minDataValue) then
minDataValue = thisData
end
end
return minDataValue, maxDataValue
end,
---when data uses sub tables, get the min max values from a specific index or key, if the value stored is number, return the min and max values
---@param self table
---@param key string
---@return number, number
GetDataMinMaxValueFromSubTable = function(self, key)
local minDataValue = 0
local maxDataValue = 0
local data = self:GetData()
for i = 1, #data do
local thisData = data[i]
if (thisData[key] > maxDataValue) then
maxDataValue = thisData[key]
elseif (thisData[key] < minDataValue) then
minDataValue = thisData[key]
end
end
return minDataValue, maxDataValue
end,
}
---@class df_value : table
---@field minValue number
---@field maxValue number
---@field ValueConstructor fun(self: df_value)
---@field SetMinMaxValues fun(self: df_value, minValue: number, maxValue: number)
---@field GetMinMaxValues fun(self: df_value) : number, number
---@field ResetMinMaxValues fun(self: df_value)
---@field GetMinValue fun(self: df_value) : number
---@field GetMaxValue fun(self: df_value) : number
---@field SetMinValue fun(self: df_value, minValue: number)
---@field SetMinValueIfLower fun(self: df_value, ...: number)
---@field SetMaxValue fun(self: df_value, maxValue: number)
---@field SetMaxValueIfBigger fun(self: df_value, ...: number)
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.ValueMixin)
---add support to min value and max value into a table or object
---@class DetailsFramework.ValueMixin
detailsFramework.ValueMixin = {
---initialize the value table
---@param self table
ValueConstructor = function(self)
self:ResetMinMaxValues()
end,
---set the min and max values
---@param self table
---@param minValue number
---@param maxValue number
SetMinMaxValues = function(self, minValue, maxValue)
self.minValue = minValue
self.maxValue = maxValue
end,
---get the min and max values
---@param self table
---@return number, number
GetMinMaxValues = function(self)
return self.minValue, self.maxValue
end,
---reset the min and max values
---@param self table
ResetMinMaxValues = function(self)
self.minValue = 0
self.maxValue = 1
end,
---get the min value
---@param self table
---@return number
GetMinValue = function(self)
return self.minValue
end,
---get the max value
---@param self table
---@return number
GetMaxValue = function(self)
return self.maxValue
end,
---set the min value
---@param self table
---@param minValue number
SetMinValue = function(self, minValue)
self.minValue = minValue
end,
---set the min value if one of the values passed is lower than the current min value
---@param self table
---@param ... number
SetMinValueIfLower = function(self, ...)
self.minValue = math.min(self.minValue, ...)
end,
---set the max value
---@param self table
---@param maxValue number
SetMaxValue = function(self, maxValue)
self.maxValue = maxValue
end,
---set the max value if one of the values passed is bigger than the current max value
---@param self table
---@param ... number
SetMaxValueIfBigger = function(self, ...)
self.maxValue = math.max(self.maxValue, ...)
end,
}
@@ -1,861 +0,0 @@
local DF = _G["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
local _
local _unpack = unpack
local type = type
local _math_floor = math.floor
local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0")
local APIBarFunctions
do
local metaPrototype = {
WidgetType = "normal_bar",
dversion = DF.dversion,
}
--check if there's a metaPrototype already existing
if (_G[DF.GlobalWidgetControlNames["normal_bar"]]) then
--get the already existing metaPrototype
local oldMetaPrototype = _G[DF.GlobalWidgetControlNames["normal_bar"]]
--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["normal_bar"]] = metaPrototype
end
end
local BarMetaFunctions = _G[DF.GlobalWidgetControlNames["normal_bar"]]
DF:Mixin(BarMetaFunctions, DF.ScriptHookMixin)
------------------------------------------------------------------------------------------------------------
--metatables
BarMetaFunctions.__call = function(object, value)
if (not value) then
return object.statusbar:GetValue()
else
return object.statusbar:SetValue(value)
end
end
BarMetaFunctions.__add = function(v1, v2)
if (type(v1) == "table") then
local v = v1.statusbar:GetValue()
v = v + v2
v1.statusbar:SetValue(v)
else
local v = v2.statusbar:GetValue()
v = v + v1
v2.statusbar:SetValue(v)
end
end
BarMetaFunctions.__sub = function(v1, v2)
if (type(v1) == "table") then
local v = v1.statusbar:GetValue()
v = v - v2
v1.statusbar:SetValue(v)
else
local v = v2.statusbar:GetValue()
v = v - v1
v2.statusbar:SetValue(v)
end
end
------------------------------------------------------------------------------------------------------------
--members
--tooltip
local function gmember_tooltip (_object)
return _object:GetTooltip()
end
--shown
local gmember_shown = function(_object)
return _object.statusbar:IsShown()
end
--frame width
local gmember_width = function(_object)
return _object.statusbar:GetWidth()
end
--frame height
local gmember_height = function(_object)
return _object.statusbar:GetHeight()
end
--value
local gmember_value = function(_object)
return _object.statusbar:GetValue()
end
--right text
local gmember_rtext = function(_object)
return _object.textright:GetText()
end
--left text
local gmember_ltext = function(_object)
return _object.textleft:GetText()
end
--left color
local gmember_color = function(_object)
local r, g, b, a = _object._texture:GetVertexColor()
return r, g, b, a
end
--icon
local gmember_icon = function(_object)
return _object._icon:GetTexture()
end
--texture
local gmember_texture = function(_object)
return _object._texture:GetTexture()
end
--font size
local gmember_textsize = function(_object)
local _, fontsize = _object.textleft:GetFont()
return fontsize
end
--font face
local gmember_textfont = function(_object)
local fontface = _object.textleft:GetFont()
return fontface
end
--font color
local gmember_textcolor = function(_object)
return _object.textleft:GetTextColor()
end
--alpha
local gmember_alpha= function(_object)
return _object:GetAlpha()
end
BarMetaFunctions.GetMembers = BarMetaFunctions.GetMembers or {}
BarMetaFunctions.GetMembers ["tooltip"] = gmember_tooltip
BarMetaFunctions.GetMembers ["shown"] = gmember_shown
BarMetaFunctions.GetMembers ["width"] = gmember_width
BarMetaFunctions.GetMembers ["height"] = gmember_height
BarMetaFunctions.GetMembers ["value"] = gmember_value
BarMetaFunctions.GetMembers ["lefttext"] = gmember_ltext
BarMetaFunctions.GetMembers ["righttext"] = gmember_rtext
BarMetaFunctions.GetMembers ["color"] = gmember_color
BarMetaFunctions.GetMembers ["icon"] = gmember_icon
BarMetaFunctions.GetMembers ["texture"] = gmember_texture
BarMetaFunctions.GetMembers ["fontsize"] = gmember_textsize
BarMetaFunctions.GetMembers ["fontface"] = gmember_textfont
BarMetaFunctions.GetMembers ["fontcolor"] = gmember_textcolor
BarMetaFunctions.GetMembers ["textsize"] = gmember_textsize --alias
BarMetaFunctions.GetMembers ["textfont"] = gmember_textfont --alias
BarMetaFunctions.GetMembers ["textcolor"] = gmember_textcolor --alias
BarMetaFunctions.GetMembers ["alpha"] = gmember_alpha
BarMetaFunctions.__index = function(_table, _member_requested)
local func = BarMetaFunctions.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 BarMetaFunctions [_member_requested]
end
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--tooltip
local smember_tooltip = function(_object, _value)
return _object:SetTooltip (_value)
end
--show
local smember_shown = function(_object, _value)
if (_value) then
return _object:Show()
else
return _object:Hide()
end
end
--hide
local smember_hide = function(_object, _value)
if (_value) then
return _object:Hide()
else
return _object:Show()
end
end
--width
local smember_width = function(_object, _value)
return _object.statusbar:SetWidth(_value)
end
--height
local smember_height = function(_object, _value)
return _object.statusbar:SetHeight(_value)
end
--statusbar value
local smember_value = function(_object, _value)
_object.statusbar:SetValue(_value)
return _object.div:SetPoint("left", _object.statusbar, "left", _value * (_object.statusbar:GetWidth()/100) - 16, 0)
end
--right text
local smember_rtext = function(_object, _value)
return _object.textright:SetText(_value)
end
--left text
local smember_ltext = function(_object, _value)
return _object.textleft:SetText(_value)
end
--color
local smember_color = function(_object, _value)
local _value1, _value2, _value3, _value4 = DF:ParseColors(_value)
_object.statusbar:SetStatusBarColor(_value1, _value2, _value3, _value4)
_object._texture.original_colors = {_value1, _value2, _value3, _value4}
_object.timer_texture:SetVertexColor(_value1, _value2, _value3, _value4)
_object.timer_textureR:SetVertexColor(_value1, _value2, _value3, _value4)
return _object._texture:SetVertexColor(_value1, _value2, _value3, _value4)
end
--background color
local smember_backgroundcolor = function(_object, _value)
local _value1, _value2, _value3, _value4 = DF:ParseColors(_value)
return _object.background:SetVertexColor(_value1, _value2, _value3, _value4)
end
--icon
local smember_icon = function(_object, _value)
if (type(_value) == "table") then
local _value1, _value2 = _unpack(_value)
_object._icon:SetTexture(_value1)
if (_value2) then
_object._icon:SetTexCoord(_unpack(_value2))
end
else
_object._icon:SetTexture(_value)
end
return
end
--texture
local smember_texture = function(_object, _value)
if (type(_value) == "table") then
local _value1, _value2 = _unpack(_value)
_object._texture:SetTexture(_value1)
_object.timer_texture:SetTexture(_value1)
_object.timer_textureR:SetTexture(_value1)
if (_value2) then
_object._texture:SetTexCoord(_unpack(_value2))
_object.timer_texture:SetTexCoord(_unpack(_value2))
_object.timer_textureR:SetTexCoord(_unpack(_value2))
end
else
if (_value:find("\\")) then
_object._texture:SetTexture(_value)
else
local file = SharedMedia:Fetch ("statusbar", _value)
if (file) then
_object._texture:SetTexture(file)
_object.timer_texture:SetTexture(file)
_object.timer_textureR:SetTexture(file)
else
_object._texture:SetTexture(_value)
_object.timer_texture:SetTexture(_value)
_object.timer_textureR:SetTexture(_value)
end
end
end
return
end
--background texture
local smember_backgroundtexture = function(_object, _value)
if (_value:find("\\")) then
_object.background:SetTexture(_value)
else
local file = SharedMedia:Fetch ("statusbar", _value)
if (file) then
_object.background:SetTexture(file)
else
_object.background:SetTexture(_value)
end
end
return
end
--font face
local smember_textfont = function(_object, _value)
DF:SetFontFace (_object.textleft, _value)
return DF:SetFontFace (_object.textright, _value)
end
--font size
local smember_textsize = function(_object, _value)
DF:SetFontSize(_object.textleft, _value)
return DF:SetFontSize(_object.textright, _value)
end
--font color
local smember_textcolor = function(_object, _value)
local _value1, _value2, _value3, _value4 = DF:ParseColors(_value)
_object.textleft:SetTextColor(_value1, _value2, _value3, _value4)
return _object.textright:SetTextColor(_value1, _value2, _value3, _value4)
end
--outline (shadow)
local smember_outline = function(_object, _value)
DF:SetFontOutline (_object.textleft, _value)
return DF:SetFontOutline (_object.textright, _value)
end
--alpha
local smember_alpha= function(_object, _value)
return _object:SetAlpha(_value)
end
BarMetaFunctions.SetMembers = BarMetaFunctions.SetMembers or {}
BarMetaFunctions.SetMembers["tooltip"] = smember_tooltip
BarMetaFunctions.SetMembers["shown"] = smember_shown
BarMetaFunctions.SetMembers["width"] = smember_width
BarMetaFunctions.SetMembers["height"] = smember_height
BarMetaFunctions.SetMembers["value"] = smember_value
BarMetaFunctions.SetMembers["righttext"] = smember_rtext
BarMetaFunctions.SetMembers["lefttext"] = smember_ltext
BarMetaFunctions.SetMembers["color"] = smember_color
BarMetaFunctions.SetMembers["backgroundcolor"] = smember_backgroundcolor
BarMetaFunctions.SetMembers["icon"] = smember_icon
BarMetaFunctions.SetMembers["texture"] = smember_texture
BarMetaFunctions.SetMembers["backgroundtexture"] = smember_backgroundtexture
BarMetaFunctions.SetMembers["fontsize"] = smember_textsize
BarMetaFunctions.SetMembers["fontface"] = smember_textfont
BarMetaFunctions.SetMembers["fontcolor"] = smember_textcolor
BarMetaFunctions.SetMembers["textsize"] = smember_textsize --alias
BarMetaFunctions.SetMembers["textfont"] = smember_textfont --alias
BarMetaFunctions.SetMembers["textcolor"] = smember_textcolor --alias
BarMetaFunctions.SetMembers["shadow"] = smember_outline
BarMetaFunctions.SetMembers["outline"] = smember_outline --alias
BarMetaFunctions.SetMembers["alpha"] = smember_alpha
BarMetaFunctions.__newindex = function(_table, _key, _value)
local func = BarMetaFunctions.SetMembers [_key]
if (func) then
return func (_table, _value)
else
return rawset (_table, _key, _value)
end
end
------------------------------------------------------------------------------------------------------------
--methods
--show & hide
function BarMetaFunctions:Show()
self.statusbar:Show()
end
function BarMetaFunctions:Hide()
self.statusbar:Hide()
end
--return color
function BarMetaFunctions:GetVertexColor()
return self._texture:GetVertexColor()
end
--set value (status bar)
function BarMetaFunctions:SetValue(value)
if (not value) then
value = 0
end
self.statusbar:SetValue(value)
self.div:SetPoint("left", self.statusbar, "left", value * (self.statusbar:GetWidth()/100) - 16, 0)
end
--set point
function BarMetaFunctions: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
--set sizes
function BarMetaFunctions:SetSize(w, h)
if (w) then
self.statusbar:SetWidth(w)
end
if (h) then
self.statusbar:SetHeight(h)
end
end
--set texture
function BarMetaFunctions:SetTexture(texture)
self._texture:SetTexture(texture)
end
--set texts
function BarMetaFunctions:SetLeftText (text)
self.textleft:SetText(text)
end
function BarMetaFunctions:SetRightText (text)
self.textright:SetText(text)
end
--set color
function BarMetaFunctions:SetColor (r, g, b, a)
r, g, b, a = DF:ParseColors(r, g, b, a)
self._texture:SetVertexColor(r, g, b, a)
self.statusbar:SetStatusBarColor(r, g, b, a)
self._texture.original_colors = {r, g, b, a}
end
--set icons
function BarMetaFunctions:SetIcon (texture, ...)
self._icon:SetTexture(texture)
if (...) then
local L, R, U, D = _unpack(...)
self._icon:SetTexCoord(L, R, U, D)
end
end
--show div
function BarMetaFunctions:ShowDiv (bool)
if (bool) then
self.div:Show()
else
self.div:Hide()
end
end
-- tooltip
function BarMetaFunctions:SetTooltip (tooltip)
if (tooltip) then
return rawset (self, "have_tooltip", tooltip)
else
return rawset (self, "have_tooltip", nil)
end
end
function BarMetaFunctions:GetTooltip()
return rawget (self, "have_tooltip")
end
-- frame levels
function BarMetaFunctions:GetFrameLevel()
return self.statusbar:GetFrameLevel()
end
function BarMetaFunctions:SetFrameLevel(level, frame)
if (not frame) then
return self.statusbar:SetFrameLevel(level)
else
local framelevel = frame:GetFrameLevel (frame) + level
return self.statusbar:SetFrameLevel(framelevel)
end
end
-- frame stratas
function BarMetaFunctions:SetFrameStrata()
return self.statusbar:GetFrameStrata()
end
function BarMetaFunctions:SetFrameStrata(strata)
if (type(strata) == "table") then
self.statusbar:SetFrameStrata(strata:GetFrameStrata())
else
self.statusbar:SetFrameStrata(strata)
end
end
--container
function BarMetaFunctions:SetContainer (container)
self.container = container
end
------------------------------------------------------------------------------------------------------------
--scripts
local OnEnter = function(frame)
local capsule = frame.MyObject
local kill = capsule:RunHooksForWidget("OnEnter", frame, capsule)
if (kill) then
return
end
frame.MyObject.background:Show()
if (frame.MyObject.have_tooltip) then
GameCooltip2:Reset()
GameCooltip2:AddLine(frame.MyObject.have_tooltip)
GameCooltip2:ShowCooltip(frame, "tooltip")
end
end
local OnLeave = function(frame)
local capsule = frame.MyObject
local kill = capsule:RunHooksForWidget("OnLeave", frame, capsule)
if (kill) then
return
end
frame.MyObject.background:Hide()
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 (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 (frame.MyObject.container.isMoving) then
frame.MyObject.container:StopMovingOrSizing()
frame.MyObject.container.isMoving = false
end
end
------------------------------------------------------------------------------------------------------------
--timer
function BarMetaFunctions:OnTimerEnd()
local capsule = self
local kill = capsule:RunHooksForWidget("OnTimerEnd", self.widget, capsule)
if (kill) then
return
end
self.timer_texture:Hide()
self.timer_textureR:Hide()
self.div_timer:Hide()
self:Hide()
self.timer = false
end
function BarMetaFunctions:CancelTimerBar(no_timer_end)
if (not self.HasTimer) then
return
end
if (self.TimerScheduled) then
DF:CancelTimer(self.TimerScheduled)
self.TimerScheduled = nil
else
if (self.statusbar:GetScript("OnUpdate")) then
self.statusbar:SetScript("OnUpdate", nil)
end
end
self.righttext = ""
self.timer_texture:Hide()
self.timer_textureR:Hide()
if (not no_timer_end) then
self:OnTimerEnd()
end
end
local OnUpdate = function(self, elapsed)
--percent of elapsed
local pct = abs(self.end_timer - GetTime() - self.tempo) / self.tempo
if (self.inverse) then
self.t:SetWidth(self.total_size * pct)
else
self.t:SetWidth(self.total_size * abs(pct-1))
end
--right text
self.remaining = self.remaining - elapsed
if (self.MyObject.RightTextIsTimer) then
self.righttext:SetText(DF:IntegerToTimer(self.remaining))
else
self.righttext:SetText(_math_floor(self.remaining))
end
if (pct >= 1) then
self.righttext:SetText("")
self:SetScript("OnUpdate", nil)
self.MyObject.HasTimer = nil
self.MyObject:OnTimerEnd()
end
end
function BarMetaFunctions:SetTimer (tempo, end_at)
if (end_at) then
self.statusbar.tempo = end_at - tempo
self.statusbar.remaining = end_at - GetTime()
self.statusbar.end_timer = end_at
else
self.statusbar.tempo = tempo
self.statusbar.remaining = tempo
self.statusbar.end_timer = GetTime() + tempo
end
self.statusbar.total_size = self.statusbar:GetWidth()
self.statusbar.inverse = self.BarIsInverse
self(0)
self.div_timer:Show()
self.background:Show()
self:Show()
if (self.LeftToRight) then
self.timer_texture:Hide()
self.timer_textureR:Show()
self.statusbar.t = self.timer_textureR
self.timer_textureR:ClearAllPoints()
self.timer_textureR:SetPoint("right", self.statusbar, "right")
self.div_timer:SetPoint("left", self.timer_textureR, "left", -14, -1)
else
self.timer_texture:Show()
self.timer_textureR:Hide()
self.statusbar.t = self.timer_texture
self.timer_texture:ClearAllPoints()
self.timer_texture:SetPoint("left", self.statusbar, "left")
self.div_timer:SetPoint("left", self.timer_texture, "right", -16, -1)
end
if (self.BarIsInverse) then
self.statusbar.t:SetWidth(1)
else
self.statusbar.t:SetWidth(self.statusbar.total_size)
end
self.timer = true
self.HasTimer = true
self.TimerScheduled = DF:ScheduleTimer("StartTimeBarAnimation", 0.1, self)
end
function DF:StartTimeBarAnimation (timebar)
timebar.TimerScheduled = nil
timebar.statusbar:SetScript("OnUpdate", OnUpdate)
end
------------------------------------------------------------------------------------------------------------
--object constructor
function DetailsFrameworkNormalBar_OnCreate (self)
self.texture.original_colors = {1, 1, 1, 1}
self.background.original_colors = {.3, .3, .3, .3}
self.timertexture.original_colors = {.3, .3, .3, .3}
return true
end
local build_statusbar = function(self)
self:SetSize(300, 14)
self.background = self:CreateTexture("$parent_background", "BACKGROUND")
self.background:Hide()
self.background:SetAllPoints()
self.background:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
self.background:SetVertexColor(.3, .3, .3, .3)
self.timertexture = self:CreateTexture("$parent_timerTexture", "ARTWORK")
self.timertexture:Hide()
self.timertexture:SetSize(300, 14)
self.timertexture:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
self.timertexture:SetPoint("LEFT", self, "LEFT")
self.timertextureR = self:CreateTexture("$parent_timerTextureR", "ARTWORK")
self.timertextureR:Hide()
self.timertextureR:SetSize(300, 14)
self.timertextureR:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
self.timertextureR:SetPoint("TOPRIGHT", self, 0, 0)
self.timertextureR:SetPoint("BOTTOMRIGHT", self, 0, 0)
self.texture = self:CreateTexture("$parent_statusbarTexture", "ARTWORK")
self.texture:SetSize(300, 14)
self.texture:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
self:SetStatusBarTexture(self.texture)
self.icontexture = self:CreateTexture("$parent_icon", "OVERLAY")
self.icontexture:SetSize(14, 14)
self.icontexture:SetPoint("LEFT", self, "LEFT")
self.sparkmouseover = self:CreateTexture("$parent_sparkMouseover", "OVERLAY")
self.sparkmouseover:SetSize(32, 32)
self.sparkmouseover:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
self.sparkmouseover:SetBlendMode("ADD")
self.sparkmouseover:SetPoint("LEFT", self, "RIGHT", -16, -1)
self.sparkmouseover:Hide()
self.sparktimer = self:CreateTexture("$parent_sparkTimer", "OVERLAY")
self.sparktimer:SetSize(32, 32)
self.sparktimer:SetPoint("LEFT", self.timertexture, "RIGHT", -16, -1)
self.sparktimer:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
self.sparktimer:SetBlendMode("ADD")
self.sparktimer:Hide()
self.lefttext = self:CreateFontString("$parent_TextLeft", "OVERLAY", "GameFontHighlight")
self.lefttext:SetJustifyH("LEFT")
self.lefttext:SetPoint("LEFT", self.icontexture, "RIGHT", 3, 0)
DF:SetFontSize(self.lefttext, 10)
self.righttext = self:CreateFontString("$parent_TextRight", "OVERLAY", "GameFontHighlight")
self.righttext:SetJustifyH("LEFT")
DF:SetFontSize(self.righttext, 10)
self.righttext:SetPoint("RIGHT", self, "RIGHT", -3, 0)
DetailsFrameworkNormalBar_OnCreate (self)
end
function DF:CreateBar (parent, texture, w, h, value, member, name)
return DF:NewBar (parent, parent, name, member, w, h, value, texture)
end
function DF:NewBar (parent, container, name, member, w, h, value, texture_name)
if (not name) then
name = "DetailsFrameworkBarNumber" .. DF.BarNameCounter
DF.BarNameCounter = DF.BarNameCounter + 1
elseif (not parent) then
return error("Details! FrameWork: parent not found.", 2)
elseif (not container) then
container = parent
end
if (name:find("$parent")) then
local parentName = DF.GetParentName(parent)
name = name:gsub("$parent", parentName)
end
local BarObject = {type = "bar", dframework = true}
if (member) then
parent [member] = BarObject
end
if (parent.dframework) then
parent = parent.widget
end
if (container.dframework) then
container = container.widget
end
value = value or 0
w = w or 150
h = h or 14
--default members:
--misc
BarObject.locked = false
BarObject.container = container
--create widgets
BarObject.statusbar = CreateFrame("statusbar", name, parent)
DF:Mixin(BarObject.statusbar, DF.WidgetFunctions)
build_statusbar (BarObject.statusbar)
BarObject.widget = BarObject.statusbar
if (not APIBarFunctions) then
APIBarFunctions = true
local idx = getmetatable(BarObject.statusbar).__index
for funcName, funcAddress in pairs(idx) do
if (not BarMetaFunctions [funcName]) then
BarMetaFunctions [funcName] = function(object, ...)
local x = loadstring ( "return _G['"..object.statusbar:GetName().."']:"..funcName.."(...)")
return x (...)
end
end
end
end
BarObject.statusbar:SetHeight(h)
BarObject.statusbar:SetWidth(w)
BarObject.statusbar:SetFrameLevel(parent:GetFrameLevel()+1)
BarObject.statusbar:SetMinMaxValues(0, 100)
BarObject.statusbar:SetValue(value or 50)
BarObject.statusbar.MyObject = BarObject
BarObject.timer_texture = _G [name .. "_timerTexture"]
BarObject.timer_texture:SetWidth(w)
BarObject.timer_texture:SetHeight(h)
BarObject.timer_textureR = _G [name .. "_timerTextureR"]
BarObject.timer_textureR:Hide()
BarObject._texture = _G [name .. "_statusbarTexture"]
BarObject.background = _G [name .. "_background"]
BarObject._icon = _G [name .. "_icon"]
BarObject.textleft = _G [name .. "_TextLeft"]
BarObject.textright = _G [name .. "_TextRight"]
BarObject.div = _G [name .. "_sparkMouseover"]
BarObject.div_timer = _G [name .. "_sparkTimer"]
--hooks
BarObject.HookList = {
OnEnter = {},
OnLeave = {},
OnHide = {},
OnShow = {},
OnMouseDown = {},
OnMouseUp = {},
OnTimerEnd = {},
}
BarObject.statusbar:SetScript("OnEnter", OnEnter)
BarObject.statusbar:SetScript("OnLeave", OnLeave)
BarObject.statusbar:SetScript("OnHide", OnHide)
BarObject.statusbar:SetScript("OnShow", OnShow)
BarObject.statusbar:SetScript("OnMouseDown", OnMouseDown)
BarObject.statusbar:SetScript("OnMouseUp", OnMouseUp)
--set class
setmetatable(BarObject, BarMetaFunctions)
--set texture
if (texture_name) then
smember_texture (BarObject, texture_name)
end
return BarObject
end --endd
@@ -1,3 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
<Script file="normal_bar.lua"/>
</Ui>
File diff suppressed because it is too large Load Diff
@@ -1,3 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
<Script file="panel.lua"/>
</Ui>
@@ -1,369 +0,0 @@
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local _
local APIImageFunctions = false
do
local metaPrototype = {
WidgetType = "image",
dversion = detailsFramework.dversion,
}
--check if there's a metaPrototype already existing
if (_G[detailsFramework.GlobalWidgetControlNames["image"]]) then
--get the already existing metaPrototype
local oldMetaPrototype = _G[detailsFramework.GlobalWidgetControlNames["image"]]
--check if is older
if ( (not oldMetaPrototype.dversion) or (oldMetaPrototype.dversion < detailsFramework.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[detailsFramework.GlobalWidgetControlNames["image"]] = metaPrototype
end
end
local ImageMetaFunctions = _G[detailsFramework.GlobalWidgetControlNames["image"]]
detailsFramework:Mixin(ImageMetaFunctions, detailsFramework.SetPointMixin)
detailsFramework:Mixin(ImageMetaFunctions, detailsFramework.ScriptHookMixin)
------------------------------------------------------------------------------------------------------------
--metatables
ImageMetaFunctions.__call = function(object, value)
return object.image:SetTexture(value)
end
------------------------------------------------------------------------------------------------------------
--members
--frame width
local gmember_width = function(object)
return object.image:GetWidth()
end
--frame height
local gmember_height = function(object)
return object.image:GetHeight()
end
--texture
local gmember_texture = function(object)
return object.image:GetTexture()
end
--alpha
local gmember_alpha = function(object)
return object.image:GetAlpha()
end
--saturation
local gmember_saturation = function(object)
return object.image:GetDesaturated()
end
--atlas
local gmember_atlas = function(object)
return object.image:GetAtlas()
end
--texcoords
local gmember_texcoord = function(object)
return object.image:GetTexCoord()
end
ImageMetaFunctions.GetMembers = ImageMetaFunctions.GetMembers or {}
detailsFramework:Mixin(ImageMetaFunctions.GetMembers, detailsFramework.DefaultMetaFunctionsGet)
detailsFramework:Mixin(ImageMetaFunctions.GetMembers, detailsFramework.LayeredRegionMetaFunctionsGet)
ImageMetaFunctions.GetMembers["alpha"] = gmember_alpha
ImageMetaFunctions.GetMembers["width"] = gmember_width
ImageMetaFunctions.GetMembers["height"] = gmember_height
ImageMetaFunctions.GetMembers["texture"] = gmember_texture
ImageMetaFunctions.GetMembers["blackwhite"] = gmember_saturation
ImageMetaFunctions.GetMembers["desaturated"] = gmember_saturation
ImageMetaFunctions.GetMembers["atlas"] = gmember_atlas
ImageMetaFunctions.GetMembers["texcoord"] = gmember_texcoord
ImageMetaFunctions.__index = function(object, key)
local func = ImageMetaFunctions.GetMembers[key]
if (func) then
return func(object, key)
end
local fromMe = rawget(object, key)
if (fromMe) then
return fromMe
end
return ImageMetaFunctions[key]
end
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--texture
local smember_texture = function(object, value)
if (type(value) == "table") then
local red, green, blue, alpha = detailsFramework:ParseColors(value)
object.image:SetTexture(red, green, blue, alpha)
else
if (detailsFramework:IsHtmlColor(value)) then
local red, green, blue, alpha = detailsFramework:ParseColors(value)
object.image:SetTexture(red, green, blue, alpha)
else
object.image:SetTexture(value)
end
end
end
--width
local smember_width = function(object, value)
return object.image:SetWidth(value)
end
--height
local smember_height = function(object, value)
return object.image:SetHeight(value)
end
--alpha
local smember_alpha = function(object, value)
return object.image:SetAlpha(value)
end
--color
local smember_color = function(object, value)
local red, green, blue, alpha = detailsFramework:ParseColors(value)
object.image:SetColorTexture(red, green, blue, alpha)
end
--vertex color
local smember_vertexcolor = function(object, value)
local red, green, blue, alpha = detailsFramework:ParseColors(value)
object.image:SetVertexColor(red, green, blue, alpha)
end
--desaturated
local smember_desaturated = function(object, value)
if (value) then
object:SetDesaturated(true)
else
object:SetDesaturated(false)
end
end
--texcoords
local smember_texcoord = function(object, value)
if (value) then
object:SetTexCoord(unpack(value))
else
object:SetTexCoord(0, 1, 0, 1)
end
end
--atlas
local smember_atlas = function(object, value)
if (value) then
object:SetAtlas(value)
end
end
--gradient
local smember_gradient = function(object, value)
if (type(value) == "table" and value.gradient and value.fromColor and value.toColor) then
object.image:SetColorTexture(1, 1, 1, 1)
local fromColor = detailsFramework:FormatColor("tablemembers", value.fromColor)
local toColor = detailsFramework:FormatColor("tablemembers", value.toColor)
object.image:SetGradient(value.gradient, fromColor, toColor)
else
error("texture.gradient expect a table{gradient = 'gradient type', fromColor = 'color', toColor = 'color'}")
end
end
ImageMetaFunctions.SetMembers = ImageMetaFunctions.SetMembers or {}
detailsFramework:Mixin(ImageMetaFunctions.SetMembers, detailsFramework.DefaultMetaFunctionsSet)
detailsFramework:Mixin(ImageMetaFunctions.SetMembers, detailsFramework.LayeredRegionMetaFunctionsSet)
ImageMetaFunctions.SetMembers["alpha"] = smember_alpha
ImageMetaFunctions.SetMembers["width"] = smember_width
ImageMetaFunctions.SetMembers["height"] = smember_height
ImageMetaFunctions.SetMembers["texture"] = smember_texture
ImageMetaFunctions.SetMembers["texcoord"] = smember_texcoord
ImageMetaFunctions.SetMembers["color"] = smember_color
ImageMetaFunctions.SetMembers["vertexcolor"] = smember_vertexcolor
ImageMetaFunctions.SetMembers["blackwhite"] = smember_desaturated
ImageMetaFunctions.SetMembers["desaturated"] = smember_desaturated
ImageMetaFunctions.SetMembers["atlas"] = smember_atlas
ImageMetaFunctions.SetMembers["gradient"] = smember_gradient
ImageMetaFunctions.__newindex = function(object, key, value)
local func = ImageMetaFunctions.SetMembers[key]
if (func) then
return func(object, value)
else
return rawset(object, key, value)
end
end
------------------------------------------------------------------------------------------------------------
--methods
--size
function ImageMetaFunctions:SetSize(width, height)
if (width) then
self.image:SetWidth(width)
end
if (height) then
return self.image:SetHeight(height)
end
end
function ImageMetaFunctions:SetGradient(gradientType, fromColor, toColor)
fromColor = detailsFramework:FormatColor("tablemembers", fromColor)
toColor = detailsFramework:FormatColor("tablemembers", toColor)
self.image:SetGradient(gradientType, fromColor, toColor)
end
------------------------------------------------------------------------------------------------------------
--object constructor
---@class df_image : texture
---@field SetGradient fun(gradientType: "vertical"|"horizontal", fromColor: table, toColor: table)
---create an object that encapsulates a texture and add additional methods to it
---@param parent frame
---@param texture texturepath|textureid
---@param width number
---@param height number
---@param layer drawlayer
---@param coords {key1: number, key2: number, key3: number, key4: number}
---@param member string
---@param name string
---@return table|nil
function detailsFramework:CreateTexture(parent, texture, width, height, layer, coords, member, name)
return detailsFramework:NewImage(parent, texture, width, height, layer, coords, member, name)
end
---create an object that encapsulates a texture and add additional methods to it
---@param parent frame
---@param texture texturepath|textureid
---@param width number
---@param height number
---@param layer drawlayer
---@param coords {key1: number, key2: number, key3: number, key4: number}
---@param member string
---@param name string
---@return table|nil
function detailsFramework:CreateImage(parent, texture, width, height, layer, coords, member, name)
return detailsFramework:NewImage(parent, texture, width, height, layer, coords, member, name)
end
function detailsFramework:NewImage(parent, texture, width, height, layer, texCoord, member, name)
if (not parent) then
return error("DetailsFrameWork: NewImage() parent not found.", 2)
end
if (not name) then
name = "DetailsFrameworkPictureNumber" .. detailsFramework.PictureNameCounter
detailsFramework.PictureNameCounter = detailsFramework.PictureNameCounter + 1
end
if (name:find("$parent")) then
local parentName = detailsFramework.GetParentName(parent)
name = name:gsub("$parent", parentName)
end
local ImageObject = {type = "image", dframework = true}
if (member) then
parent[member] = ImageObject
end
if (parent.dframework) then
parent = parent.widget
end
texture = texture or ""
ImageObject.image = parent:CreateTexture(name, layer or "overlay")
ImageObject.widget = ImageObject.image
detailsFramework:Mixin(ImageObject.image, detailsFramework.WidgetFunctions)
if (not APIImageFunctions) then
APIImageFunctions = true
local idx = getmetatable(ImageObject.image).__index
for funcName, funcAddress in pairs(idx) do
if (not ImageMetaFunctions[funcName]) then
ImageMetaFunctions[funcName] = function(object, ...)
local x = loadstring( "return _G['" .. object.image:GetName() .. "']:" .. funcName .. "(...)")
return x(...)
end
end
end
end
ImageObject.image.MyObject = ImageObject
if (width) then
ImageObject.image:SetWidth(width)
end
if (height) then
ImageObject.image:SetHeight(height)
end
if (texture) then
if (type(texture) == "table") then
if (texture.gradient) then
if (detailsFramework.IsDragonflight() or detailsFramework.IsNonRetailWowWithRetailAPI()) then
ImageObject.image:SetColorTexture(1, 1, 1, 1)
local fromColor = detailsFramework:FormatColor("tablemembers", texture.fromColor)
local toColor = detailsFramework:FormatColor("tablemembers", texture.toColor)
ImageObject.image:SetGradient(texture.gradient, fromColor, toColor)
else
local fromR, fromG, fromB, fromA = detailsFramework:ParseColors(texture.fromColor)
local toR, toG, toB, toA = detailsFramework:ParseColors(texture.toColor)
ImageObject.image:SetColorTexture(1, 1, 1, 1)
ImageObject.image:SetGradientAlpha(texture.gradient, fromR, fromG, fromB, fromA, toR, toG, toB, toA)
end
else
local r, g, b, a = detailsFramework:ParseColors(texture)
ImageObject.image:SetColorTexture(r, g, b, a)
end
elseif (type(texture) == "string") then
local isAtlas = C_Texture.GetAtlasInfo(texture)
if (isAtlas) then
ImageObject.image:SetAtlas(texture)
else
if (detailsFramework:IsHtmlColor(texture)) then
local r, g, b = detailsFramework:ParseColors(texture)
ImageObject.image:SetColorTexture(r, g, b)
else
ImageObject.image:SetTexture(texture)
end
end
else
ImageObject.image:SetTexture(texture)
end
end
if (texCoord and type(texCoord) == "table" and texCoord[4]) then
ImageObject.image:SetTexCoord(unpack(texCoord))
end
ImageObject.HookList = {
}
setmetatable(ImageObject, ImageMetaFunctions)
return ImageObject
end
@@ -1,607 +0,0 @@
local DF = _G["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
local _
local texCoordinates
local CreateImageEditorFrame = function()
local editorWindow = DF:NewPanel(UIParent, nil, "DetailsFrameworkImageEdit", nil, 650, 500, false)
editorWindow:SetPoint("center", UIParent, "center")
editorWindow:SetResizable(true)
editorWindow:SetMovable(true)
editorWindow:SetClampedToScreen(true)
tinsert(UISpecialFrames, "DetailsFrameworkImageEdit")
editorWindow:SetFrameStrata("TOOLTIP")
if (not DetailsFramework.IsDragonflight()) then
editorWindow:SetMaxResize(500, 500)
else
editorWindow:SetResizeBounds(100, 100, 500, 500)
end
_G.DetailsFrameworkImageEditTable = editorWindow
editorWindow.hooks = {}
local background = DF:NewImage(editorWindow, nil, nil, nil, "background", nil, "background", "$parentBackground")
background:SetAllPoints()
background:SetTexture(0, 0, 0, .8)
local edit_texture = DF:NewImage(editorWindow, nil, 500, 500, "artwork", nil, "edit_texture", "$parentImage")
edit_texture:SetAllPoints()
_G.DetailsFrameworkImageEdit_EditTexture = edit_texture
local background_frame = CreateFrame("frame", "DetailsFrameworkImageEditBackground", DetailsFrameworkImageEdit, "BackdropTemplate")
background_frame:SetPoint("topleft", DetailsFrameworkImageEdit, "topleft", -10, 30)
background_frame:SetFrameStrata("TOOLTIP")
background_frame:SetFrameLevel(editorWindow:GetFrameLevel())
background_frame:SetSize(790, 560)
background_frame:SetResizable(true)
background_frame:SetMovable(true)
background_frame:SetScript("OnMouseDown", function()
editorWindow:StartMoving()
end)
background_frame:SetScript("OnMouseUp", function()
editorWindow:StopMovingOrSizing()
end)
DF:CreateTitleBar (background_frame, "Image Editor")
DF:ApplyStandardBackdrop(background_frame, false, 0.98)
DF:CreateStatusBar(background_frame)
background_frame:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
background_frame:SetBackdropColor(0, 0, 0, 0.9)
background_frame:SetBackdropBorderColor(0, 0, 0, 1)
local haveHFlip = false
local haveVFlip = false
--Top Slider
local topCoordTexture = DF:NewImage(editorWindow, nil, nil, nil, "overlay", nil, nil, "$parentImageTopCoord")
topCoordTexture:SetPoint("topleft", editorWindow, "topleft")
topCoordTexture:SetPoint("topright", editorWindow, "topright")
topCoordTexture:SetColorTexture(1, 0, 0)
topCoordTexture.height = 1
topCoordTexture.alpha = .2
local topSlider = DF:NewSlider (editorWindow, nil, "$parentTopSlider", "topSlider", 100, 100, 0.1, 100, 0.1, 0)
topSlider:SetAllPoints(editorWindow.widget)
topSlider:SetOrientation("VERTICAL")
topSlider.backdrop = nil
topSlider.fractional = true
topSlider:SetHook("OnEnter", function() return true end)
topSlider:SetHook("OnLeave", function() return true end)
local topSliderThumpTexture = topSlider:CreateTexture(nil, "overlay")
topSliderThumpTexture:SetColorTexture(1, 1, 1)
topSliderThumpTexture:SetWidth(512)
topSliderThumpTexture:SetHeight(1)
topSlider:SetThumbTexture (topSliderThumpTexture)
topSlider:SetHook("OnValueChange", function(_, _, value)
topCoordTexture.image:SetHeight(editorWindow.frame:GetHeight()/100*value)
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end)
topSlider:Hide()
--Bottom Slider
local bottomCoordTexture = DF:NewImage(editorWindow, nil, nil, nil, "overlay", nil, nil, "$parentImageBottomCoord")
bottomCoordTexture:SetPoint("bottomleft", editorWindow, "bottomleft", 0, 0)
bottomCoordTexture:SetPoint("bottomright", editorWindow, "bottomright", 0, 0)
bottomCoordTexture:SetColorTexture(1, 0, 0)
bottomCoordTexture.height = 1
bottomCoordTexture.alpha = .2
local bottomSlider = DF:NewSlider (editorWindow, nil, "$parentBottomSlider", "bottomSlider", 100, 100, 0.1, 100, 0.1, 100)
bottomSlider:SetAllPoints(editorWindow.widget)
bottomSlider:SetOrientation("VERTICAL")
bottomSlider.backdrop = nil
bottomSlider.fractional = true
bottomSlider:SetHook("OnEnter", function() return true end)
bottomSlider:SetHook("OnLeave", function() return true end)
local bottomSliderThumpTexture = bottomSlider:CreateTexture(nil, "overlay")
bottomSliderThumpTexture:SetColorTexture(1, 1, 1)
bottomSliderThumpTexture:SetWidth(512)
bottomSliderThumpTexture:SetHeight(1)
bottomSlider:SetThumbTexture (bottomSliderThumpTexture)
bottomSlider:SetHook("OnValueChange", function(_, _, value)
value = math.abs(value-100)
bottomCoordTexture.image:SetHeight(math.max(editorWindow.frame:GetHeight()/100*value, 1))
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end)
bottomSlider:Hide()
--Left Slider
local leftCoordTexture = DF:NewImage(editorWindow, nil, nil, nil, "overlay", nil, nil, "$parentImageLeftCoord")
leftCoordTexture:SetPoint("topleft", editorWindow, "topleft", 0, 0)
leftCoordTexture:SetPoint("bottomleft", editorWindow, "bottomleft", 0, 0)
leftCoordTexture:SetColorTexture(1, 0, 0)
leftCoordTexture.width = 1
leftCoordTexture.alpha = .2
local leftSlider = DF:NewSlider (editorWindow, nil, "$parentLeftSlider", "leftSlider", 100, 100, 0.1, 100, 0.1, 0.1)
leftSlider:SetAllPoints(editorWindow.widget)
leftSlider.backdrop = nil
leftSlider.fractional = true
leftSlider:SetHook("OnEnter", function() return true end)
leftSlider:SetHook("OnLeave", function() return true end)
local leftSliderThumpTexture = leftSlider:CreateTexture(nil, "overlay")
leftSliderThumpTexture:SetColorTexture(1, 1, 1)
leftSliderThumpTexture:SetWidth(1)
leftSliderThumpTexture:SetHeight(512)
leftSlider:SetThumbTexture (leftSliderThumpTexture)
leftSlider:SetHook("OnValueChange", function(_, _, value)
leftCoordTexture.image:SetWidth(editorWindow.frame:GetWidth()/100*value)
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end)
leftSlider:Hide()
--Right Slider
local rightCoordTexture = DF:NewImage(editorWindow, nil, nil, nil, "overlay", nil, nil, "$parentImageRightCoord")
rightCoordTexture:SetPoint("topright", editorWindow, "topright", 0, 0)
rightCoordTexture:SetPoint("bottomright", editorWindow, "bottomright", 0, 0)
rightCoordTexture:SetColorTexture(1, 0, 0)
rightCoordTexture.width = 1
rightCoordTexture.alpha = .2
local rightSlider = DF:NewSlider (editorWindow, nil, "$parentRightSlider", "rightSlider", 100, 100, 0.1, 100, 0.1, 100)
rightSlider:SetAllPoints(editorWindow.widget)
rightSlider.backdrop = nil
rightSlider.fractional = true
rightSlider:SetHook("OnEnter", function() return true end)
rightSlider:SetHook("OnLeave", function() return true end)
--[
local rightSliderThumpTexture = rightSlider:CreateTexture(nil, "overlay")
rightSliderThumpTexture:SetColorTexture(1, 1, 1)
rightSliderThumpTexture:SetWidth(1)
rightSliderThumpTexture:SetHeight(512)
rightSlider:SetThumbTexture (rightSliderThumpTexture)
--]]
rightSlider:SetHook("OnValueChange", function(_, _, value)
value = math.abs(value-100)
rightCoordTexture.image:SetWidth(math.max(editorWindow.frame:GetWidth()/100*value, 1))
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end)
rightSlider:Hide()
--Edit Buttons
local buttonsBackground = DF:NewPanel(UIParent, nil, "DetailsFrameworkImageEditButtonsBg", nil, 115, 230)
--buttonsBackground:SetPoint("topleft", window, "topright", 2, 0)
buttonsBackground:SetPoint("topright", background_frame, "topright", -8, -10)
buttonsBackground:Hide()
--buttonsBackground:SetMovable(true)
tinsert(UISpecialFrames, "DetailsFrameworkImageEditButtonsBg")
buttonsBackground:SetFrameStrata("TOOLTIP")
local alphaFrameShown = false
local editingSide = nil
local lastButton = nil
local alphaFrame
local originalColor = {0.9999, 0.8196, 0}
local enableTexEdit = function(button, bottom, side)
if (alphaFrameShown) then
alphaFrame:Hide()
alphaFrameShown = false
button.text:SetTextColor(unpack(originalColor))
end
if (ColorPickerFrame:IsShown()) then
ColorPickerFrame:Hide()
end
if (lastButton) then
lastButton.text:SetTextColor(unpack(originalColor))
end
if (editingSide == side) then
editorWindow [editingSide.."Slider"]:Hide()
editingSide = nil
return
elseif (editingSide) then
editorWindow [editingSide.."Slider"]:Hide()
end
editingSide = side
button.text:SetTextColor(1, 1, 1)
lastButton = button
editorWindow [side.."Slider"]:Show()
end
local yMod = -10
local leftTexCoordButton = DF:NewButton(buttonsBackground, nil, "$parentLeftTexButton", nil, 100, 20, enableTexEdit, "left", nil, nil, "Crop Left", 1)
leftTexCoordButton:SetPoint("topright", buttonsBackground, "topright", -8, -10 + yMod)
leftTexCoordButton:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
local rightTexCoordButton = DF:NewButton(buttonsBackground, nil, "$parentRightTexButton", nil, 100, 20, enableTexEdit, "right", nil, nil, "Crop Right", 1)
rightTexCoordButton:SetPoint("topright", buttonsBackground, "topright", -8, -30 + yMod)
rightTexCoordButton:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
local topTexCoordButton = DF:NewButton(buttonsBackground, nil, "$parentTopTexButton", nil, 100, 20, enableTexEdit, "top", nil, nil, "Crop Top", 1)
topTexCoordButton:SetPoint("topright", buttonsBackground, "topright", -8, -50 + yMod)
topTexCoordButton:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
local bottomTexCoordButton = DF:NewButton(buttonsBackground, nil, "$parentBottomTexButton", nil, 100, 20, enableTexEdit, "bottom", nil, nil, "Crop Bottom", 1)
bottomTexCoordButton:SetPoint("topright", buttonsBackground, "topright", -8, -70 + yMod)
bottomTexCoordButton:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
local Alpha = DF:NewButton(buttonsBackground, nil, "$parentBottomAlphaButton", nil, 100, 20, alpha, nil, nil, nil, "Alpha", 1)
Alpha:SetPoint("topright", buttonsBackground, "topright", -8, -115 + yMod)
Alpha:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
--overlay color
local selectedColor = function(default)
if (default) then
edit_texture:SetVertexColor(unpack(default))
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
else
edit_texture:SetVertexColor(ColorPickerFrame:GetColorRGB())
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end
end
local changeColor = function()
ColorPickerFrame.func = nil
ColorPickerFrame.opacityFunc = nil
ColorPickerFrame.cancelFunc = nil
ColorPickerFrame.previousValues = nil
local right, g, bottom = edit_texture:GetVertexColor()
ColorPickerFrame:SetColorRGB (right, g, bottom)
ColorPickerFrame:SetParent(buttonsBackground.widget)
ColorPickerFrame.hasOpacity = false
ColorPickerFrame.previousValues = {right, g, bottom}
ColorPickerFrame.func = selectedColor
ColorPickerFrame.cancelFunc = selectedColor
ColorPickerFrame:ClearAllPoints()
ColorPickerFrame:SetPoint("left", buttonsBackground.widget, "right")
ColorPickerFrame:Show()
if (alphaFrameShown) then
alphaFrame:Hide()
alphaFrameShown = false
Alpha.button.text:SetTextColor(unpack(originalColor))
end
if (lastButton) then
lastButton.text:SetTextColor(unpack(originalColor))
if (editingSide) then
editorWindow [editingSide.."Slider"]:Hide()
end
end
end
local changeColorButton = DF:NewButton(buttonsBackground, nil, "$parentOverlayColorButton", nil, 100, 20, changeColor, nil, nil, nil, "Color", 1)
changeColorButton:SetPoint("topright", buttonsBackground, "topright", -8, -95 + yMod)
changeColorButton:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
alphaFrame = DF:NewPanel(buttonsBackground, nil, "DetailsFrameworkImageEditAlphaBg", nil, 40, 225)
alphaFrame:SetPoint("topleft", buttonsBackground, "topright", 2, 0)
alphaFrame:Hide()
local alphaSlider = DF:NewSlider (alphaFrame, nil, "$parentAlphaSlider", "alphaSlider", 30, 220, 1, 100, 1, edit_texture:GetAlpha()*100)
alphaSlider:SetPoint("top", alphaFrame, "top", 0, -5)
alphaSlider:SetOrientation("VERTICAL")
alphaSlider.thumb:SetSize(40, 30)
--leftSlider.backdrop = nil
--leftSlider.fractional = true
local alpha = function(button)
if (ColorPickerFrame:IsShown()) then
ColorPickerFrame:Hide()
end
if (lastButton) then
lastButton.text:SetTextColor(unpack(originalColor))
if (editingSide) then
editorWindow [editingSide.."Slider"]:Hide()
end
end
if (not alphaFrameShown) then
alphaFrame:Show()
alphaSlider:SetValue(edit_texture:GetAlpha()*100)
alphaFrameShown = true
button.text:SetTextColor(1, 1, 1)
else
alphaFrame:Hide()
alphaFrameShown = false
button.text:SetTextColor(unpack(originalColor))
end
end
Alpha.clickfunction = alpha
alphaSlider:SetHook("OnValueChange", function(_, _, value)
edit_texture:SetAlpha(value/100)
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end)
local resizer = CreateFrame("Button", nil, editorWindow.widget, "BackdropTemplate")
resizer:SetNormalTexture([[Interface\AddOns\Details\images\skins\default_skin]])
resizer:SetHighlightTexture([[Interface\AddOns\Details\images\skins\default_skin]])
resizer:GetNormalTexture():SetTexCoord(0.00146484375, 0.01513671875, 0.24560546875, 0.25927734375)
resizer:GetHighlightTexture():SetTexCoord(0.00146484375, 0.01513671875, 0.24560546875, 0.25927734375)
resizer:SetWidth(16)
resizer:SetHeight(16)
resizer:SetPoint("BOTTOMRIGHT", editorWindow.widget, "BOTTOMRIGHT", 0, 0)
resizer:EnableMouse(true)
resizer:SetFrameLevel(editorWindow.widget:GetFrameLevel() + 2)
resizer:SetScript("OnMouseDown", function(self, button)
editorWindow.widget:StartSizing("BOTTOMRIGHT")
end)
resizer:SetScript("OnMouseUp", function(self, button)
editorWindow.widget:StopMovingOrSizing()
end)
editorWindow.widget:SetScript("OnMouseDown", function()
editorWindow.widget:StartMoving()
end)
editorWindow.widget:SetScript("OnMouseUp", function()
editorWindow.widget:StopMovingOrSizing()
end)
editorWindow.widget:SetScript("OnSizeChanged", function()
edit_texture.width = editorWindow.width
edit_texture.height = editorWindow.height
leftSliderThumpTexture:SetHeight(editorWindow.height)
rightSliderThumpTexture:SetHeight(editorWindow.height)
topSliderThumpTexture:SetWidth(editorWindow.width)
bottomSliderThumpTexture:SetWidth(editorWindow.width)
rightCoordTexture.image:SetWidth(math.max( (editorWindow.frame:GetWidth() / 100 * math.abs(rightSlider:GetValue()-100)), 1))
leftCoordTexture.image:SetWidth(editorWindow.frame:GetWidth()/100*leftSlider:GetValue())
bottomCoordTexture:SetHeight(math.max( (editorWindow.frame:GetHeight() / 100 * math.abs(bottomSlider:GetValue()-100)), 1))
topCoordTexture:SetHeight(editorWindow.frame:GetHeight()/100*topSlider:GetValue())
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end)
--flip button
local flip = function(button, bottom, side)
if (side == 1) then
haveHFlip = not haveHFlip
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
elseif (side == 2) then
haveVFlip = not haveVFlip
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end
end
local flipButtonH = DF:NewButton(buttonsBackground, nil, "$parentFlipButton", nil, 100, 20, flip, 1, nil, nil, "Flip H", 1)
flipButtonH:SetPoint("topright", buttonsBackground, "topright", -8, -140 + yMod)
flipButtonH:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
--select area to crop
local dragFrame = CreateFrame("frame", nil, background_frame, "BackdropTemplate")
dragFrame:EnableMouse(false)
dragFrame:SetFrameStrata("TOOLTIP")
dragFrame:SetPoint("topleft", edit_texture.widget, "topleft")
dragFrame:SetPoint("bottomright", edit_texture.widget, "bottomright")
dragFrame:SetBackdrop({edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Worldmap\UI-QuestBlob-Inside]], tileSize = 256, tile = true})
dragFrame:SetBackdropColor(1, 1, 1, .2)
dragFrame:Hide()
local selectionBoxUp = dragFrame:CreateTexture(nil, "overlay")
selectionBoxUp:SetHeight(1)
selectionBoxUp:SetColorTexture(1, 1, 1)
local selectionBoxDown = dragFrame:CreateTexture(nil, "overlay")
selectionBoxDown:SetHeight(1)
selectionBoxDown:SetColorTexture(1, 1, 1)
local selectionBoxLeft = dragFrame:CreateTexture(nil, "overlay")
selectionBoxLeft:SetWidth(1)
selectionBoxLeft:SetColorTexture(1, 1, 1)
local selectionBoxRight = dragFrame:CreateTexture(nil, "overlay")
selectionBoxRight:SetWidth(1)
selectionBoxRight:SetColorTexture(1, 1, 1)
function dragFrame.ClearSelectionBoxPoints()
selectionBoxUp:ClearAllPoints()
selectionBoxDown:ClearAllPoints()
selectionBoxLeft:ClearAllPoints()
selectionBoxRight:ClearAllPoints()
end
local startCropFunc = function()
dragFrame:Show()
dragFrame:EnableMouse(true)
end
local cropSelection = DF:NewButton(buttonsBackground, nil, "$parentCropSelection", nil, 100, 20, startCropFunc, 2, nil, nil, "Crop Selection", 1)
cropSelection:InstallCustomTexture()
dragFrame.OnTick = function(self, deltaTime)
local x1, y1 = unpack(self.ClickedAt)
local x2, y2 = GetCursorPosition()
dragFrame.ClearSelectionBoxPoints()
if (x2 > x1) then
--right
if (y1 > y2) then
--top
selectionBoxUp:SetPoint("topleft", UIParent, "bottomleft", x1, y1)
selectionBoxUp:SetPoint("topright", UIParent, "bottomleft", x2, y1)
selectionBoxLeft:SetPoint("topleft", UIParent, "bottomleft", x1, y1)
selectionBoxLeft:SetPoint("bottomleft", UIParent, "bottomleft", x1, y2)
else
--bottom
end
else
--left
if (y2 > y1) then
--top
else
--bottom
end
end
end
dragFrame:SetScript("OnMouseDown", function(self, MouseButton)
if (MouseButton == "LeftButton") then
self.ClickedAt = {GetCursorPosition()}
dragFrame:SetScript("OnUpdate", dragFrame.OnTick)
end
end)
dragFrame:SetScript("OnMouseUp", function(self, MouseButton)
if (MouseButton == "LeftButton") then
self.ReleaseAt = {GetCursorPosition()}
dragFrame:EnableMouse(false)
dragFrame:Hide()
dragFrame:SetScript("OnUpdate", nil)
print(self.ClickedAt[1], self.ClickedAt[2], self.ReleaseAt[1], self.ReleaseAt[2])
end
end)
--accept
editorWindow.accept = function(self, bottom, keepEditing)
if (not keepEditing) then
buttonsBackground:Hide()
editorWindow:Hide()
alphaFrame:Hide()
ColorPickerFrame:Hide()
end
local coords = {}
local left, right, top, bottom = leftSlider.value/100, rightSlider.value/100, topSlider.value/100, bottomSlider.value/100
if (haveHFlip) then
coords [1] = right
coords [2] = left
else
coords [1] = left
coords [2] = right
end
if (haveVFlip) then
coords [3] = bottom
coords [4] = top
else
coords [3] = top
coords [4] = bottom
end
return editorWindow.callback_func(edit_texture.width, edit_texture.height, {edit_texture:GetVertexColor()}, edit_texture:GetAlpha(), coords, editorWindow.extra_param)
end
local acceptButton = DF:NewButton(buttonsBackground, nil, "$parentAcceptButton", nil, 100, 20, editorWindow.accept, nil, nil, nil, "Done", 1)
acceptButton:SetPoint("topright", buttonsBackground, "topright", -8, -200)
acceptButton:SetTemplate(DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
function DF:RefreshImageEditor()
if (edit_texture.maximize) then
DetailsFrameworkImageEdit:SetSize(266, 226)
else
DetailsFrameworkImageEdit:SetSize(edit_texture.width, edit_texture.height)
end
local left, right, top, bottom = unpack(texCoordinates)
if (left > right) then
haveHFlip = true
leftSlider:SetValue(right * 100)
rightSlider:SetValue(left * 100)
else
haveHFlip = false
leftSlider:SetValue(left * 100)
rightSlider:SetValue(right * 100)
end
if (top > bottom) then
haveVFlip = true
topSlider:SetValue(bottom * 100)
bottomSlider:SetValue(top * 100)
else
haveVFlip = false
topSlider:SetValue(top * 100)
bottomSlider:SetValue(bottom * 100)
end
if (editorWindow.callback_func) then
editorWindow.accept(nil, nil, true)
end
end
editorWindow:Hide()
end
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DF:ImageEditor(callback, texture, texcoord, colors, width, height, extraParam, alpha, maximize)
if (not _G.DetailsFrameworkImageEdit) then
CreateImageEditorFrame()
end
local window = _G.DetailsFrameworkImageEditTable
texcoord = texcoord or {0, 1, 0, 1}
texCoordinates = texcoord
colors = colors or {1, 1, 1, 1}
alpha = alpha or 1
_G.DetailsFrameworkImageEdit_EditTexture:SetTexture(texture)
_G.DetailsFrameworkImageEdit_EditTexture.width = width
_G.DetailsFrameworkImageEdit_EditTexture.height = height
_G.DetailsFrameworkImageEdit_EditTexture.maximize = maximize
_G.DetailsFrameworkImageEdit_EditTexture:SetVertexColor(colors [1], colors [2], colors [3])
_G.DetailsFrameworkImageEdit_EditTexture:SetAlpha(alpha)
DF.Schedules.NewTimer(0.2, DF.RefreshImageEditor)
window:Show()
window.callback_func = callback
window.extra_param = extraParam
DetailsFrameworkImageEditButtonsBg:Show()
DetailsFrameworkImageEditButtonsBg:SetBackdrop(nil)
table.wipe(window.hooks)
end
@@ -1,219 +0,0 @@
--stopped doing the duplicate savedTable
local DF = _G ["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
--create namespace
DF.SavedVars = {}
function DF.SavedVars.CreateNewSavedTable(dbTable, savedTableName)
local defaultVars = dbTable.defaultSavedVars
local newSavedTable = DF.table.deploy({}, defaultVars)
dbTable.profiles[savedTableName] = newSavedTable
return newSavedTable
end
function DF.SavedVars.GetOrCreateAddonSavedTablesPlayerList(addonFrame)
local addonGlobalSavedTable = _G[addonFrame.__savedVarsName]
--player list
local playerList = addonGlobalSavedTable.__savedVarsByGUID
if (not playerList) then
addonGlobalSavedTable.__savedVarsByGUID = {}
end
--saved variables table
if (not addonGlobalSavedTable.__savedVars) then
addonGlobalSavedTable.__savedVars = {}
end
return addonGlobalSavedTable.__savedVarsByGUID
end
--addon statup
function DF.SavedVars.LoadSavedVarsForPlayer(addonFrame)
local playerSerial = UnitGUID("player")
--savedTableObject is equivalent of "addon.db"
local dbTable = DF.SavedVars.CreateSavedVarsTable(addonFrame, addonFrame.__savedVarsDefaultTemplate)
addonFrame.__savedVarsDefaultTemplate = nil
addonFrame.db = dbTable
--load players list
local savedVarsName = DF.SavedVars.GetOrCreateAddonSavedTablesPlayerList(addonFrame)
local playerSavedTableName = savedVarsName[playerSerial]
if (not playerSavedTableName) then
savedVarsName[playerSerial] = "Default"
playerSavedTableName = savedVarsName[playerSerial]
end
local savedTable = addonFrame.db:GetSavedTable(playerSavedTableName)
if (not savedTable) then
--create a new saved table for this character
savedTable = addonFrame.db:CreateNewSavedTable(playerSavedTableName)
end
DF.SavedVars.SetSavedTable(dbTable, playerSavedTableName, true, true)
return savedTable
end
function DF.SavedVars.TableCleanUpRecursive(t, default)
for key, value in pairs(t) do
if (type(value) == "table") then
DF.SavedVars.TableCleanUpRecursive(value, default[key])
else
if (value == default[key]) then
t[key] = nil
end
end
end
end
function DF.SavedVars.CloseSavedTable(dbTable)
local currentSavedTable = dbTable:GetSavedTable(dbTable:GetCurrentSavedTableName())
local default = dbTable.defaultSavedVars
if (type(currentSavedTable) == "table") then
DF.SavedVars.TableCleanUpRecursive(currentSavedTable, default)
--save
local addonGlobalSavedTable = _G[dbTable.addonFrame.__savedVarsName]
addonGlobalSavedTable.__savedVars[dbTable:GetCurrentSavedTableName()] = currentSavedTable
end
end
--base functions
function DF.SavedVars.SetSavedTable(dbTable, savedTableName, createIfNonExistant, isFromInit)
local savedTableToBeApplied = dbTable:GetSavedTable(savedTableName)
if (savedTableToBeApplied) then
if (not isFromInit) then
--callback unload profile table
local currentSavedTable = dbTable:GetSavedTable(dbTable:GetCurrentSavedTableName())
dbTable:TriggerCallback("OnProfileUnload", currentSavedTable)
DF.SavedVars.CloseSavedTable(dbTable, currentSavedTable)
end
dbTable.profile = savedTableToBeApplied
dbTable.currentSavedTableName = savedTableName
dbTable:TriggerCallback("OnProfileLoad", savedTableToBeApplied)
else
if (createIfNonExistant) then
local newSavedTable = dbTable:CreateNewSavedTable(savedTableName)
--callback unload profile table
local currentSavedTable = dbTable:GetSavedTable(dbTable:GetCurrentSavedTableName())
dbTable:TriggerCallback("OnProfileUnload", currentSavedTable)
DF.SavedVars.CloseSavedTable(dbTable, currentSavedTable)
dbTable.profile = newSavedTable
dbTable.currentSavedTableName = savedTableName
dbTable:TriggerCallback("OnProfileLoad", newSavedTable)
else
DF:Msg("profile does not exists", savedTableName)
return
end
end
end
function DF.SavedVars.GetSavedTables(dbTable)
return dbTable.profiles
end
function DF.SavedVars.GetSavedTable(dbTable, savedTableName)
local profiles = dbTable:GetSavedTables()
return profiles[savedTableName]
end
function DF.SavedVars.GetCurrentSavedTableName(dbTable)
return dbTable.currentSavedTableName
end
--duplicate savedTable
function DF.SavedVars.DuplicateSavedTable(dbTable, savedTableName)
local originalSavedTable = dbTable:GetSavedTable(savedTableName)
if (originalSavedTable) then
local newSavedTable = DF.table.copy({}, originalSavedTable)
end
end
--callbacks
function DF.SavedVars.TriggerCallback(dbTable, callbackName, savedTable)
local registeredCallbacksTable = dbTable.registeredCallbacks[callbackName]
for i = 1, #registeredCallbacksTable do
local callback = registeredCallbacksTable[i]
DF:CoreDispatch(dbTable.addonFrame.__name, callback.func, savedTable, unpack(callback.payload))
end
end
function DF.SavedVars.RegisterCallback(dbTable, callbackName, func, ...)
local registeredCallbacksTable = dbTable.registeredCallbacks[callbackName]
if (registeredCallbacksTable) then
--check for duplicates
for i = 1, #registeredCallbacksTable do
if (registeredCallbacksTable[i].func == func) then
return
end
end
--register
registeredCallbacksTable[#registeredCallbacksTable+1] = {func = func, payload = {...}}
return true
end
end
function DF.SavedVars.UnregisterCallback(dbTable, callbackName, func)
local registeredCallbacksTable = dbTable.registeredCallbacks[callbackName]
if (registeredCallbacksTable) then
for i = 1, #registeredCallbacksTable do
if (registeredCallbacksTable[i].func == func) then
tremove(registeredCallbacksTable, i)
return true
end
end
end
end
function DF.SavedVars.CreateSavedVarsTable(addonFrame, templateTable)
local dbTable = {
profiles = {},
defaultSavedVars = templateTable,
currentSavedTableName = "",
addonFrame = addonFrame,
--methods
GetSavedTable = DF.SavedVars.GetSavedTable,
SetSavedTable = DF.SavedVars.SetSavedTable,
GetSavedTables = DF.SavedVars.GetSavedTables,
GetCurrentSavedTableName = DF.SavedVars.GetCurrentSavedTableName,
CreateNewSavedTable = DF.SavedVars.CreateNewSavedTable,
TriggerCallback = DF.SavedVars.TriggerCallback,
--back compatibility with ace3DB
GetCurrentProfile = DF.SavedVars.GetCurrentSavedTableName,
GetProfile = DF.SavedVars.GetSavedTable,
GetProfiles = DF.SavedVars.GetSavedTables,
SetProfile = DF.SavedVars.SetSavedTable,
RegisterCallback = DF.SavedVars.RegisterCallback,
registeredCallbacks = {
["OnProfileLoad"] = {},
["OnProfileUnload"] = {},
["OnProfileCopied"] = {},
["OnProfileReset"] = {},
["OnDatabaseLoad"] = {},
["OnDatabaseShutdown"] = {},
},
}
return dbTable
end
@@ -1,73 +0,0 @@
local DF = _G["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
local C_Timer = _G.C_Timer
local unpack = table.unpack or _G.unpack
--make a namespace for schedules
DF.Schedules = DF.Schedules or {}
--run a scheduled function with its payload
local triggerScheduledTick = function(tickerObject)
local payload = tickerObject.payload
local callback = tickerObject.callback
local result, errortext = pcall(callback, unpack(payload))
if (not result) then
DF:Msg("error on scheduler: ", tickerObject.path, tickerObject.name, errortext)
end
return result
end
--schedule to repeat a task with an interval of @time
function DF.Schedules.NewTicker(time, callback, ...)
local payload = {...}
local newTicker = C_Timer.NewTicker(time, triggerScheduledTick)
newTicker.payload = payload
newTicker.callback = callback
newTicker.expireAt = GetTime() + time
--debug
newTicker.path = debugstack()
--
return newTicker
end
--schedule a task with an interval of @time
function DF.Schedules.NewTimer(time, callback, ...)
local payload = {...}
local newTimer = C_Timer.NewTimer(time, triggerScheduledTick)
newTimer.payload = payload
newTimer.callback = callback
newTimer.expireAt = GetTime() + time
--debug
newTimer.path = debugstack()
--
return newTimer
end
--cancel an ongoing ticker
function DF.Schedules.Cancel(tickerObject)
--ignore if there's no ticker object
if (tickerObject) then
return tickerObject:Cancel()
end
end
--schedule a task with an interval of @time without payload
function DF.Schedules.After(time, callback)
C_Timer.After(time, callback)
end
function DF.Schedules.SetName(object, name)
object.name = name
end
function DF.Schedules.RunNextTick(callback)
return DF.Schedules.After(0, callback)
end
@@ -1,132 +0,0 @@
local detailsFramework = DetailsFramework
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local unpack = unpack
local CreateFrame = CreateFrame
local geterrorhandler = geterrorhandler
local wipe = wipe
local parseCodeForNamedLocalFunctions = function(codeBlock, startIndex, listOfFunctionsFound)
local nestedLevel = 0
local endIndex = startIndex
local currentQuote = ""
---@type number for the 'function' keyword, need to ignore the one that started the 'local function' capture
local ignoreFunctionIndex = startIndex + 6
---@type boolean
local bFoundEnd = false
---@type boolean
local bIsInString = false
---@type boolean
local bIsInComment = false
while (endIndex <= #codeBlock) do
local char = string.sub(codeBlock, endIndex, endIndex)
--check if the character is inside a comment
if (char == "-") then
local nextChar = string.sub(codeBlock, endIndex + 1, endIndex + 1)
if nextChar == "-" then
bIsInComment = true
end
elseif (char == "\n") then
bIsInComment = false
end
if (not bIsInComment) then
--check if it is inside a string
if (char == "'" or char == '"') then
if (not bIsInString) then
bIsInString = true
currentQuote = char
elseif (bIsInString and currentQuote == char) then
bIsInString = false
currentQuote = ""
end
end
if (not bIsInString) then
--check if the word starts with "i", "f", "d" or "e"
if (char == "i") then
local nextChars = string.sub(codeBlock, endIndex, endIndex + 1)
if (nextChars == "if") then
nestedLevel = nestedLevel + 1
end
elseif (char == "f") then
local nextChars = string.sub(codeBlock, endIndex, endIndex + 7)
--also check if the index isn't the one that started the 'local function' capture
if (nextChars == "function" and endIndex ~= ignoreFunctionIndex) then
nestedLevel = nestedLevel + 1
end
--for 'do' keyword, used by for and while and also by the 'do' keyword itself creating a block
elseif (char == "d") then
local nextChars = string.sub(codeBlock, endIndex, endIndex + 1)
if (nextChars == "do") then
nestedLevel = nestedLevel + 1
end
elseif (char == "e") then
local nextChars = string.sub(codeBlock, endIndex, endIndex + 2)
if (nextChars == "end") then
if (nestedLevel > 0) then
--reduce the nested level by 1
nestedLevel = nestedLevel - 1
else
--if the nested level is zero then the end of the function got found
bFoundEnd = true
endIndex = endIndex + 2 --adjust endIndex to include the 'end' keyword
break
end
end
end
end
end
endIndex = endIndex + 1
end
if (bFoundEnd) then
---@type string get the function body
local functionBody = string.sub(codeBlock, startIndex, endIndex)
table.insert(listOfFunctionsFound, functionBody)
return endIndex
end
end
---search a code block for named local functions and bring them to the top of the code block
---this is useful for when you want to call a function before it's defined
---same thing as been implemented in Lua 5.2 but not in WoW Lua
---@param codeBlock string
function detailsFramework:BringNamedLocalFunctionToTop(codeBlock)
---@type string[]
local listOfFunctionsFound = {}
---@type number|nil
local startIndex = string.find(codeBlock, "local function")
while startIndex do
startIndex = parseCodeForNamedLocalFunctions(codeBlock, startIndex, listOfFunctionsFound)
if (not startIndex) then
break
end
startIndex = string.find(codeBlock, "local function", startIndex + 1)
end
for i = #listOfFunctionsFound, 1, -1 do
local thisMatch = listOfFunctionsFound[i]
local blockStartIndex = thisMatch[2]
local blockEndIndex = thisMatch[3]
codeBlock = codeBlock:sub(1, blockStartIndex - 1) .. codeBlock:sub(blockEndIndex + 1)
end
for i = #listOfFunctionsFound, 1, -1 do
codeBlock = listOfFunctionsFound[i][1] .. "\n\n" .. codeBlock
end
end
@@ -1,233 +0,0 @@
--note: this scroll bar is using legacy code and shouldn't be used on creating new stuff
local DF = _G["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
function DF:CreateScrollBar(master, scrollContainer, x, y)
return DF:NewScrollBar(master, scrollContainer, x, y)
end
function DF:NewScrollBar(parent, scrollContainer, x, y)
local newSlider = CreateFrame("Slider", nil, parent, "BackdropTemplate")
newSlider.scrollMax = 560
newSlider:SetPoint("TOPLEFT", parent, "TOPRIGHT", x, y)
newSlider.ativo = true
newSlider.bg = newSlider:CreateTexture(nil, "BACKGROUND")
newSlider.bg:SetAllPoints(true)
newSlider.bg:SetTexture(0, 0, 0, 0)
newSlider.thumb = newSlider:CreateTexture(nil, "OVERLAY")
newSlider.thumb:SetTexture("Interface\\Buttons\\UI-ScrollBar-Knob")
newSlider.thumb:SetSize(29, 30)
newSlider:SetThumbTexture(newSlider.thumb)
newSlider:SetOrientation("VERTICAL")
newSlider:SetSize(16, 100)
newSlider:SetMinMaxValues(0, newSlider.scrollMax)
newSlider:SetValue(0)
newSlider.ultimo = 0
local upButton = CreateFrame("Button", nil, parent,"BackdropTemplate")
upButton:SetPoint("BOTTOM", newSlider, "TOP", 0, -12)
upButton.x = 0
upButton.y = -12
upButton:SetWidth(29)
upButton:SetHeight(32)
upButton:SetNormalTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Up")
upButton:SetPushedTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Down")
upButton:SetDisabledTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollUpButton-Disabled")
upButton:Show()
upButton:Disable()
local downDutton = CreateFrame("Button", nil, parent,"BackdropTemplate")
downDutton:SetPoint("TOP", newSlider, "BOTTOM", 0, 12)
downDutton.x = 0
downDutton.y = 12
downDutton:SetWidth(29)
downDutton:SetHeight(32)
downDutton:SetNormalTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Up")
downDutton:SetPushedTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Down")
downDutton:SetDisabledTexture("Interface\\BUTTONS\\UI-ScrollBar-ScrollDownButton-Disabled")
downDutton:Show()
downDutton:Disable()
parent.baixo = downDutton
parent.cima = upButton
parent.slider = newSlider
downDutton:SetScript("OnMouseDown", function(self)
if (not newSlider:IsEnabled()) then
return
end
local current = newSlider:GetValue()
local minValue, maxValue = newSlider:GetMinMaxValues()
if (current + 5 < maxValue) then
newSlider:SetValue(current + 5)
else
newSlider:SetValue(maxValue)
end
self.precionado = true
self.last_up = -0.3
self:SetScript("OnUpdate", function(self, elapsed)
self.last_up = self.last_up + elapsed
if (self.last_up > 0.03) then
self.last_up = 0
local current = newSlider:GetValue()
local minValue, maxValue = newSlider:GetMinMaxValues()
if (current + 2 < maxValue) then
newSlider:SetValue(current + 2)
else
newSlider:SetValue(maxValue)
end
end
end)
end)
downDutton:SetScript("OnMouseUp", function(self)
self.precionado = false
self:SetScript("OnUpdate", nil)
end)
upButton:SetScript("OnMouseDown", function(self)
if (not newSlider:IsEnabled()) then
return
end
local current = newSlider:GetValue()
if (current - 5 > 0) then
newSlider:SetValue(current - 5)
else
newSlider:SetValue(0)
end
self.precionado = true
self.last_up = -0.3
self:SetScript("OnUpdate", function(self, elapsed)
self.last_up = self.last_up + elapsed
if (self.last_up > 0.03) then
self.last_up = 0
local current = newSlider:GetValue()
if (current - 2 > 0) then
newSlider:SetValue(current - 2)
else
newSlider:SetValue(0)
end
end
end)
end)
upButton:SetScript("OnMouseUp", function(self)
self.precionado = false
self:SetScript("OnUpdate", nil)
end)
upButton:SetScript("OnEnable", function(self)
local current = newSlider:GetValue()
if (current == 0) then
upButton:Disable()
end
end)
newSlider:SetScript("OnValueChanged", function(self)
local current = self:GetValue()
parent:SetVerticalScroll(current)
local minValue, maxValue = newSlider:GetMinMaxValues()
if (current == minValue) then
upButton:Disable()
elseif (not upButton:IsEnabled()) then
upButton:Enable()
end
if (current == maxValue) then
downDutton:Disable()
elseif (not downDutton:IsEnabled()) then
downDutton:Enable()
end
end)
newSlider:SetScript("OnShow", function(self)
upButton:Show()
downDutton:Show()
end)
newSlider:SetScript("OnDisable", function(self)
upButton:Disable()
downDutton:Disable()
end)
newSlider:SetScript("OnEnable", function(self)
upButton:Enable()
downDutton:Enable()
end)
parent:SetScript("OnMouseWheel", function(self, delta)
if (not newSlider:IsEnabled()) then
return
end
local current = newSlider:GetValue()
if (delta < 0) then
local minValue, maxValue = newSlider:GetMinMaxValues()
if (current + (parent.wheel_jump or 20) < maxValue) then
newSlider:SetValue(current + (parent.wheel_jump or 20))
else
newSlider:SetValue(maxValue)
end
elseif (delta > 0) then
if (current + (parent.wheel_jump or 20) > 0) then
newSlider:SetValue(current - (parent.wheel_jump or 20))
else
newSlider:SetValue(0)
end
end
end)
function newSlider:Altura(height)
self:SetHeight(height)
end
function newSlider:Update(desativar)
if (desativar) then
newSlider:Disable()
newSlider:SetValue(0)
newSlider.ativo = false
parent:EnableMouseWheel(false)
return
end
self.scrollMax = scrollContainer:GetHeight() - parent:GetHeight()
if (self.scrollMax > 0) then
newSlider:SetMinMaxValues(0, self.scrollMax)
if (not newSlider.ativo) then
newSlider:Enable()
newSlider.ativo = true
parent:EnableMouseWheel(true)
end
else
newSlider:Disable()
newSlider:SetValue(0)
newSlider.ativo = false
parent:EnableMouseWheel(false)
end
end
function newSlider:cimaPoint(x, y)
upButton:SetPoint("BOTTOM", newSlider, "TOP", x, y - 12)
end
function newSlider:baixoPoint(x, y)
downDutton:SetPoint("TOP", newSlider, "BOTTOM", x, y + 12)
end
return newSlider
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -1,810 +0,0 @@
local DF = _G ["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
local _
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 maxStatusBarValue = 100000000
local cleanfunction = function() end
local APISplitBarFunctions
do
local metaPrototype = {
WidgetType = "split_bar",
dversion = DF.dversion,
}
--check if there's a metaPrototype already existing
if (_G[DF.GlobalWidgetControlNames["split_bar"]]) then
--get the already existing metaPrototype
local oldMetaPrototype = _G[DF.GlobalWidgetControlNames["split_bar"]]
--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["split_bar"]] = metaPrototype
end
end
local SplitBarMetaFunctions = _G[DF.GlobalWidgetControlNames["split_bar"]]
DF:Mixin(SplitBarMetaFunctions, DF.ScriptHookMixin)
------------------------------------------------------------------------------------------------------------
--metatables
SplitBarMetaFunctions.__call = function(_table, value)
if (not value) then
return _table.statusbar:GetValue()
else
_table.spark:SetPoint("left", _table.statusbar, "left", value * (_table.statusbar:GetWidth()/100) - 18, 0)
return _table.statusbar:SetValue(value)
end
end
SplitBarMetaFunctions.__add = function(v1, v2)
if (type(v1) == "table") then
local v = v1.statusbar:GetValue()
v = v + v2
v1.spark:SetPoint("left", v1.statusbar, "left", value * (v1.statusbar:GetWidth()/100) - 18, 0)
v1.statusbar:SetValue(v)
else
local v = v2.statusbar:GetValue()
v = v + v1
v2.spark:SetPoint("left", v2.statusbar, "left", value * (v2.statusbar:GetWidth()/100) - 18, 0)
v2.statusbar:SetValue(v)
end
end
SplitBarMetaFunctions.__sub = function(v1, v2)
if (type(v1) == "table") then
local v = v1.statusbar:GetValue()
v = v - v2
v1.spark:SetPoint("left", v1.statusbar, "left", value * (v1.statusbar:GetWidth()/100) - 18, 0)
v1.statusbar:SetValue(v)
else
local v = v2.statusbar:GetValue()
v = v - v1
v2.spark:SetPoint("left", v2.statusbar, "left", value * (v2.statusbar:GetWidth()/100) - 18, 0)
v2.statusbar:SetValue(v)
end
end
------------------------------------------------------------------------------------------------------------
--members
--tooltip
local function gmember_tooltip (_object)
return _object:GetTooltip()
end
--shown
local gmember_shown = function(_object)
return _object.statusbar:IsShown()
end
--frame width
local gmember_width = function(_object)
return _object.statusbar:GetWidth()
end
--frame height
local gmember_height = function(_object)
return _object.statusbar:GetHeight()
end
--value
local gmember_value = function(_object)
return _object.statusbar:GetValue()
end
--right text
local gmember_rtext = function(_object)
return _object.textright:GetText()
end
--left text
local gmember_ltext = function(_object)
return _object.textleft:GetText()
end
--right color
local gmember_rcolor = function(_object)
return _object.rightTexture.original_colors
end
--left color
local gmember_lcolor = function(_object)
return _object.texture.original_colors
end
--right icon
local gmember_ricon = function(_object)
return _object.iconright:GetTexture()
end
--left icon
local gmember_licon = function(_object)
return _object.iconleft:GetTexture()
end
--texture
local gmember_texture = function(_object)
return _object.texture:GetTexture()
end
--font size
local gmember_textsize = function(_object)
local _, fontsize = _object.textleft:GetFont()
return fontsize
end
--font face
local gmember_textfont = function(_object)
local fontface = _object.textleft:GetFont()
return fontface
end
--font color
local gmember_textcolor = function(_object)
return _object.textleft:GetTextColor()
end
SplitBarMetaFunctions.GetMembers = SplitBarMetaFunctions.GetMembers or {}
SplitBarMetaFunctions.GetMembers ["tooltip"] = gmember_tooltip
SplitBarMetaFunctions.GetMembers ["shown"] = gmember_shown
SplitBarMetaFunctions.GetMembers ["width"] = gmember_width
SplitBarMetaFunctions.GetMembers ["height"] = gmember_height
SplitBarMetaFunctions.GetMembers ["value"] = gmember_value
SplitBarMetaFunctions.GetMembers ["righttext"] = gmember_rtext
SplitBarMetaFunctions.GetMembers ["lefttext"] = gmember_ltext
SplitBarMetaFunctions.GetMembers ["rightcolor"] = gmember_rcolor
SplitBarMetaFunctions.GetMembers ["leftcolor"] = gmember_lcolor
SplitBarMetaFunctions.GetMembers ["righticon"] = gmember_ricon
SplitBarMetaFunctions.GetMembers ["lefticon"] = gmember_licon
SplitBarMetaFunctions.GetMembers ["texture"] = gmember_texture
SplitBarMetaFunctions.GetMembers ["fontsize"] = gmember_textsize
SplitBarMetaFunctions.GetMembers ["fontface"] = gmember_textfont
SplitBarMetaFunctions.GetMembers ["fontcolor"] = gmember_textcolor
SplitBarMetaFunctions.GetMembers ["textsize"] = gmember_textsize --alias
SplitBarMetaFunctions.GetMembers ["textfont"] = gmember_textfont --alias
SplitBarMetaFunctions.GetMembers ["textcolor"] = gmember_textcolor --alias
SplitBarMetaFunctions.__index = function(_table, _member_requested)
local func = SplitBarMetaFunctions.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 SplitBarMetaFunctions [_member_requested]
end
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--tooltip
local smember_tooltip = function(_object, _value)
return _object:SetTooltip (_value)
end
--show
local smember_shown = function(_object, _value)
if (_value) then
return _object:Show()
else
return _object:Hide()
end
end
--hide
local smember_hide = function(_object, _value)
if (_value) then
return _object:Hide()
else
return _object:Show()
end
end
--width
local smember_width = function(_object, _value)
return _object.statusbar:SetWidth(_value)
end
--height
local smember_height = function(_object, _value)
return _object.statusbar:SetHeight(_value)
end
--statusbar value
local smember_value = function(_object, _value)
_object.statusbar:SetValue(_value)
return _object.spark:SetPoint("left", _object.statusbar, "left", _value * (_object.statusbar:GetWidth()/100) - 18, 0)
end
--right text
local smember_rtext = function(_object, _value)
return _object.textright:SetText(_value)
end
--left text
local smember_ltext = function(_object, _value)
return _object.textleft:SetText(_value)
end
--right color
local smember_rcolor = function(_object, _value)
local _value1, _value2, _value3, _value4 = DF:ParseColors(_value)
_object.rightTexture.original_colors = {_value1, _value2, _value3, _value4}
return _object.rightTexture:SetVertexColor(_value1, _value2, _value3, _value4)
end
--left color
local smember_lcolor = function(_object, _value)
local _value1, _value2, _value3, _value4 = DF:ParseColors(_value)
_object.statusbar:SetStatusBarColor(_value1, _value2, _value3, _value4)
_object.texture.original_colors = {_value1, _value2, _value3, _value4}
return _object.texture:SetVertexColor(_value1, _value2, _value3, _value4)
end
--right icon
local smember_ricon = function(_object, _value)
if (type(_value) == "table") then
local _value1, _value2 = _unpack(_value)
_object.iconright:SetTexture(_value1)
if (_value2) then
_object.iconright:SetTexCoord(_unpack(_value2))
end
else
_object.iconright:SetTexture(_value)
end
return
end
--left icon
local smember_licon = function(_object, _value)
if (type(_value) == "table") then
local _value1, _value2 = _unpack(_value)
_object.iconleft:SetTexture(_value1)
if (_value2) then
_object.iconleft:SetTexCoord(_unpack(_value2))
end
else
_object.iconleft:SetTexture(_value)
end
return
end
--texture
local smember_texture = function(_object, _value)
if (type(_value) == "table") then
local _value1, _value2 = _unpack(_value)
_object.texture:SetTexture(_value1)
_object.rightTexture:SetTexture(_value1)
if (_value2) then
_object.texture:SetTexCoord(_unpack(_value2))
_object.rightTexture:SetTexCoord(_unpack(_value2))
end
else
_object.texture:SetTexture(_value)
_object.rightTexture:SetTexture(_value)
end
return
end
--font face
local smember_textfont = function(_object, _value)
DF:SetFontFace (_object.textleft, _value)
return DF:SetFontFace (_object.textright, _value)
end
--font size
local smember_textsize = function(_object, _value)
DF:SetFontSize(_object.textleft, _value)
return DF:SetFontSize(_object.textright, _value)
end
--font color
local smember_textcolor = function(_object, _value)
local _value1, _value2, _value3, _value4 = DF:ParseColors(_value)
_object.textleft:SetTextColor(_value1, _value2, _value3, _value4)
return _object.textright:SetTextColor(_value1, _value2, _value3, _value4)
end
SplitBarMetaFunctions.SetMembers = SplitBarMetaFunctions.SetMembers or {}
SplitBarMetaFunctions.SetMembers ["tooltip"] = smember_tooltip
SplitBarMetaFunctions.SetMembers ["shown"] = smember_shown
SplitBarMetaFunctions.SetMembers ["width"] = smember_width
SplitBarMetaFunctions.SetMembers ["height"] = smember_height
SplitBarMetaFunctions.SetMembers ["value"] = smember_value
SplitBarMetaFunctions.SetMembers ["righttext"] = smember_rtext
SplitBarMetaFunctions.SetMembers ["lefttext"] = smember_ltext
SplitBarMetaFunctions.SetMembers ["rightcolor"] = smember_rcolor
SplitBarMetaFunctions.SetMembers ["leftcolor"] = smember_lcolor
SplitBarMetaFunctions.SetMembers ["righticon"] = smember_ricon
SplitBarMetaFunctions.SetMembers ["lefticon"] = smember_licon
SplitBarMetaFunctions.SetMembers ["texture"] = smember_texture
SplitBarMetaFunctions.SetMembers ["fontsize"] = smember_textsize
SplitBarMetaFunctions.SetMembers ["fontface"] = smember_textfont
SplitBarMetaFunctions.SetMembers ["fontcolor"] = smember_textcolor
SplitBarMetaFunctions.SetMembers ["textsize"] = smember_textsize --alias
SplitBarMetaFunctions.SetMembers ["textfont"] = smember_textfont --alias
SplitBarMetaFunctions.SetMembers ["textcolor"] = smember_textcolor --alias
SplitBarMetaFunctions.__newindex = function(_table, _key, _value)
local func = SplitBarMetaFunctions.SetMembers [_key]
if (func) then
return func (_table, _value)
else
return rawset (_table, _key, _value)
end
end
------------------------------------------------------------------------------------------------------------
--methods
--show & hide
function SplitBarMetaFunctions:Show()
return self.statusbar:Show()
end
function SplitBarMetaFunctions:Hide()
return self.statusbar:Hide()
end
-- set split
function SplitBarMetaFunctions:SetSplit (value)
if (not value) then
value = self.statusbar:GetValue()
elseif (value < 0 or value > 100) then
return
end
self.statusbar:SetValue(value)
self.spark:SetPoint("left", self.statusbar, "left", value * (self.statusbar:GetWidth()/100) - 18, 0)
end
-- setpoint
function SplitBarMetaFunctions: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 SplitBarMetaFunctions:SetSize(w, h)
if (w) then
self.statusbar:SetWidth(w)
end
if (h) then
self.statusbar:SetHeight(h)
end
end
-- texture
function SplitBarMetaFunctions:SetTexture(texture)
self.rightTexture:SetTexture(texture)
self.texture:SetTexture(texture)
end
function SplitBarMetaFunctions:SetBackgroundTexture(texture)
self.background:SetTexture(texture)
end
-- texts
function SplitBarMetaFunctions:SetLeftText (text)
self.textleft:SetText(text)
end
function SplitBarMetaFunctions:SetRightText (text)
self.textright:SetText(text)
end
-- colors
function SplitBarMetaFunctions:SetLeftColor (r, g, b, a)
r, g, b, a = DF:ParseColors(r, g, b, a)
self.texture:SetVertexColor(r, g, b, a)
self.texture.original_colors = {r, g, b, a}
end
function SplitBarMetaFunctions:SetRightColor (r, g, b, a)
r, g, b, a = DF:ParseColors(r, g, b, a)
self.rightTexture:SetVertexColor(r, g, b, a)
self.rightTexture.original_colors = {r, g, b, a}
end
function SplitBarMetaFunctions:SetBackgroundColor (r, g, b, a)
r, g, b, a = DF:ParseColors(r, g, b, a)
self.background:SetVertexColor(r, g, b, a)
self.background.original_colors = {r, g, b, a}
end
function SplitBarMetaFunctions:GetLeftColor()
return self.texture:GetVertexColor()
end
function SplitBarMetaFunctions:GetRightColor()
return self.rightTexture:GetVertexColor()
end
-- icons
function SplitBarMetaFunctions:SetLeftIcon (texture, ...)
self.iconleft:SetTexture(texture)
if (...) then
local L, R, U, D = unpack(...)
self.iconleft:SetTexCoord(L, R, U, D)
end
end
function SplitBarMetaFunctions:SetRightIcon (texture, ...)
self.iconright:SetTexture(texture)
if (...) then
local L, R, U, D = unpack(...)
self.iconright:SetTexCoord(L, R, U, D)
end
end
-- tooltip
function SplitBarMetaFunctions:SetTooltip (tooltip)
if (tooltip) then
return rawset (self, "have_tooltip", tooltip)
else
return rawset (self, "have_tooltip", nil)
end
end
function SplitBarMetaFunctions:GetTooltip()
return rawget (self, "have_tooltip")
end
-- frame levels
function SplitBarMetaFunctions:GetFrameLevel()
return self.statusbar:GetFrameLevel()
end
function SplitBarMetaFunctions:SetFrameLevel(level, frame)
if (not frame) then
return self.statusbar:SetFrameLevel(level)
else
local framelevel = frame:GetFrameLevel (frame) + level
return self.statusbar:SetFrameLevel(framelevel)
end
end
-- frame stratas
function SplitBarMetaFunctions:SetFrameStrata(strata)
if (type(strata) == "table") then
self.statusbar:SetFrameStrata(strata:GetFrameStrata())
else
self.statusbar:SetFrameStrata(strata)
end
end
-- animation
--animation with acceleration ~animation ~healthbaranimation
local animateLeftWithAccel = function(self, deltaTime)
local currentPercent = DetailsFramework:GetRangePercent(self.targetValue, self.startValue, self.currentValue)
currentPercent = abs(currentPercent - 1)
currentPercent = min(0.9, currentPercent)
currentPercent = max(0.5, currentPercent)
local animationMultiplier = math.sin(currentPercent * math.pi)
local valueChange = self.step * (deltaTime * animationMultiplier)
self.currentValue = self.currentValue - valueChange
local barWidth = self:GetWidth()
self.currentValue = Clamp(self.currentValue, 0, maxStatusBarValue)
self.statusbar:SetValue(self.currentValue)
self.rightTexture:SetWidth(barWidth - barWidth*self.currentValue)
if (self.currentValue - 0.001 <= self.targetValue) then
self.targetValue = Clamp(self.targetValue, 0, maxStatusBarValue)
self:SetValue(self.targetValue)
self.currentValue = self.targetValue
if (not self.SparkAlwaysShow) then
self.spark:Hide()
end
self.widget:SetScript("OnUpdate", nil)
return
end
self.spark:SetPoint("center", self.widget, "left", self.currentValue * barWidth, 0)
self.spark:Show()
end
local animateRightWithAccel = function(self, deltaTime)
--get the animation elapsed percent
local currentPercent = DetailsFramework:GetRangePercent(self.startValue, self.targetValue, self.currentValue)
currentPercent = min(0.9, currentPercent) --slow down the animation but avoid very slow
currentPercent = max(0.5, currentPercent) --default: 0.1, using 0.5 makes the animation start fast and go slow
--get the sine value and scale time with it
local animationMultiplier = math.sin(currentPercent * math.pi)
local valueChange = self.step * (deltaTime * animationMultiplier)
self.currentValue = self.currentValue + valueChange
local barWidth = self:GetWidth()
self.currentValue = Clamp(self.currentValue, 0, maxStatusBarValue)
self.statusbar:SetValue(self.currentValue)
local rightTextureSize = barWidth - barWidth*self.currentValue
self.rightTexture:SetWidth(rightTextureSize)
if (self.currentValue + 0.001 >= self.targetValue) then
self.targetValue = Clamp(self.targetValue, 0, maxStatusBarValue)
self:SetValue(self.targetValue)
self.currentValue = self.targetValue
if (not self.SparkAlwaysShow) then
self.spark:Hide()
end
self.widget:SetScript("OnUpdate", nil)
return
end
self.spark:SetPoint("center", self.widget, "left", self.currentValue * barWidth, 0)
self.spark:Show()
end
local onUpdate = function(self, deltaTime)
self = self.MyObject
--select the animation function
--target is always equal to current
if (self.targetValue > self.currentValue) then
animateRightWithAccel(self, deltaTime)
else
animateLeftWithAccel(self, deltaTime)
end
end
function SplitBarMetaFunctions:EnableAnimations()
return
end
function SplitBarMetaFunctions:DisableAnimations()
self.widget:SetScript("OnUpdate", nil)
end
function SplitBarMetaFunctions:SetValueWithAnimation(value)
if (self.widget:GetScript("OnUpdate") == nil) then
self.widget:SetScript("OnUpdate", onUpdate)
self.widget:SetMinMaxValues(0, 1)
self.spark:ClearAllPoints()
self.spark:SetHeight(self:GetHeight() * 2.6)
self.spark:SetAlpha(0.4)
end
self.startValue = self.currentValue
self.step = abs(value - self.currentValue)
self.targetValue = value
self.rightTexture:Show()
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:AddLine(frame.MyObject.have_tooltip)
GameCooltip2:ShowCooltip(frame, "tooltip")
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
DF.popup: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 (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 (frame.MyObject.container.isMoving) then
frame.MyObject.container:StopMovingOrSizing()
frame.MyObject.container.isMoving = false
end
end
local OnSizeChanged = function(statusbar)
statusbar.MyObject.spark:SetPoint("left", statusbar, "left", statusbar:GetValue() * (statusbar:GetWidth()/100) - 18, 0)
statusbar.MyObject.rightTexture:SetWidth(statusbar:GetWidth() - statusbar.MyObject.texture:GetWidth())
end
------------------------------------------------------------------------------------------------------------
--object constructor
function DetailsFrameworkSplitlBar_OnCreate (self)
self.texture.original_colors = {1, 1, 1, 1}
self.rightTexture.original_colors = {.5, .5, .5, 1}
self.spark:SetPoint("left", self, "left", self:GetValue() * (self:GetWidth()/100) - 18, 0)
return true
end
function DF:CreateSplitBar(parent, width, height, member, name)
return DF:NewSplitBar(parent, nil, name, member, width, height)
end
local build_statusbar = function(self)
self:SetSize(300, 14)
self.background = self:CreateTexture("$parent_StatusBarBackground", "BACKGROUND")
self.background:SetPoint("topright", self, "topright")
self.background:SetPoint("bottomright", self, "bottomright")
self.background:SetPoint("topleft", self, "topleft")
self.background:SetPoint("bottomleft", self, "bottomleft")
self.background:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
self.background:SetVertexColor(.3, .3, .3, 1)
--this is the left texture and it grows to the right, it is embed within the bar by SetStatusBarTexture
self.texture = self:CreateTexture("$parent_StatusBarTexture", "ARTWORK", nil, 1)
self.texture:Hide()
self.texture:SetSize(300, 14)
self.texture:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
--this is the right texture and its size is the bar:GetWidth() - self.texture:GetWidth()
self.rightTexture = self:CreateTexture("$parent_StatusBarTextureRight", "ARTWORK", nil, 2)
self.rightTexture:Hide()
self.rightTexture:SetSize(300, 14)
self.rightTexture:SetTexture([[Interface\PaperDollInfoFrame\UI-Character-Skills-Bar]])
self.rightTexture:SetPoint("topright", self, "topright")
self.rightTexture:SetPoint("bottomright", self, "bottomright")
self.rightTexture:SetVertexColor(1, 0, 0)
self.lefticon = self:CreateTexture("$parent_IconLeft", "OVERLAY")
self.lefticon:SetSize(14, 14)
self.lefticon:SetPoint("LEFT", self, "LEFT")
self.righticon = self:CreateTexture("$parent_IconRight", "OVERLAY")
self.righticon:SetSize(14, 14)
self.righticon:SetPoint("RIGHT", self, "RIGHT")
self.spark = self:CreateTexture("$parent_Spark", "OVERLAY")
self.spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
self.spark:SetBlendMode("ADD")
self.spark:SetSize(32, 32)
self.spark:SetPoint("LEFT", self, "RIGHT", -17, -1)
self.lefttext = self:CreateFontString("$parent_TextLeft", "OVERLAY", "GameFontHighlight")
DF:SetFontSize(self.lefttext, 10)
self.lefttext:SetJustifyH("left")
self.lefttext:SetPoint("LEFT", self.lefticon, "RIGHT", 3, 0)
self.righttext = self:CreateFontString("$parent_TextRight", "OVERLAY", "GameFontHighlight")
DF:SetFontSize(self.righttext, 10)
self.righttext:SetJustifyH("right")
self.righttext:SetPoint("RIGHT", self.righticon, "LEFT", -3, 0)
self:SetStatusBarTexture(self.texture)
self:SetMinMaxValues(1, 100)
self:SetValue(50)
DetailsFrameworkSplitlBar_OnCreate (self)
end
function DF:NewSplitBar (parent, container, name, member, w, h)
if (not name) then
name = "DetailsFrameworkSplitbar" .. DF.SplitBarCounter
DF.SplitBarCounter = DF.SplitBarCounter + 1
end
if (not parent) then
return error("Details! FrameWork: parent not found.", 2)
end
if (not container) then
container = parent
end
if (name:find("$parent")) then
local parentName = DF.GetParentName(parent)
name = name:gsub("$parent", parentName)
end
local SplitBarObject = {type = "barsplit", dframework = true}
if (member) then
parent [member] = SplitBarObject
end
if (parent.dframework) then
parent = parent.widget
end
if (container.dframework) then
container = container.widget
end
--default members:
--misc
SplitBarObject.locked = false
SplitBarObject.container = container
SplitBarObject.currentValue = 0.5
--create widgets
SplitBarObject.statusbar = CreateFrame("statusbar", name, parent, "BackdropTemplate")
build_statusbar (SplitBarObject.statusbar)
SplitBarObject.spark = SplitBarObject.statusbar.spark
SplitBarObject.widget = SplitBarObject.statusbar
if (not APISplitBarFunctions) then
APISplitBarFunctions = true
local idx = getmetatable(SplitBarObject.statusbar).__index
for funcName, funcAddress in pairs(idx) do
if (not SplitBarMetaFunctions [funcName]) then
SplitBarMetaFunctions [funcName] = function(object, ...)
local x = loadstring ( "return _G['"..object.statusbar:GetName().."']:"..funcName.."(...)")
return x (...)
end
end
end
end
SplitBarObject.statusbar:SetHeight(h or 200)
SplitBarObject.statusbar:SetWidth(w or 14)
SplitBarObject.statusbar:SetValue(0.5)
SplitBarObject.statusbar.MyObject = SplitBarObject
SplitBarObject.textleft = _G [name .. "_TextLeft"]
SplitBarObject.textright = _G [name .. "_TextRight"]
SplitBarObject.iconleft = _G [name .. "_IconLeft"]
SplitBarObject.iconright = _G [name .. "_IconRight"]
SplitBarObject.background = _G [name .. "_StatusBarBackground"]
SplitBarObject.texture = _G [name .. "_StatusBarTexture"]
SplitBarObject.rightTexture = _G [name .. "_StatusBarTextureRight"]
--hooks
SplitBarObject.HookList = {
OnEnter = {},
OnLeave = {},
OnHide = {},
OnShow = {},
OnMouseDown = {},
OnMouseUp = {},
OnSizeChanged = {},
}
SplitBarObject.statusbar:SetScript("OnEnter", OnEnter)
SplitBarObject.statusbar:SetScript("OnLeave", OnLeave)
SplitBarObject.statusbar:SetScript("OnHide", OnHide)
SplitBarObject.statusbar:SetScript("OnShow", OnShow)
SplitBarObject.statusbar:SetScript("OnMouseDown", OnMouseDown)
SplitBarObject.statusbar:SetScript("OnMouseUp", OnMouseUp)
SplitBarObject.statusbar:SetScript("OnSizeChanged", OnSizeChanged)
setmetatable(SplitBarObject, SplitBarMetaFunctions)
return SplitBarObject
end
@@ -1,3 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ .. \FrameXML\UI.xsd">
<Script file="split_bar.lua"/>
</Ui>
@@ -1,422 +0,0 @@
local detailsFramework = DetailsFramework
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local unpack = unpack
local CreateFrame = CreateFrame
local PixelUtil = PixelUtil
---@class df_tabinfotable : {name: string, text: string}
---@class df_tabcontainer : frame
---@field AllFrames df_tabcontainerframe[]
---@field AllButtons df_tabcontainerbutton[]
---@field AllFramesByName table<string, df_tabcontainerframe>
---@field AllButtonsByName table<string, df_tabcontainerbutton>
---@field hookList table
---@field CurrentIndex number
---@field IsContainer boolean
---@field ButtonSelectedBorderColor table
---@field ButtonNotSelectedBorderColor table
---@field CanCloseWithRightClick boolean
---@field SetIndex fun(self: df_tabcontainer, index: number)
---@field SelectTabByIndex fun(self: df_tabcontainer, menuIndex: number)
---@field SelectTabByName fun(self: df_tabcontainer, name: string)
---@field CreateUnderlineGlow fun(button: button)
---@field OnShow fun(self: df_tabcontainer)
---@field GetTabFrameByName fun(self: df_tabcontainer, name: string): df_tabcontainerframe
---@field GetTabFrameByIndex fun(self: df_tabcontainer, index: number): df_tabcontainerframe
---@field GetTabButtonByName fun(self: df_tabcontainer, name: string): df_tabcontainerbutton
---@field GetTabButtonByIndex fun(self: df_tabcontainer, index: number): df_tabcontainerbutton
---@class df_tabcontainerframe : frame
---@field bIsFrontPage boolean
---@field titleText fontstring
---@field tabIndex number
---@field OnMouseDown fun(self: df_tabcontainerframe, button: string)
---@field OnMouseUp fun(self: df_tabcontainerframe, button: string)
---@field RefreshOptions fun(self: df_tabcontainerframe)|nil
---@class df_tabcontainerbutton : button
---@field selectedUnderlineGlow texture
---@field textsize number
---@field mainFrame df_tabcontainer
---@field leftSelectionIndicator texture
--create a template for the tab buttons
local tabTemplate = detailsFramework.table.copy({}, detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE"))
tabTemplate.backdropbordercolor = nil
detailsFramework.TabContainerMixin = {
---@param self df_tabcontainer
---@param tabIndex number
---@return df_tabcontainerframe
GetTabFrameByIndex = function(self, tabIndex)
return self.AllFrames[tabIndex]
end,
---@param self df_tabcontainer
---@param name string
---@return df_tabcontainerframe
GetTabFrameByName = function(self, name)
return self.AllFramesByName[name]
end,
---@param self df_tabcontainer
---@param tabIndex number
---@return df_tabcontainerbutton
GetTabButtonByIndex = function(self, tabIndex)
return self.AllButtons[tabIndex]
end,
---@param self df_tabcontainer
---@param name string
---@return df_tabcontainerbutton
GetTabButtonByName = function(self, name)
return self.AllButtonsByName[name]
end,
---@param self df_tabcontainer
---@param backdropTable backdrop|nil
---@param backdropColorTable table|string|nil
---@param backdropBorderColorTable table|string|nil
SetTabFramesBackdrop = function(self, backdropTable, backdropColorTable, backdropBorderColorTable)
for tabIndex, tabFrame in ipairs(self.AllFrames) do
if (backdropTable) then
tabFrame:SetBackdrop(backdropTable)
end
if (backdropColorTable) then
local r, g, b, a = detailsFramework:ParseColors(backdropColorTable)
tabFrame:SetBackdropColor(r, g, b, a)
end
if (backdropBorderColorTable) then
local r, g, b, a = detailsFramework:ParseColors(backdropColorTable)
tabFrame:SetBackdropBorderColor(r, g, b, a)
end
end
end,
---create a underglow texture for the selected tab, this texture is a small yellow bright gradient below the button
---@param self df_tabcontainerbutton
CreateUnderlineGlow = function(self)
local selectedGlow = self:CreateTexture(nil, "background", nil, -4)
selectedGlow:SetPoint("topleft", self["widget"], "bottomleft", -7, 0)
selectedGlow:SetPoint("topright", self["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()
self.selectedUnderlineGlow = selectedGlow
end,
---@param tabContainer df_tabcontainer
---@param menuIndex number
SelectTabByIndex = function(tabContainer, menuIndex)
---@type df_tabcontainerbutton
local tabButton = tabContainer.AllButtons[menuIndex]
---@type df_tabcontainerframe
local tabFrame = tabContainer.AllFrames[menuIndex]
--hide all tab frame and hide the selection glow from tab buttons
for i = 1, #tabContainer.AllFrames do
---@type df_tabcontainerframe
local thisTabFrame = tabContainer.AllFrames[i]
thisTabFrame:Hide()
---@type df_tabcontainerbutton
local thisTabButton = tabContainer.AllButtons[i]
if (tabContainer.ButtonNotSelectedBorderColor) then
thisTabButton:SetBackdropBorderColor(unpack(tabContainer.ButtonNotSelectedBorderColor))
end
if (thisTabButton.selectedUnderlineGlow) then
thisTabButton.selectedUnderlineGlow:Hide()
end
end
tabFrame:Show()
if (tabFrame.RefreshOptions) then
tabFrame:RefreshOptions()
end
if (tabContainer.ButtonSelectedBorderColor) then
tabButton:SetBackdropBorderColor(unpack(tabContainer.ButtonSelectedBorderColor))
end
if (tabButton.selectedUnderlineGlow) then
tabButton.selectedUnderlineGlow:Show()
end
tabContainer.CurrentIndex = menuIndex
if (tabContainer.hookList.OnSelectIndex) then
detailsFramework:QuickDispatch(tabContainer.hookList.OnSelectIndex, tabContainer, tabButton)
end
end,
---@param tabContainer df_tabcontainer
---@param name string
SelectTabByName = function(tabContainer, name)
---@type df_tabcontainerframe
local tabFrame = tabContainer.AllFramesByName[name]
if (tabFrame) then
local tabIndex = tabFrame.tabIndex
tabContainer:SelectTabByIndex(tabIndex)
else
error("df_tabcontainer:SelectTabByName(name): param #2 'name' not found within 'tabContainer.AllFramesByName'.")
end
end,
---@param self df_tabcontainer
---@param index number
SetIndex = function(self, index)
self.CurrentIndex = index
end,
---@param self df_tabcontainer
OnShow = function(self)
local index = self.CurrentIndex
self:SelectTabByIndex(index)
end
}
detailsFramework.TabContainerFrameMixin = {
---@param self df_tabcontainerframe
---@param button string
OnMouseDown = function(self, button)
--search for UIParent
---@type frame
local highestParent = detailsFramework:FindHighestParent(self)
local tabContainer = self:GetParent()
---@cast tabContainer df_tabcontainer
if (button == "LeftButton") then
if (not highestParent.IsMoving and highestParent:IsMovable()) then
highestParent:StartMoving()
highestParent.IsMoving = true
end
elseif (button == "RightButton") then
if (not highestParent.IsMoving and tabContainer.IsContainer) then
if (self.bIsFrontPage) then
if (tabContainer.CanCloseWithRightClick) then
if (highestParent["CloseFunction"]) then
highestParent["CloseFunction"](highestParent)
else
highestParent:Hide()
end
end
else
--goes back to front page
tabContainer:SelectTabByIndex(1)
end
end
end
end,
---@param self df_tabcontainerframe
---@param button string
OnMouseUp = function(self, button)
local frame = detailsFramework:FindHighestParent(self)
if (frame.IsMoving) then
frame:StopMovingOrSizing()
frame.IsMoving = false
end
end,
}
---creates a frame called tabContainer which is used as base for the tab container object
---the function receives a table called tabList which contains sub tables with two keys 'name' and 'text', name is the frame name and text is the text displayed on the button
---then the function iterate amongst the tabList and create a frame and a button for each entry using the value of the 'text' key as the text for the button and 'name' for the name of the frame
---when the user click on a button, the tabContainer hide all frames and show the frame which was created together with that button
---@param parent frame the parent frame
---@param title string a string to use as the title of the tab container, the title is always shown
---@param frameName string the frame name to pass into the CreateFrame function
---@param tabList df_tabinfotable[] the list of tabs to create, each entry has a 'name' and 'text' keys
---@param optionsTable {button_border_color: table, button_selected_border_color: table, right_click_y: number, hide_click_label: boolean, close_text_alpha: number, rightbutton_always_close: boolean, right_click_interact: boolean, y_offset: number, button_width: number, button_height: number, button_x: number, button_y: number, button_text_size: number, container_width_offset: number}|nil
---@param hookList table<string, function>|nil
---@param languageInfo any
---@return df_tabcontainer
function detailsFramework:CreateTabContainer(parent, title, frameName, tabList, optionsTable, hookList, languageInfo)
optionsTable = optionsTable or {}
local parentFrameWidth = parent:GetWidth()
local yOffset = optionsTable.y_offset or 0
local buttonWidth = optionsTable.button_width or 160
local buttonHeight = optionsTable.button_height or 20
local buttonAnchorX = optionsTable.button_x or 230
local buttonAnchorY = optionsTable.button_y or 0
local buttonTextSize = optionsTable.button_text_size or 10
local containerWidthOffset = optionsTable.container_width_offset or 0
--create the base frame
---@type df_tabcontainer
local tabContainer = CreateFrame("frame", frameName, parent["widget"] or parent, "BackdropTemplate")
tabContainer.hookList = hookList or {}
detailsFramework:Mixin(tabContainer, detailsFramework.TabContainerMixin)
--create the fontstring which show the title
---@type fontstring
local mainTitle = detailsFramework:CreateLabel(tabContainer, title, 24, "white")
mainTitle:SetPoint("topleft", tabContainer, "topleft", 10, -30 + yOffset)
tabContainer.AllFrames = {}
tabContainer.AllButtons = {}
tabContainer.AllFramesByName = {}
tabContainer.AllButtonsByName = {}
tabContainer.CurrentIndex = 1
tabContainer.IsContainer = true
tabContainer.ButtonSelectedBorderColor = optionsTable.button_selected_border_color or {1, 1, 0, 1}
tabContainer.ButtonNotSelectedBorderColor = optionsTable.button_border_color or {0, 0, 0, 0}
if (optionsTable.right_click_interact ~= nil) then
tabContainer.CanCloseWithRightClick = optionsTable.right_click_interact
else
tabContainer.CanCloseWithRightClick = true
end
--languageInfo
local addonId = languageInfo and languageInfo.language_addonId or "none"
for tabIndex, tabInfo in ipairs(tabList) do
--create a frame which will be shown when the tabButton is clicked
--when this tab isn't selected, this frame is hidden
---@type df_tabcontainerframe
local tabFrame = CreateFrame("frame", "$parent" .. tabInfo.name, tabContainer, "BackdropTemplate")
detailsFramework:Mixin(tabFrame, detailsFramework.TabContainerFrameMixin)
tabFrame:SetAllPoints()
tabFrame:SetFrameLevel(210)
tabFrame:SetScript("OnMouseDown", tabFrame.OnMouseDown)
tabFrame:SetScript("OnMouseUp", tabFrame.OnMouseUp)
tabFrame.tabIndex = tabIndex
tabFrame:Hide()
--attempt to get the localized text from the language system using the addonId and the frameInfo.text
local phraseId = tabInfo.text
local bIsLanguagePrahseID = detailsFramework.Language.DoesPhraseIDExistsInDefaultLanguage(addonId, phraseId)
--create the fontstring which show this tab text, this text is only shown when the tab is shown
local titleLabel = detailsFramework:CreateLabel(tabFrame, "", 16, "silver")
if (bIsLanguagePrahseID) then
DetailsFramework.Language.RegisterObjectWithDefault(addonId, titleLabel, tabInfo.text, tabInfo.text)
else
titleLabel:SetText(tabInfo.text)
end
titleLabel:SetPoint("topleft", mainTitle, "bottomleft", 0, 0)
tabFrame.titleText = titleLabel
---@type df_tabcontainerbutton
local tabButton = detailsFramework:CreateButton(tabContainer, function() tabContainer:SelectTabByIndex(tabIndex) end, buttonWidth, buttonHeight, tabInfo.text, tabIndex, nil, nil, nil, "$parentTabButton" .. tabInfo.name, false, tabTemplate)
PixelUtil.SetSize(tabButton, buttonWidth, buttonHeight)
tabButton:SetFrameLevel(220)
tabButton.textsize = buttonTextSize
tabButton.mainFrame = tabContainer
tabContainer.CreateUnderlineGlow(tabButton)
--register the fontstring with the language system
if (bIsLanguagePrahseID) then
DetailsFramework.Language.RegisterObjectWithDefault(addonId, tabButton["widget"], tabInfo.text, tabInfo.text)
end
local rightClickToBack
if (tabIndex == 1 or optionsTable.rightbutton_always_close) then
rightClickToBack = detailsFramework:CreateLabel(tabFrame, "right click to close", 10, "gray")
rightClickToBack:SetPoint("bottomright", tabFrame, "bottomright", -1, optionsTable.right_click_y or 0)
if (optionsTable.close_text_alpha) then
rightClickToBack:SetAlpha(optionsTable.close_text_alpha)
end
tabFrame.bIsFrontPage = true
else
rightClickToBack = detailsFramework:CreateLabel(tabFrame, "right click to go back to main menu", 10, "gray")
rightClickToBack:SetPoint("bottomright", tabFrame, "bottomright", -1, optionsTable.right_click_y or 0)
if (optionsTable.close_text_alpha) then
rightClickToBack:SetAlpha(optionsTable.close_text_alpha)
end
end
if (optionsTable.hide_click_label) then
rightClickToBack:Hide()
end
table.insert(tabContainer.AllFrames, tabFrame)
table.insert(tabContainer.AllButtons, tabButton)
tabContainer.AllFramesByName[tabInfo.name] = tabFrame
tabContainer.AllFramesByName[tabInfo.text] = tabFrame
tabContainer.AllButtonsByName[tabInfo.name] = tabButton
tabContainer.AllButtonsByName[tabInfo.text] = tabButton
end
--order buttons
local x = buttonAnchorX
local y = buttonAnchorY
local spaceBetweenButtons = 3
local allocatedSpaceForButtons = parentFrameWidth - ((#tabList - 2) * spaceBetweenButtons) - buttonAnchorX + containerWidthOffset
local amountButtonsPerRow = math.floor(allocatedSpaceForButtons / buttonWidth)
tabContainer.AllButtons[1]:SetPoint("topleft", mainTitle, "topleft", x, y)
x = x + buttonWidth + 2
for i = 2, #tabContainer.AllButtons do
local button = tabContainer.AllButtons[i]
PixelUtil.SetPoint(button, "topleft", mainTitle, "topleft", x, y)
x = x + buttonWidth + 2
if (i % amountButtonsPerRow == 0) then
x = buttonAnchorX
y = y - buttonHeight - 1
end
end
--when show the frame, reset to the current internal index
tabContainer:SetScript("OnShow", tabContainer.OnShow)
--select the first frame
local defaultTab = 1
tabContainer:SelectTabByIndex(defaultTab)
return tabContainer
end
--[=[example:
local parent = UIParent
local title = "My AddOn Options"
local frameName = "MyAddOnOptionsFrame"
local tabList = {
{name = "GeneralSettings", text = "General Settings"},
{name = "AdvancedSettings", text = "Advanced Settings"},
{name = "AboutTheAddon", text = "Addon Info"},
}
local optionsTable = {}
local hookList = {}
local languageInfo = {language_addonId = "MyAddOnTocName"}
local tabContainer = DetailsFramework:CreateTabContainer(parent, title, frameName, tabList, optionsTable, hookList, languageInfo)
tabContainer:SetPoint("center", UIParent, "center", 0, 0)
tabContainer:SetSize(750, 450)
tabContainer:Show()
--ways for getting a tab frame and start to create widgets inside it
local tabIndex = 1
local generalSettingsTabFrame = tabContainer:GetTabFrameByIndex(tabIndex) --using a tabIndex
local advancedSettingsTabFrame = tabContainer:GetTabFrameByName("Advanced Settings") --using the tab text
local aboutTabFrame = tabContainer:GetTabFrameByName("AboutTheAddon") --using the tab name
--clicking on tab buttons will automatically show the tab frame, to select a tab frame without clicking on the button, use:
tabContainer:SelectTabByIndex(tabIndex) --using a tabIndex
tabContainer:SelectTabByName("Advanced Settings") --using the tab text
tabContainer:SelectTabByName("AdvancedSettings") --using the tab name
--modify the background color by applying a backdrop
local backdropTable = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}
local backdropColor = {DetailsFramework:GetDefaultBackdropColor()}
local backdropBorderColor = {0, 0, 0, 1}
tabContainer:SetTabFramesBackdrop(backdropTable, backdropColor, backdropBorderColor)
--]=]
File diff suppressed because it is too large Load Diff
@@ -1,3 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
<Script file="textentry.lua"/>
</Ui>
@@ -1,462 +0,0 @@
local DF = _G["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
end
local _
local type = type
local floor = math.floor
local GetTime = GetTime
local APITimeBarFunctions
do
local metaPrototype = {
WidgetType = "timebar",
dversion = DF.dversion,
}
--check if there's a metaPrototype already existing
if (_G[DF.GlobalWidgetControlNames["timebar"]]) then
--get the already existing metaPrototype
local oldMetaPrototype = _G[DF.GlobalWidgetControlNames["timebar"]]
--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["timebar"]] = metaPrototype
end
end
local TimeBarMetaFunctions = _G[DF.GlobalWidgetControlNames["timebar"]]
DF:Mixin(TimeBarMetaFunctions, DF.ScriptHookMixin)
--methods
TimeBarMetaFunctions.SetMembers = TimeBarMetaFunctions.SetMembers or {}
TimeBarMetaFunctions.GetMembers = TimeBarMetaFunctions.GetMembers or {}
TimeBarMetaFunctions.__index = function(table, key)
local func = TimeBarMetaFunctions.GetMembers[key]
if (func) then
return func(table, key)
end
local fromMe = rawget(table, key)
if (fromMe) then
return fromMe
end
return TimeBarMetaFunctions[key]
end
TimeBarMetaFunctions.__newindex = function(table, key, value)
local func = TimeBarMetaFunctions.SetMembers[key]
if (func) then
return func(table, value)
else
return rawset(table, key, value)
end
end
--scripts
local OnEnterFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnEnter", statusBar, statusBar.MyObject)
if (kill) then
return
end
if (statusBar.MyObject.tooltip) then
GameCooltip2:Reset()
GameCooltip2:AddLine(statusBar.MyObject.tooltip)
GameCooltip2:ShowCooltip(statusBar, "tooltip")
end
end
local OnLeaveFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnLeave", statusBar, statusBar.MyObject)
if (kill) then
return
end
if (statusBar.MyObject.tooltip) then
GameCooltip2:Hide()
end
end
local OnHideFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnHide", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
local OnShowFunc = function(statusBar)
local kill = statusBar.MyObject:RunHooksForWidget("OnShow", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
local OnMouseDownFunc = function(statusBar, mouseButton)
local kill = statusBar.MyObject:RunHooksForWidget("OnMouseDown", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
local OnMouseUpFunc = function(statusBar, mouseButton)
local kill = statusBar.MyObject:RunHooksForWidget("OnMouseUp", statusBar, statusBar.MyObject)
if (kill) then
return
end
end
--timer functions
function TimeBarMetaFunctions:SetIconSize(width, height)
if (width and not height) then
self.statusBar.icon:SetWidth(width)
elseif (not width and height) then
self.statusBar.icon:SetHeight(height)
elseif (width and height) then
self.statusBar.icon:SetSize(width, height)
end
end
function TimeBarMetaFunctions:SetIcon(texture, L, R, T, B)
if (texture) then
self.statusBar.icon:Show()
self.statusBar.icon:SetPoint("left", self.statusBar, "left", 2, 0)
self.statusBar.icon:SetSize(self.statusBar:GetHeight()-2, self.statusBar:GetHeight()-2)
self.statusBar.leftText:ClearAllPoints()
self.statusBar.leftText:SetPoint("left", self.statusBar.icon, "right", 2, 0)
self.statusBar.icon:SetTexture(texture)
if (L) then
self.statusBar.icon:SetTexCoord(L, R, T, B)
end
else
self.statusBar.icon:Hide()
self.statusBar.leftText:ClearAllPoints()
self.statusBar.leftText:SetPoint("left", self.statusBar, "left", 2, 0)
end
end
function TimeBarMetaFunctions:GetIcon()
return self.statusBar.icon
end
function TimeBarMetaFunctions:SetTexture(texture)
self.statusBar.barTexture:SetTexture(texture)
end
function TimeBarMetaFunctions:SetColor(color, green, blue, alpha)
local r, g, b, a = DF:ParseColors(color, green, blue, alpha)
self.statusBar.barTexture:SetVertexColor(r, g, b, a)
end
function TimeBarMetaFunctions:SetLeftText(text)
self.statusBar.leftText:SetText(text)
end
function TimeBarMetaFunctions:SetRightText(text)
self.statusBar.rightText:SetText(text)
end
function TimeBarMetaFunctions:SetFont(font, size, color, shadow)
if (font) then
DF:SetFontFace(self.statusBar.leftText, font)
end
if (size) then
DF:SetFontSize(self.statusBar.leftText, size)
end
if (color) then
DF:SetFontColor(self.statusBar.leftText, color)
end
if (shadow) then
DF:SetFontOutline(self.statusBar.leftText, shadow)
end
end
function TimeBarMetaFunctions:SetThrottle(seconds)
if (seconds and seconds > 0) then
self.statusBar.isUsingThrottle = true
self.statusBar.amountThrottle = seconds
else
self.statusBar.isUsingThrottle = false
end
end
function TimeBarMetaFunctions:SetDirection(direction)
direction = direction or "right"
self.direction = direction
end
function TimeBarMetaFunctions:HasTimer()
return self.statusBar.hasTimer
end
function TimeBarMetaFunctions:StopTimer()
if (self.statusBar.hasTimer) then
self.statusBar.hasTimer = nil
local kill = self:RunHooksForWidget("OnTimerEnd", self.statusBar, self)
if (kill) then
return
end
end
local statusBar = self.statusBar
statusBar:SetScript("OnUpdate", nil)
statusBar:SetMinMaxValues(0, 100)
statusBar:SetValue(100)
statusBar.rightText:SetText("")
statusBar.spark:Hide()
end
function TimeBarMetaFunctions:ShowSpark(state, alpha, color)
if (type(state) == "boolean" and state == false) then
self.statusBar.dontShowSpark = true
else
self.statusBar.dontShowSpark = nil
end
if (alpha) then
self.statusBar.sparkAlpha = alpha
else
self.statusBar.sparkAlpha = nil
end
if (color) then
local r, g, b = DF:ParseColors(color)
if (r and g and b) then
self.statusBar.sparkColorR = r
self.statusBar.sparkColorG = g
self.statusBar.sparkColorB = b
end
else
self.statusBar.sparkColorR = nil
self.statusBar.sparkColorG = nil
self.statusBar.sparkColorB = nil
end
end
local OnUpdateFunc = function(self, deltaTime)
if (self.isUsingThrottle) then
self.throttle = self.throttle + deltaTime
if (self.throttle < self.amountThrottle) then
return
end
self.throttle = 0
end
local timeNow = GetTime()
self:SetValue(timeNow)
--adjust the spark
local spark = self.spark
local startTime, endTime = self:GetMinMaxValues()
if (not self.dontShowSpark) then
if (self.direction == "right") then
local pct = abs((timeNow - endTime) / (endTime - startTime))
pct = abs(1 - pct)
spark:SetPoint("left", self, "left", (self:GetWidth() * pct) - 16, 0)
spark:Show()
else
spark:SetPoint("right", self, "right", self:GetWidth() * (timeNow/self.endTime), 0)
end
end
local timeLeft = floor(endTime - timeNow)
local formatedTimeLeft = DF:IntegerToTimer(timeLeft)
self.rightText:SetText(formatedTimeLeft)
--check if finished
if (timeNow >= self.endTime) then
self.MyObject:StopTimer()
end
end
function TimeBarMetaFunctions:SetTimer(currentTime, startTime, endTime)
self.statusBar:Show()
if (not currentTime or currentTime == 0) then
self:StopTimer()
return
end
if (startTime and endTime) then
if (self.statusBar.hasTimer and currentTime == self.statusBar.timeLeft1) then
--it is the same timer called again
return
end
self.statusBar.startTime = startTime
self.statusBar.endTime = endTime
else
local bForceNewTimer = type(startTime) == "boolean" and startTime
if (self.statusBar.hasTimer and currentTime == self.statusBar.timeLeft2 and not bForceNewTimer) then
--it is the same timer called again
return
end
self.statusBar.startTime = GetTime()
self.statusBar.endTime = GetTime() + currentTime
self.statusBar.timeLeft2 = currentTime
end
self.statusBar:SetMinMaxValues(self.statusBar.startTime, self.statusBar.endTime)
if (self.direction == "right") then
self.statusBar:SetReverseFill(false)
else
self.statusBar:SetReverseFill(true)
end
if (self.statusBar.dontShowSpark) then
self.statusBar.spark:Hide()
else
self.statusBar.spark:Show()
self.statusBar.spark:SetHeight(self.statusBar:GetHeight()+20)
if (self.statusBar.sparkAlpha) then
self.statusBar.spark:SetAlpha(self.statusBar.sparkAlpha)
else
self.statusBar.spark:SetAlpha(1)
end
if (self.statusBar.sparkColorR) then
self.statusBar.spark:SetVertexColor(self.statusBar.sparkColorR, self.statusBar.sparkColorG, self.statusBar.sparkColorB)
else
self.statusBar.spark:SetVertexColor(1, 1, 1)
end
end
self.statusBar.hasTimer = true
self.statusBar.direction = self.direction
self.statusBar.throttle = 0
self.statusBar:SetScript("OnUpdate", OnUpdateFunc)
local kill = self:RunHooksForWidget("OnTimerStart", self.statusBar, self)
if (kill) then
return
end
end
function DF:CreateTimeBar(parent, texture, width, height, value, member, name)
if (not name) then
name = "DetailsFrameworkBarNumber" .. DF.BarNameCounter
DF.BarNameCounter = DF.BarNameCounter + 1
elseif (not parent) then
return error("Details! FrameWork: parent not found.", 2)
end
if (name:find("$parent")) then
local parentName = DF.GetParentName(parent)
name = name:gsub("$parent", parentName)
end
local timeBar = {
type = "timebar",
dframework = true
}
if (member) then
parent[member] = timeBar
end
if (parent.dframework) then
parent = parent.widget
end
value = value or 0
width = width or 150
height = height or 14
timeBar.locked = false
timeBar.statusBar = CreateFrame("statusbar", name, parent, "BackdropTemplate")
timeBar.widget = timeBar.statusBar
DF:Mixin(timeBar.statusBar, DF.WidgetFunctions)
timeBar.statusBar.MyObject = timeBar
timeBar.direction = "right"
if (not APITimeBarFunctions) then
APITimeBarFunctions = true
local idx = getmetatable(timeBar.statusBar).__index
for funcName, funcAddress in pairs(idx) do
if (not TimeBarMetaFunctions[funcName]) then
TimeBarMetaFunctions[funcName] = function(object, ...)
local x = loadstring("return _G['"..object.statusBar:GetName().."']:"..funcName.."(...)")
return x(...)
end
end
end
end
--create widgets
timeBar.statusBar:SetWidth(width)
timeBar.statusBar:SetHeight(height)
timeBar.statusBar:SetFrameLevel(parent:GetFrameLevel()+1)
timeBar.statusBar:SetMinMaxValues(0, 100)
timeBar.statusBar:SetValue(value or 100)
timeBar.statusBar:EnableMouse(false)
timeBar.statusBar.backgroundTexture = timeBar.statusBar:CreateTexture(nil, "border")
timeBar.statusBar.backgroundTexture:SetColorTexture(.1, .1, .1, .6)
timeBar.statusBar.backgroundTexture:SetAllPoints()
timeBar.statusBar.barTexture = timeBar.statusBar:CreateTexture(nil, "artwork")
timeBar.statusBar.barTexture:SetTexture(texture or [[Interface\WorldStateFrame\WORLDSTATEFINALSCORE-HIGHLIGHT]])
timeBar.statusBar:SetStatusBarTexture(timeBar.statusBar.barTexture)
timeBar.statusBar.spark = timeBar.statusBar:CreateTexture(nil, "overlay", nil, 7)
timeBar.statusBar.spark:SetTexture([[Interface\CastingBar\UI-CastingBar-Spark]])
timeBar.statusBar.spark:SetBlendMode("ADD")
timeBar.statusBar.spark:Hide()
timeBar.statusBar.icon = timeBar.statusBar:CreateTexture(nil, "overlay", nil, 5)
timeBar.statusBar.icon:SetPoint("left", timeBar.statusBar, "left", 2, 0)
timeBar.statusBar.leftText = timeBar.statusBar:CreateFontString("$parentLeftText", "overlay", "GameFontNormal", 4)
timeBar.statusBar.leftText:SetPoint("left", timeBar.statusBar.icon, "right", 2, 0)
timeBar.statusBar.rightText = timeBar.statusBar:CreateFontString(nil, "overlay", "GameFontNormal", 4)
timeBar.statusBar.rightText:SetPoint("right", timeBar.statusBar, "right", -2, 0)
timeBar.statusBar.rightText:SetJustifyH("left")
--hooks
timeBar.HookList = {
OnEnter = {},
OnLeave = {},
OnHide = {},
OnShow = {},
OnMouseDown = {},
OnMouseUp = {},
OnTimerStart = {},
OnTimerEnd = {},
}
timeBar.statusBar:SetScript("OnEnter", OnEnterFunc)
timeBar.statusBar:SetScript("OnLeave", OnLeaveFunc)
timeBar.statusBar:SetScript("OnHide", OnHideFunc)
timeBar.statusBar:SetScript("OnShow", OnShowFunc)
timeBar.statusBar:SetScript("OnMouseDown", OnMouseDownFunc)
timeBar.statusBar:SetScript("OnMouseUp", OnMouseUpFunc)
--set class
setmetatable(timeBar, TimeBarMetaFunctions)
return timeBar
end
@@ -1,2 +0,0 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/..\FrameXML\UI.xsd">
</Ui>
@@ -1,24 +0,0 @@
local DetailsFramework = _G["DetailsFramework"]
if (not DetailsFramework or not DetailsFrameworkCanLoad) then
return
end
local _
local DF = DetailsFramework
--backdrop namespace
DF.BackdropUtil = {}
function DF.BackdropUtil:SetColorStripe(frame, index, backdrop, color1, color2)
if (backdrop == nil or type(backdrop) == "table") then
frame:SetBackdrop(backdrop and {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
end
if (index % 2 == 0) then
local r, g, b, a = DF:ParseColors(color1 or {.2, .2, .2, 0.5})
frame:SetBackdropColor(r, g, b, a)
else
local r, g, b, a = DF:ParseColors(color2 or {.3, .3, .3, 0.5})
frame:SetBackdropColor(r, g, b, a)
end
end