Framework Update

This commit is contained in:
Tercio Jose
2023-10-11 20:44:19 -03:00
parent 0cca378d2b
commit ac21f315a3
28 changed files with 4104 additions and 2989 deletions
+53
View File
@@ -0,0 +1,53 @@
--[=[
for this example, let's consider the name of your addon is "Slice And Dance"
addon folder name on World of Warcraft/_retail_/Interface/AddOns/SliceAndDance/
toc file example /World of Warcraft/_retail_/Interface/AddOns/SliceAndDance/SliceAndDance.toc:
## Interface: 100107
## Title: "Slice And Dance"
## Notes: Show a slice and dice bar for rogues
## SavedVariables: SliceAndDanceDatabase
SliceAndDance_Core.lua
--]=]
--create a new file on your addon folder called "SliceAndDance_Core.lua"
--this are the contents to add to the file
--each file of your addon receives a payload with the addon name and a private table
--this private table is shared between all files of your addon and cannot be accessed by other addons or scripts
--the addon name is the ToC name of your addon, the toc is also the folder name of your addon in the addons folder
local addonName, priviteTable = ...
--saved variables name
--this is the name of the global table where your addon will store it's saved variables
--you define this on the addon.toc file under the line "## SavedVariables: SliceAndDanceDatabase"
local savedVariablesName = "SliceAndDanceDatabase"
--default settings
--a simple table with default settings for your addon, any value modified by the user will be stored in the saved variables table
--if your addon doesn't have any settings, you can just pass an empty table
local defaultSettingsExample = {
width = 500,
height = 500,
name = "John",
}
local detailsFramework = DetailsFramework
--create the core addon object, this is a table which will all public functions of your addon
local myNewAddonObject = detailsFramework:CreateNewAddOn(addonName, savedVariablesName, defaultSettingsExample)
--by default, the table generated by the CreateNewAddOn() isn't placed in the global environment
--if this is desired for some reason, you can do it manually
_G.MyNewAddon = myNewAddonObject
--this function is called when the savedVariables of your addon is ready to be used
function myNewAddonObject.OnLoad(self, profile)
--self is: myNewAddonObject
--profile is a table with defaultSettingsExample
end
--this function is called when when the loading screen is done and the player character is ready to play
function myNewAddonObject.OnInit(self, profile) --fired from detailsFramework at PLAYER_LOGIN
--self is: myNewAddonObject
--profile is a table with defaultSettingsExample
end
+1 -1
View File
@@ -119,7 +119,7 @@ function detailsFramework:CreateNewAddOn(addonName, globalSavedVariablesName, sa
end
--old create addon
--old create addon using ace3
function detailsFramework: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")
+488 -496
View File
File diff suppressed because it is too large Load Diff
+9 -4
View File
@@ -382,6 +382,7 @@ detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.ScriptHookMixin)
end
---add an icon to the left of the button text
---short method truncates the text: false = do nothing, nil = increate the button width, 1 = decrease the font size, 2 = truncate the text
---@param texture any
---@param width number|nil
---@param height number|nil
@@ -464,6 +465,9 @@ detailsFramework:Mixin(ButtonMetaFunctions, detailsFramework.ScriptHookMixin)
textSize = textSize - 1
end
end
elseif (shortMethod == 2) then
detailsFramework:TruncateText(self.button.text, self:GetWidth() - self.icon:GetWidth() - 15)
end
end
end
@@ -810,8 +814,8 @@ end
--object constructor
local onDisableFunc = function(self)
self.texture_disabled:Show()
self.texture_disabled:SetVertexColor(0, 0, 0)
self.texture_disabled:SetAlpha(.5)
self.texture_disabled:SetVertexColor(0.1, 0.1, 0.1)
self.texture_disabled:SetAlpha(.834)
end
local onEnableFunc = function(self)
@@ -836,7 +840,7 @@ end
self:SetScript("OnEnable", onEnableFunc)
end
---@class df_button : button
---@class df_button : button, df_scripthookmixin
---@field widget button
---@field tooltip string
---@field shown boolean
@@ -852,13 +856,14 @@ end
---@field textcolor any
---@field textfont string
---@field textsize number
---@field icon texture created after calling SetIcon()
---@field SetTemplate fun(self: df_button, template: table) set the button visual by a template
---@field RightClick fun(self: df_button) right click the button executing its right click function
---@field Exec fun(self: df_button) execute the button function for the left button
---@field Disable fun(self: df_button) disable the button
---@field Enable fun(self: df_button) enable the button
---@field IsEnabled fun(self: df_button) : boolean returns true if the button is enabled
---@field SetIcon fun(self: df_button,texture: string, width: number|nil, height: number|nil, layout: string|nil, texcoord: table|nil, overlay: table|nil, textDistance: number|nil, leftPadding: number|nil, textHeight: number|nil, shortMethod: any|nil)
---@field SetIcon fun(self: df_button,texture: string|number, width: number|nil, height: number|nil, layout: string|nil, texcoord: table|nil, overlay: table|nil, textDistance: number|nil, leftPadding: number|nil, textHeight: number|nil, shortMethod: any|nil)
---@field GetIconTexture fun(self: df_button) : string returns the texture path of the button icon
---@field SetTexture fun(self: df_button, normalTexture: string, highlightTexture: string, pressedTexture: string, disabledTexture: string) set the regular button textures
---@field SetFontFace fun(self: df_button, font: string) set the button font
+7 -8
View File
@@ -1,13 +1,12 @@
do
do
local DF = _G ["DetailsFramework"]
if (not DF or not DetailsFrameworkCanLoad) then
return
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},
@@ -172,13 +171,13 @@ do
["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
DF.alias_text_colors[colorName] = colorTable
end
end
+17 -2
View File
@@ -23,9 +23,14 @@
---@field RoundedCornerPanelMixin df_roundedcornermixin
---@field Schedules df_schedule
---@field HeaderFunctions df_headerfunctions
---@field KeybindMixin df_keybindmixin
---@field Math df_math
---@field table df_table_functions
---@field IsValidSpecId fun(self:table, specId:number):boolean check if the passed specId is valid for the player class, also return false for tutorial specs
---@field DebugVisibility fun(self:table, object:uiobject) print the reason why the frame isn't shown in the screen
---@field Dispatch fun(self:table, callback:function, ...) : any dispatch a function call using xpcall
---@field QuickDispatch fun(self:table, callback:function, ...) : any dispatch a function call without errors if the function passed is invalid
---@field CoreDispatch fun(self:table, context:string, callback:function, ...) : any deprecated at this point, use Dispatch instead
---@field GetDefaultBackdropColor fun(self:table) : red, green, blue, alpha return the standard backdrop color used by blizzard on their own frames
---@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
@@ -64,7 +69,17 @@
---@field NewColor fun(self:table, colorName:string, red:number, green:number, blue:number, alpha:number)
---@field CreateKeybindFrame fun(self:table, parent:frame, name:string?, options:table?, setKeybindCallback:function?, keybindData:table?) : df_keybindframe
---@field CreateStatusBar fun(self:table, parent:frame, options:table?) : frame
---@field CreateScrollBox fun(self:table, parent:frame, name:string, refreshFunc:function, data:table, width:number, height:number, lineAmount:number, lineHeight:number, createLineFunc:function?, autoAmount:boolean?, noScroll:boolean?) : df_scrollbox
---@field CreateScrollBox fun(self:table, parent:frame, name:string, refreshFunc:function, data:table, width:number, height:number, lineAmount:number, lineHeight:number, createLineFunc:function?, autoAmount:boolean?, noScroll:boolean?, noBackdrop:boolean?) : df_scrollbox
---@field GetTemplate fun(self:table, templateType:templatetype, templateName:string) : table
---@field UpdateLoadConditionsTable fun(self:table, loadConditionsTable:table)
---@field IconPick fun(self:table, callback:function, bCloseWhenSelect:boolean?, param1:any?, param2:any?)
---@field OpenLoadConditionsPanel fun(self:table, optionsTable:table, callback:function, frameOptions:table?)
---@field InstallTemplate fun(self:table, widgetType:string, templateName:string, template:table, parentName:any) : table
---@field NewSpecialLuaEditorEntry fun(self:table, parent:frame, width:number, height:number, member:string?, name:string?, nointent:boolean?, showLineNumbers:boolean?, bNoName:boolean?) : df_luaeditor
---@field PassLoadFilters fun(self:table, loadTable:table, encounterID:number?) : boolean, string
---@field CreateLoadFilterParser fun(self:table, callback:fun(encounterId:number?)) create a helper which will callback when encounterId, spec, talent, role, combatstate changes
---@field CreateSwitch fun(self:table, parent:frame, onSwitch:function, defaultValue:boolean, width:number?, height:number?, leftText:string?, rightText:string?, member:string?, name:string?, colorInverted:boolean?, switchFunc:function?, returnFunc:function?, withLabel:string?, switch_template:table?, label_template:table?) : df_checkbox, df_label?
---@field CreateCheckboxGroup fun(self:table, parent:frame, radioOptions:df_radiooptions[], name:string?, options:table?, anchorOptions:table?) : df_checkboxgroup
---@field CreateRadioGroup fun(self:table, parent:frame, radioOptions:df_radiooptions[], name:string?, options:table?, anchorOptions:table?) : df_radiogroup
---@field
---@field
+1 -1
View File
@@ -1334,7 +1334,7 @@ function DF:CreateNewDropdownFrame(parent, name)
child.mouseover = mouseover
scroll:SetScrollChild(child)
tinsert(UISpecialFrames, newDropdownFrame.dropdownborder:GetName())
table.insert(UISpecialFrames, newDropdownFrame.dropdownborder:GetName())
--tinsert(UISpecialFrames, f.dropdownframe:GetName()) --not adding this solves an issue with ConsolePort addon and stackoverflows on Hide...
return newDropdownFrame
+148 -21
View File
@@ -1,6 +1,6 @@
local dversion = 470
local dversion = 474
local major, minor = "DetailsFramework-1.0", dversion
local DF, oldminor = LibStub:NewLibrary(major, minor)
@@ -19,7 +19,7 @@ local type = type
local unpack = unpack
local upper = string.upper
local string_match = string.match
local tinsert = _G.tinsert
local tinsert = table.insert
local abs = _G.abs
local tremove = _G.tremove
@@ -1434,6 +1434,45 @@ function DF:GetSpellBookSpells()
return spellNamesInSpellBook, spellIdsInSpellBook
end
---return a table of passive talents, format: [spellId] = true
---@return {Name: string, ID: number, Texture: any, IsSelected: boolean}[]
function DF:GetAllTalents()
local allTalents = {}
local configId = C_ClassTalents.GetActiveConfigID()
if (configId) then
local configInfo = C_Traits.GetConfigInfo(configId)
--get the spells from the SPEC from talents
for treeIndex, treeId in ipairs(configInfo.treeIDs) do
local treeNodes = C_Traits.GetTreeNodes(treeId)
for nodeIdIndex, treeNodeID in ipairs(treeNodes) do
local traitNodeInfo = C_Traits.GetNodeInfo(configId, treeNodeID)
if (traitNodeInfo) then
local activeEntry = traitNodeInfo.activeEntry
local entryIds = traitNodeInfo.entryIDs
for i = 1, #entryIds do
local entryId = entryIds[i] --number
local traitEntryInfo = C_Traits.GetEntryInfo(configId, entryId)
local borderTypes = Enum.TraitNodeEntryType
if (traitEntryInfo.type) then -- == borderTypes.SpendCircle
local definitionId = traitEntryInfo.definitionID
local traitDefinitionInfo = C_Traits.GetDefinitionInfo(definitionId)
local spellId = traitDefinitionInfo.overriddenSpellID or traitDefinitionInfo.spellID
local spellName, _, spellTexture = GetSpellInfo(spellId)
if (spellName) then
local talentInfo = {Name = spellName, ID = spellId, Texture = spellTexture, IsSelected = (activeEntry and activeEntry.rank and activeEntry.rank > 0) or false}
allTalents[#allTalents+1] = talentInfo
end
end
end
end
end
end
end
return allTalents
end
---return a table where keys are spellIds (number) and the value is true
---@return table<number, boolean>
function DF:GetAvailableSpells()
@@ -1528,7 +1567,7 @@ function DF:GetAvailableSpells()
return HasPetSpells()
end
--get pet spells from the pet spellbook
--get pet spells from the pet spellbook
local numPetSpells = getNumPetSpells()
if (numPetSpells) then
for i = 1, numPetSpells do
@@ -1772,7 +1811,7 @@ end
--add a new color name, the color can be query using DetailsFramework:ParseColors(colorName)
function DF:NewColor(colorName, red, green, blue, alpha)
assert(type(colorName) == "string", "DetailsFramework:NewColor(): colorName must be a string.")
assert(not DF.alias_text_colors[colorName], "DetailsFramework:NewColor(): colorName already exists.")
--assert(not DF.alias_text_colors[colorName], "DetailsFramework:NewColor(): colorName already exists.")
red, green, blue, alpha = DetailsFramework:ParseColors(red, green, blue, alpha)
local colorTable = DetailsFramework:FormatColor("table", red, green, blue, alpha)
@@ -3475,6 +3514,12 @@ DF.button_templates["OPTIONS_BUTTON_TEMPLATE"] = {
backdropbordercolor = {0, 0, 0, 1},
}
DF.button_templates["OPTIONS_BUTTON_GOLDENBORDER_TEMPLATE"] = {
backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], edgeSize = 1, bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true},
backdropcolor = {1, 1, 1, .5},
backdropbordercolor = {1, 0.785, 0, 1},
}
--sliders
DF.slider_templates = DF.slider_templates or {}
DF.slider_templates["OPTIONS_SLIDER_TEMPLATE"] = {
@@ -3489,6 +3534,12 @@ DF.slider_templates["OPTIONS_SLIDER_TEMPLATE"] = {
thumbcolor = {0, 0, 0, 0.5},
}
---install a template
---@param widgetType string
---@param templateName string
---@param template table
---@param parentName any
---@return table
function DF:InstallTemplate(widgetType, templateName, template, parentName)
local newTemplate = {}
@@ -4986,13 +5037,13 @@ function DF:GetCharacterRaceList()
end
for i = 1, 100 do
local raceInfo = C_CreatureInfo.GetRaceInfo (i)
local raceInfo = C_CreatureInfo.GetRaceInfo(i)
if (raceInfo and DF.RaceList [raceInfo.raceID]) then
tinsert(DF.RaceCache, {Name = raceInfo.raceName, FileString = raceInfo.clientFileString, ID = raceInfo.raceID})
end
if IS_WOW_PROJECT_MAINLINE then
local alliedRaceInfo = C_AlliedRaces.GetRaceInfoByID (i)
local alliedRaceInfo = C_AlliedRaces.GetRaceInfoByID(i)
if (alliedRaceInfo and DF.AlliedRaceList [alliedRaceInfo.raceID]) then
tinsert(DF.RaceCache, {Name = alliedRaceInfo.maleName, FileString = alliedRaceInfo.raceFileString, ID = alliedRaceInfo.raceID})
end
@@ -5005,24 +5056,72 @@ end
--get a list of talents for the current spec the player is using
--if onlySelected return an index table with only the talents the character has selected
--if onlySelectedHash return a hash table with [spelID] = true
function DF:GetCharacterTalents (onlySelected, onlySelectedHash)
function DF:GetCharacterTalents(bOnlySelected, bOnlySelectedHash)
local talentList = {}
local version, build, date, tocversion = GetBuildInfo()
for i = 1, 7 do
for o = 1, 3 do
local talentID, name, texture, selected, available = GetTalentInfo (i, o, 1)
if (onlySelectedHash) then
if (selected) then
talentList [talentID] = true
break
if (tocversion >= 70000 and tocversion <= 99999) then
for i = 1, 7 do
for o = 1, 3 do
local talentID, name, texture, selected, available = GetTalentInfo(i, o, 1)
if (bOnlySelectedHash) then
if (selected) then
talentList[talentID] = true
break
end
elseif (bOnlySelected) then
if (selected) then
table.insert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
break
end
else
table.insert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
end
elseif (onlySelected) then
if (selected) then
tinsert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
break
end
end
elseif (tocversion >= 100000) then
if (not bOnlySelected) then
return DF:GetAllTalents()
end
local configId = C_ClassTalents.GetActiveConfigID()
if (configId) then
local configInfo = C_Traits.GetConfigInfo(configId)
--get the spells from the SPEC from talents
for treeIndex, treeId in ipairs(configInfo.treeIDs) do
local treeNodes = C_Traits.GetTreeNodes(treeId)
for nodeIdIndex, treeNodeID in ipairs(treeNodes) do
local traitNodeInfo = C_Traits.GetNodeInfo(configId, treeNodeID)
if (traitNodeInfo) then
local activeEntry = traitNodeInfo.activeEntry
local entryIds = traitNodeInfo.entryIDs
for i = 1, #entryIds do
local entryId = entryIds[i] --number
local traitEntryInfo = C_Traits.GetEntryInfo(configId, entryId)
local borderTypes = Enum.TraitNodeEntryType
if (traitEntryInfo.type) then -- == borderTypes.SpendCircle
local definitionId = traitEntryInfo.definitionID
local traitDefinitionInfo = C_Traits.GetDefinitionInfo(definitionId)
local spellId = traitDefinitionInfo.overriddenSpellID or traitDefinitionInfo.spellID
local spellName, _, spellTexture = GetSpellInfo(spellId)
local bIsSelected = (activeEntry and activeEntry.rank and activeEntry.rank > 0) or false
if (spellName and bIsSelected) then
local talentInfo = {Name = spellName, ID = spellId, Texture = spellTexture, IsSelected = true}
if (bOnlySelectedHash) then
talentList[spellId] = talentInfo
else
table.insert(talentList, talentInfo)
end
end
end
end
end
end
else
tinsert(talentList, {Name = name, ID = talentID, Texture = texture, IsSelected = selected})
end
end
end
@@ -5030,7 +5129,7 @@ function DF:GetCharacterTalents (onlySelected, onlySelectedHash)
return talentList
end
function DF:GetCharacterPvPTalents (onlySelected, onlySelectedHash)
function DF:GetCharacterPvPTalents(onlySelected, onlySelectedHash)
if (onlySelected or onlySelectedHash) then
local talentsSelected = C_SpecializationInfo.GetAllSelectedPvpTalentIDs()
local talentList = {}
@@ -5294,6 +5393,15 @@ DF.SpecListByClass = {
},
}
---return if the specId is a valid spec, it'll return false for specIds from the tutorial area
---@param self table
---@param specId number
function DF:IsValidSpecId(specId)
local _, class = UnitClass("player")
local specs = DF.SpecListByClass[class]
return specs and specs[specId] and true or false
end
--given a class and a specId, return if the specId is a spec from the class passed
function DF:IsSpecFromClass(class, specId)
return DF.ClassSpecs[class] and DF.ClassSpecs[class][specId]
@@ -5808,4 +5916,23 @@ function DF:DebugVisibility(UIObject)
local numPoints = UIObject:GetNumPoints()
print("Num Points:", numPoints > 0 and "|cFF00FF00" .. numPoints .. "|r" or "|cFFFF00000|r")
end
local beenchmarkTime = 0
local beenchmarkEnabled = false
function _G.__benchmark(bNotPrintResult)
if (not beenchmarkEnabled) then
beenchmarkEnabled = true
beenchmarkTime = debugprofilestop()
else
local elapsed = debugprofilestop() - beenchmarkTime
beenchmarkEnabled = false
if (bNotPrintResult) then
return elapsed
end
print("Elapsed Time:", elapsed)
return elapsed
end
end
+3 -2
View File
@@ -638,8 +638,8 @@ local default_header_options = {
---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
---@param options table?
---@param frameName string?
---@return df_headerframe
function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
---create the header frame which is returned by this function
@@ -649,6 +649,7 @@ function detailsFramework:CreateHeader(parent, headerTable, options, frameName)
detailsFramework:Mixin(newHeader, detailsFramework.OptionsFunctions)
detailsFramework:Mixin(newHeader, detailsFramework.HeaderMixin)
options = options or {}
newHeader:BuildOptionsTable(default_header_options, options)
--set the backdrop and backdrop color following the values in the options table
+1101 -460
View File
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -23,7 +23,7 @@
<Script file="charts.lua"/>
<Script file="scripting.lua"/>
<Script file="externals.lua"/>
<Script file="frames.lua"/>
<Script file="rounded_panel.lua"/>
<Include file="tutorial_alert.xml"/>
<Include file="split_bar.xml"/>
@@ -32,8 +32,10 @@
<Include file="cooltip.xml"/>
<Include file="dropdown.xml"/>
<Include file="normal_bar.xml"/>
<Script file="scrollbox.lua"/>
<Include file="panel.xml"/>
<Script file="loadconditions.lua"/>
<Include file="unitframe.lua"/>
<Script file="icon.lua"/>
<Script file="icongeneric.lua"/>
+869
View File
@@ -0,0 +1,869 @@
local detailsFramework = _G ["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local _
--lua locals
local rawset = rawset
local rawget = rawget
local setmetatable = setmetatable
local unpack = unpack ---@diagnostic disable-line
local type = type
local floor = math.floor
local loadstring = loadstring ---@diagnostic disable-line
local CreateFrame = CreateFrame ---@diagnostic disable-line
local UnitIsUnit = UnitIsUnit ---@diagnostic disable-line
local UnitClass = UnitClass ---@diagnostic disable-line
local GetInstanceInfo = GetInstanceInfo ---@diagnostic disable-line
local C_ChallengeMode = C_ChallengeMode ---@diagnostic disable-line
local C_Map = C_Map ---@diagnostic disable-line
local GetTalentInfoByID = GetTalentInfoByID ---@diagnostic disable-line
local IS_WOW_PROJECT_MAINLINE = WOW_PROJECT_ID == WOW_PROJECT_MAINLINE ---@diagnostic disable-line
local IS_WOW_PROJECT_NOT_MAINLINE = WOW_PROJECT_ID ~= WOW_PROJECT_MAINLINE ---@diagnostic disable-line
local IS_WOW_PROJECT_CLASSIC_ERA = WOW_PROJECT_ID == WOW_PROJECT_CLASSIC ---@diagnostic disable-line
local PixelUtil = PixelUtil or DFPixelUtil ---@diagnostic disable-line
local UnitGroupRolesAssigned = detailsFramework.UnitGroupRolesAssigned
local loadConditionsFrame
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--load conditions panel
--this is the table prototype to hold load conditions settings
local default_load_conditions = {
class = {},
spec = {},
race = {},
talent = {},
pvptalent = {},
group = {},
role = {},
affix = {},
encounter_ids = {},
map_ids = {},
}
--[=[
Skittish 135994 2
Volcanic 451169 3
Necrotic 1029009 4
Teeming 136054 5
Raging 132345 6
Bolstering 132333 7
Sanguine 136124 8
Tyrannical 236401 9
Fortified 463829 10
Bursting 1035055 11
Grievous 132090 12
Explosive 2175503 13
Quaking 136025 14
Infested 2032223 16
Reaping 2446016 117
Beguiling 237565 119
Awakened 442737 120
Prideful 3528307 121
Inspiring 135946 122
Spiteful 135945 123
Storming 136018 124
Tormented 3528304 128
Infernal 1394959 129
Encrypted 4038106 130
Shrouded 136177 131
Thundering 1385910 132
[PH] 0 133
Entangling 134412 134
Afflicted 237555 135
Incorporeal 298642 136
Shielding 535593 137
--]=]
local deprecatedAffixes = {
[2] = true, --Skittish
[5] = true, --Teeming
[16] = true, --Infested
[117] = true, --Reaping
[119] = true, --Beguiling
[13] = true, --Explosive
[14] = true, --Quaking
[120] = true, --Awakened
[121] = true, --Prideful
[130] = true, --Encrypted
}
local default_load_conditions_frame_options = {
title = "Details! Framework: Load Conditions",
name = "Object",
}
function detailsFramework:CreateLoadFilterParser(callback)
local filterFrame = CreateFrame("frame")
filterFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
if IS_WOW_PROJECT_MAINLINE then
filterFrame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
filterFrame:RegisterEvent("PLAYER_TALENT_UPDATE")
end
filterFrame:RegisterEvent("PLAYER_ROLES_ASSIGNED")
filterFrame:RegisterEvent("ZONE_CHANGED_NEW_AREA")
if IS_WOW_PROJECT_MAINLINE then
filterFrame:RegisterEvent("CHALLENGE_MODE_START")
end
filterFrame:RegisterEvent("ENCOUNTER_START")
filterFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
filterFrame:RegisterEvent("PLAYER_REGEN_DISABLED")
filterFrame:SetScript("OnEvent", function(self, event, ...)
if (event == "ENCOUNTER_START") then --triggers before regen_disabled
local encounterID = ...
filterFrame.EncounterIDCached = encounterID
elseif (event == "PLAYER_REGEN_DISABLED") then
elseif (event == "ENCOUNTER_END") then
filterFrame.EncounterIDCached = nil
elseif (event == "PLAYER_REGEN_ENABLED") then
--f.EncounterIDCached = nil
--when the player dies during an encounter, the game is triggering regen enabled
elseif (event == "PLAYER_SPECIALIZATION_CHANGED") then
if (loadConditionsFrame and loadConditionsFrame:IsShown()) then
loadConditionsFrame:Refresh()
end
local unit = ...
if (not unit or not UnitIsUnit("player", unit)) then
return
end
elseif (event == "PLAYER_ROLES_ASSIGNED") then
local assignedRole = UnitGroupRolesAssigned("player")
if (assignedRole == "NONE") then
local spec = DetailsFramework.GetSpecialization()
if (spec) then
assignedRole = DetailsFramework.GetSpecializationRole(spec)
end
end
if (detailsFramework.CurrentPlayerRole == assignedRole) then
return
end
detailsFramework.CurrentPlayerRole = assignedRole
end
detailsFramework:QuickDispatch(callback, filterFrame.EncounterIDCached)
end)
end
function detailsFramework:PassLoadFilters(loadTable, encounterID)
--class
local passLoadClass
if (loadTable.class.Enabled) then
local _, classFileName = UnitClass("player")
if (not loadTable.class[classFileName]) then
return false, _G["CLASS"]
else
passLoadClass = true
end
end
--spec
if (IS_WOW_PROJECT_MAINLINE and loadTable.spec.Enabled) then
local canCheckTalents = true
if (passLoadClass) then
--if is allowed to load on this class, check if the talents isn't from another class
local _, classFileName = UnitClass("player")
local specsForThisClass = detailsFramework:GetClassSpecIDs(classFileName)
canCheckTalents = false
for _, specID in ipairs(specsForThisClass) do
if (loadTable.spec[specID] or loadTable.spec[specID..""]) then
--theres a talent for this class
canCheckTalents = true
break
end
end
end
if (canCheckTalents) then
local specIndex = DetailsFramework.GetSpecialization()
if (specIndex) then
local specID = DetailsFramework.GetSpecializationInfo(specIndex)
if not specID or(not loadTable.spec[specID] and not loadTable.spec[specID .. ""]) then
return false, _G["SPECIALIZATION"]
end
else
return false, _G["SPECIALIZATION"]
end
end
end
--race
if (loadTable.race.Enabled) then
local raceName, raceFileName, raceID = UnitRace("player")
if (not loadTable.race [raceFileName]) then
return false, _G["RACE"]
end
end
--talents
if (IS_WOW_PROJECT_MAINLINE and loadTable.talent.Enabled) then
local bOnlySelected, bUseHashTable = true, true
local talentsInUse = detailsFramework:GetCharacterTalents(bOnlySelected, bUseHashTable)
local hasTalent
for talentId in pairs(talentsInUse) do
if talentId and(loadTable.talent[talentId] or loadTable.talent[talentId .. ""]) then
hasTalent = true
break
end
end
if (not hasTalent) then
return false, _G["TALENTS"]
end
end
--pvptalent
if (IS_WOW_PROJECT_MAINLINE and loadTable.pvptalent.Enabled) then
local talentsInUse = detailsFramework:GetCharacterPvPTalents(false, true)
local hasTalent
for talentID, _ in pairs(talentsInUse) do
if talentID and(loadTable.pvptalent [talentID] or loadTable.pvptalent [talentID .. ""]) then
hasTalent = true
break
end
end
if (not hasTalent) then
return false, (_G["PVP"] or "") .. " " .. (_G["TALENTS"] or "")
end
end
--group
if (loadTable.group.Enabled) then
local _, zoneType = GetInstanceInfo()
if (not loadTable.group[zoneType]) then
return false, _G["GROUP"]
end
end
--role
if (loadTable.role.Enabled) then
local assignedRole = UnitGroupRolesAssigned("player")
if (assignedRole == "NONE") then
local spec = DetailsFramework.GetSpecialization()
if (spec) then
assignedRole = DetailsFramework.GetSpecializationRole(spec)
end
end
if (not loadTable.role [assignedRole]) then
return false, _G["ROLE"]
end
end
--affix
if (IS_WOW_PROJECT_MAINLINE and loadTable.affix.Enabled) then
local isInMythicDungeon = C_ChallengeMode.IsChallengeModeActive()
if (not isInMythicDungeon) then
return false, "M+ Affix"
end
local level, affixes, wasEnergized = C_ChallengeMode.GetActiveKeystoneInfo()
local hasAffix = false
for _, affixID in ipairs(affixes) do
if affixID and(loadTable.affix[affixID] or loadTable.affix[affixID .. ""]) then
hasAffix = true
break
end
end
if (not hasAffix) then
return false, "M+ Affix"
end
end
--encounter id
if (loadTable.encounter_ids.Enabled) then
if (not encounterID) then
return
end
local bHasEncounter
for _, userEnteredEncounterId in pairs(loadTable.encounter_ids) do
if (userEnteredEncounterId == encounterID) then
bHasEncounter = true
break
end
end
if (not bHasEncounter) then
return false, _G["GUILD_NEWS_FILTER3"] --"raid encounters"
end
end
--map id
if (loadTable.map_ids.Enabled) then
local _, _, _, _, _, _, _, zoneMapID = GetInstanceInfo()
local uiMapID = C_Map.GetBestMapForUnit("player")
local bHasMapID = false
for _, userEnteredMapId in pairs(loadTable.map_ids) do
if (userEnteredMapId == zoneMapID or userEnteredMapId == uiMapID) then
bHasMapID = true
break
end
end
if (not bHasMapID) then
return false, _G["BATTLEFIELD_MINIMAP"] --"zone map"
end
end
return true
end
--this func will deploy the default values from the prototype into the config table
function detailsFramework:UpdateLoadConditionsTable(configTable)
configTable = configTable or {}
detailsFramework.table.deploy(configTable, default_load_conditions)
return configTable
end
--/run Plater.OpenOptionsPanel()PlaterOptionsPanelContainer:SelectIndex(Plater, 14)
function detailsFramework:OpenLoadConditionsPanel(optionsTable, callback, frameOptions)
frameOptions = frameOptions or {}
detailsFramework.table.deploy(frameOptions, default_load_conditions_frame_options)
detailsFramework:UpdateLoadConditionsTable(optionsTable)
if (not loadConditionsFrame) then
loadConditionsFrame = detailsFramework:CreateSimplePanel(UIParent, 1024, 600, "Load Conditions", "loadConditionsFrame")
loadConditionsFrame:SetBackdropColor(0, 0, 0, 1)
loadConditionsFrame.AllRadioGroups = {}
loadConditionsFrame.AllTextEntries = {}
loadConditionsFrame.OptionsTable = optionsTable
detailsFramework:ApplyStandardBackdrop(loadConditionsFrame, false, 1.1)
local xStartAt = 10
local x2StartAt = 500
local anchorPositions = {
class = {xStartAt, -70},
spec = {xStartAt, -200},
race = {xStartAt, -250},
role = {xStartAt, -380},
talent = {xStartAt, -440},
pvptalent = {x2StartAt, -70},
group = {x2StartAt, -170},
affix = {x2StartAt, -240},
encounter_ids = {x2StartAt+1, -375},
map_ids = {x2StartAt + 210, -375},
}
local editingLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Load Conditions For:")
local editingWhatLabel = detailsFramework:CreateLabel(loadConditionsFrame, "")
editingLabel:SetPoint("topleft", loadConditionsFrame, "topleft", 10, -35)
editingWhatLabel:SetPoint("left", editingLabel, "right", 2, 0)
--this label store the name of what is being edited
loadConditionsFrame.EditingLabel = editingWhatLabel
--when the user click on an option, run the callback
loadConditionsFrame.RunCallback = function()
detailsFramework:Dispatch(loadConditionsFrame.CallbackFunc)
end
--when the user click on an option or when the panel is opened
--check if there's an option enabled and fadein all options, fadeout otherwise
loadConditionsFrame.OnRadioStateChanged = function(radioGroup, subConfigTable)
subConfigTable.Enabled = nil
subConfigTable.Enabled = next(subConfigTable) and true or nil
radioGroup:SetFadeState(subConfigTable.Enabled)
end
--create the radio group for character class
loadConditionsFrame.OnRadioCheckboxClick = function(self, key, value)
--hierarchy: DBKey ["class"] key ["HUNTER"] value TRUE
local DBKey = self:GetParent().DBKey
loadConditionsFrame.OptionsTable [DBKey] [key and key .. ""] = value and true or nil
if not value then -- cleanup "number" type values
loadConditionsFrame.OptionsTable [DBKey] [key] = nil
end
loadConditionsFrame.OnRadioStateChanged(self:GetParent(), loadConditionsFrame.OptionsTable [DBKey])
loadConditionsFrame.RunCallback()
end
--create the radio group for classes
local classes = {}
for _, classTable in pairs(detailsFramework:GetClassList()) do
table.insert(classes, {
name = classTable.Name,
set = loadConditionsFrame.OnRadioCheckboxClick,
param = classTable.FileString,
get = function() return loadConditionsFrame.OptionsTable.class[classTable.FileString] end,
texture = classTable.Texture,
texcoord = classTable.TexCoord,
})
end
local classGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, classes, nil, {width = 430, height = 200, title = "Character Class", backdrop_color = {0, 0, 0, 0}}, {offset_x = 130, amount_per_line = 3})
classGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.class[1], anchorPositions.class[2])
classGroup.DBKey = "class"
table.insert(loadConditionsFrame.AllRadioGroups, classGroup)
--create the radio group for character spec
if IS_WOW_PROJECT_MAINLINE then
local specs = {}
for _, specID in ipairs(detailsFramework:GetClassSpecIDs(select(2, UnitClass("player")))) do
local specID, specName, specDescription, specIcon, specBackground, specRole, specClass = DetailsFramework.GetSpecializationInfoByID(specID)
table.insert(specs, {
name = specName,
set = loadConditionsFrame.OnRadioCheckboxClick,
param = specID,
get = function() return loadConditionsFrame.OptionsTable.spec[specID] or loadConditionsFrame.OptionsTable.spec[specID..""] end,
texture = specIcon,
})
end
local specGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, specs, nil, {width = 200, height = 200, title = "Character Spec", backdrop_color = {0, 0, 0, 0}}, {offset_x = 120, amount_per_line = 4})
specGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.spec[1], anchorPositions.spec[2])
specGroup.DBKey = "spec"
table.insert(loadConditionsFrame.AllRadioGroups, specGroup)
end
--create radio group for character races
local raceList = {}
for _, raceTable in ipairs(detailsFramework:GetCharacterRaceList()) do
table.insert(raceList, {
name = raceTable.Name:sub(1, 15),
set = loadConditionsFrame.OnRadioCheckboxClick,
param = raceTable.FileString,
get = function() return loadConditionsFrame.OptionsTable.race [raceTable.FileString] end,
})
end
local raceGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, raceList, nil, {width = 200, height = 200, title = "Character Race", backdrop_color = {0, 0, 0, 0}})
raceGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.race [1], anchorPositions.race [2])
raceGroup.DBKey = "race"
table.insert(loadConditionsFrame.AllRadioGroups, raceGroup)
--create radio group for talents
if IS_WOW_PROJECT_MAINLINE then
--[=[ 7.0 to 9.0 talents schema
local talentList = {}
for _, talentTable in ipairs(detailsFramework:GetCharacterTalents()) do
if talentTable.ID then
table.insert(talentList, {
name = talentTable.Name:sub(1, 15),
set = loadConditionsFrame.OnRadioCheckboxClick,
param = talentTable.ID,
get = function() return loadConditionsFrame.OptionsTable.talent[talentTable.ID] or loadConditionsFrame.OptionsTable.talent[talentTable.ID .. ""] end,
texture = talentTable.Texture,
})
end
end
--]=]
--10.0 talents schema
local talentList = {}
local talentGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, talentList, nil, {width = 200, height = 200, title = "Character Talents", backdrop_color = {0, 0, 0, 0}}, {offset_x = 64, amount_per_line = 16})
talentGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.talent[1], anchorPositions.talent[2])
talentGroup.DBKey = "talent"
table.insert(loadConditionsFrame.AllRadioGroups, talentGroup)
loadConditionsFrame.TalentGroup = talentGroup
do
if (false) then --disabled, isn't in use
--create a frame to show talents selected in other specs or characters
local otherTalents = CreateFrame("frame", nil, loadConditionsFrame, "BackdropTemplate")
otherTalents:SetSize(26, 26)
otherTalents:SetPoint("left", talentGroup.Title.widget, "right", 10, -2)
otherTalents.Texture = detailsFramework:CreateImage(otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
otherTalents.Texture:SetAllPoints()
local removeTalent = function(_, _, talentID)
loadConditionsFrame.OptionsTable.talent[talentID] = nil
GameCooltip2:Hide()
loadConditionsFrame.OnRadioStateChanged(talentGroup, loadConditionsFrame.OptionsTable[talentGroup.DBKey])
--loadConditionsFrame.CanShowTalentWarning()
end
local buildTalentMenu = function()
local playerTalents = detailsFramework:GetCharacterTalents()
local indexedTalents = {}
for _, talentTable in ipairs(playerTalents) do
table.insert(indexedTalents, talentTable.ID)
end
--talents selected to load
GameCooltip2:AddLine("select a talent to remove it (added from a different spec or character)", "", 1, "orange", "orange", 9)
GameCooltip2:AddLine("$div", nil, nil, -1, -1)
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.talent) do
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
local talentID, name, texture, selected, available = GetTalentInfoByID(talentID)
if (name) then
GameCooltip2:AddLine(name)
GameCooltip2:AddIcon(texture, 1, 1, 16, 16, .1, .9, .1, .9)
GameCooltip2:AddMenu(1, removeTalent, talentID)
end
end
end
end
otherTalents.CoolTip = {
Type = "menu",
BuildFunc = buildTalentMenu,
OnEnterFunc = function(self) end,
OnLeaveFunc = function(self) end,
FixedValue = "none",
ShowSpeed = 0.05,
Options = function()
GameCooltip2:SetOption("TextFont", "Friz Quadrata TT")
GameCooltip2:SetOption("TextColor", "orange")
GameCooltip2:SetOption("TextSize", 12)
GameCooltip2:SetOption("FixedWidth", 220)
GameCooltip2:SetOption("ButtonsYMod", -4)
GameCooltip2:SetOption("YSpacingMod", -4)
GameCooltip2:SetOption("IgnoreButtonAutoHeight", true)
GameCooltip2:SetColor(1, 0.5, 0.5, 0.5, 0)
local preset2_backdrop = {bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
local gray_table = {0.37, 0.37, 0.37, 0.95}
local black_table = {0.2, 0.2, 0.2, 1}
GameCooltip2:SetBackdrop(1, preset2_backdrop, gray_table, black_table)
GameCooltip2:SetBackdrop(2, preset2_backdrop, gray_table, black_table)
end,
}
GameCooltip2:CoolTipInject(otherTalents)
--[=[
function loadConditionsFrame.CanShowTalentWarning() --not in use
local playerTalents = detailsFramework:GetCharacterTalents()
local indexedTalents = {}
for _, talentTable in ipairs(playerTalents) do
table.insert(indexedTalents, talentTable.ID)
end
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.talent) do
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
otherTalents:Show()
return
end
end
otherTalents:Hide()
end
--]=]
end
end
end
--create radio group for pvp talents
if IS_WOW_PROJECT_MAINLINE then
local pvpTalentList = {}
for _, talentTable in ipairs(detailsFramework:GetCharacterPvPTalents()) do
table.insert(pvpTalentList, {
name = talentTable.Name:sub(1, 15),
set = loadConditionsFrame.OnRadioCheckboxClick,
param = talentTable.ID,
get = function() return loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID] or loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID .. ""] end,
texture = talentTable.Texture,
})
end
local pvpTalentGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, pvpTalentList, nil, {width = 200, height = 200, title = "Characer PvP Talents", backdrop_color = {0, 0, 0, 0}}, {offset_x = 160, amount_per_line = 3})
pvpTalentGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.pvptalent [1], anchorPositions.pvptalent [2])
pvpTalentGroup.DBKey = "pvptalent"
table.insert(loadConditionsFrame.AllRadioGroups, pvpTalentGroup)
loadConditionsFrame.PvPTalentGroup = pvpTalentGroup
do
if (false) then
--create a frame to show talents selected in other specs or characters
local otherTalents = CreateFrame("frame", nil, loadConditionsFrame, "BackdropTemplate")
otherTalents:SetSize(26, 26)
otherTalents:SetPoint("left", pvpTalentGroup.Title.widget, "right", 10, -2)
otherTalents.Texture = detailsFramework:CreateImage(otherTalents, [[Interface\BUTTONS\AdventureGuideMicrobuttonAlert]], 24, 24)
otherTalents.Texture:SetAllPoints()
local removeTalent = function(_, _, talentID)
loadConditionsFrame.OptionsTable.pvptalent [talentID] = nil
GameCooltip2:Hide()
loadConditionsFrame.OnRadioStateChanged(pvpTalentGroup, loadConditionsFrame.OptionsTable [pvpTalentGroup.DBKey])
--loadConditionsFrame.CanShowPvPTalentWarning()
end
local buildTalentMenu = function()
local playerTalents = detailsFramework:GetCharacterPvPTalents()
local indexedTalents = {}
for _, talentTable in ipairs(playerTalents) do
table.insert(indexedTalents, talentTable.ID)
end
--talents selected to load
GameCooltip2:AddLine("select a talent to remove it(added from a different spec or character)", "", 1, "orange", "orange", 9)
GameCooltip2:AddLine("$div", nil, nil, -1, -1)
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.pvptalent) do
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
local _, name, texture = GetPvpTalentInfoByID(talentID)
if (name) then
GameCooltip2:AddLine(name)
GameCooltip2:AddIcon(texture, 1, 1, 16, 16, .1, .9, .1, .9)
GameCooltip2:AddMenu(1, removeTalent, talentID)
end
end
end
end
otherTalents.CoolTip = {
Type = "menu",
BuildFunc = buildTalentMenu,
OnEnterFunc = function(self) end,
OnLeaveFunc = function(self) end,
FixedValue = "none",
ShowSpeed = 0.05,
Options = function()
GameCooltip2:SetOption("TextFont", "Friz Quadrata TT")
GameCooltip2:SetOption("TextColor", "orange")
GameCooltip2:SetOption("TextSize", 12)
GameCooltip2:SetOption("FixedWidth", 220)
GameCooltip2:SetOption("ButtonsYMod", -4)
GameCooltip2:SetOption("YSpacingMod", -4)
GameCooltip2:SetOption("IgnoreButtonAutoHeight", true)
GameCooltip2:SetColor(1, 0.5, 0.5, 0.5, 0)
local preset2_backdrop = {edgeFile = [[Interface\Buttons\WHITE8X8]], tile = true, edgeSize = 1, tileSize = 16, insets = {left = 0, right = 0, top = 0, bottom = 0}}
local gray_table = {0.37, 0.37, 0.37, 0.95}
local black_table = {0.2, 0.2, 0.2, 1}
GameCooltip2:SetBackdrop(1, preset2_backdrop, gray_table, black_table)
GameCooltip2:SetBackdrop(2, preset2_backdrop, gray_table, black_table)
end,
}
GameCooltip2:CoolTipInject(otherTalents)
function loadConditionsFrame.CanShowPvPTalentWarning()
local playerTalents = detailsFramework:GetCharacterPvPTalents()
local indexedTalents = {}
for _, talentTable in ipairs(playerTalents) do
table.insert(indexedTalents, talentTable.ID)
end
for talentID, _ in pairs(loadConditionsFrame.OptionsTable.pvptalent) do
if (type(talentID) == "number" and not detailsFramework.table.find(indexedTalents, talentID)) then
otherTalents:Show()
return
end
end
otherTalents:Hide()
end
--]=]
end
end
end
--create radio for group types
local groupTypes = {}
for _, groupTable in ipairs(detailsFramework:GetGroupTypes()) do
table.insert(groupTypes, {
name = groupTable.Name,
set = loadConditionsFrame.OnRadioCheckboxClick,
param = groupTable.ID,
get = function() return loadConditionsFrame.OptionsTable.group [groupTable.ID] or loadConditionsFrame.OptionsTable.group [groupTable.ID .. ""] end,
})
end
local groupTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, groupTypes, nil, {width = 200, height = 200, title = "Group Types", backdrop_color = {0, 0, 0, 0}}, {offset_x = 125})
groupTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.group[1], anchorPositions.group[2])
groupTypesGroup.DBKey = "group"
table.insert(loadConditionsFrame.AllRadioGroups, groupTypesGroup)
--create radio for character roles
local roleTypes = {}
for _, roleTable in ipairs(detailsFramework:GetRoleTypes()) do
table.insert(roleTypes, {
name = (roleTable.Texture .. " " .. roleTable.Name),
set = loadConditionsFrame.OnRadioCheckboxClick,
param = roleTable.ID,
get = function() return loadConditionsFrame.OptionsTable.role [roleTable.ID] or loadConditionsFrame.OptionsTable.role [roleTable.ID .. ""] end,
})
end
local roleTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, roleTypes, nil, {width = 200, height = 200, title = "Role Types", backdrop_color = {0, 0, 0, 0}})
roleTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.role[1], anchorPositions.role[2])
roleTypesGroup.DBKey = "role"
table.insert(loadConditionsFrame.AllRadioGroups, roleTypesGroup)
--create radio group for mythic+ affixes
if IS_WOW_PROJECT_MAINLINE then
local affixes = {}
for i = 2, 1000 do
local affixName, desc, texture = C_ChallengeMode.GetAffixInfo(i)
if (affixName and not deprecatedAffixes[i]) then
table.insert(affixes, {
name = affixName,
set = loadConditionsFrame.OnRadioCheckboxClick,
param = i,
get = function() return loadConditionsFrame.OptionsTable.affix[i] or loadConditionsFrame.OptionsTable.affix[i .. ""] end,
texture = texture,
})
end
end
local affixTypesGroup = detailsFramework:CreateCheckboxGroup(loadConditionsFrame, affixes, nil, {width = 200, height = 200, title = "M+ Affixes", backdrop_color = {0, 0, 0, 0}}, {offset_x = 125})
affixTypesGroup:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.affix [1], anchorPositions.affix [2])
affixTypesGroup.DBKey = "affix"
table.insert(loadConditionsFrame.AllRadioGroups, affixTypesGroup)
end
--text entries functions
local textEntryRefresh = function(self)
local idList = loadConditionsFrame.OptionsTable [self.DBKey]
self:SetText("")
for _, id in pairs(idList) do
if tonumber(id) then
self:SetText(self:GetText() .. " " .. id)
end
end
self:SetText(self:GetText():gsub("^ ", ""))
end
local textEntryOnEnterPressed = function(_, self)
table.wipe(loadConditionsFrame.OptionsTable [self.DBKey])
local text = self:GetText()
for _, ID in ipairs({strsplit(" ", text)}) do
ID = detailsFramework:trim(ID)
ID = tonumber(ID)
if (ID) then
table.insert(loadConditionsFrame.OptionsTable [self.DBKey], ID)
loadConditionsFrame.OptionsTable [self.DBKey].Enabled = true
end
end
end
--create the text entry to type the encounter ID
local encounterIDLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Encounter ID", detailsFramework:GetTemplate("font", "ORANGE_FONT_TEMPLATE"))
local encounterIDEditbox = detailsFramework:CreateTextEntry(loadConditionsFrame, function() loadConditionsFrame.RunCallback() end, 200, 20, "EncounterEditbox", _, _, detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
encounterIDLabel:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.encounter_ids[1], anchorPositions.encounter_ids[2])
encounterIDEditbox:SetPoint("topleft", encounterIDLabel, "bottomleft", 0, -2)
encounterIDEditbox.DBKey = "encounter_ids"
encounterIDEditbox.Refresh = textEntryRefresh
encounterIDEditbox.tooltip = "Enter multiple IDs separating with a whitespace.\nExample: 35 45 95\n\nSanctum of Domination:\n"
for _, encounterTable in ipairs(detailsFramework:GetCLEncounterIDs()) do
encounterIDEditbox.tooltip = encounterIDEditbox.tooltip .. encounterTable.ID .. " - " .. encounterTable.Name .. "\n"
end
encounterIDEditbox:SetHook("OnEnterPressed", textEntryOnEnterPressed)
table.insert(loadConditionsFrame.AllTextEntries, encounterIDEditbox)
--create the text entry for map ID
local mapIDLabel = detailsFramework:CreateLabel(loadConditionsFrame, "Map ID", detailsFramework:GetTemplate("font", "ORANGE_FONT_TEMPLATE"))
local mapIDEditbox = detailsFramework:CreateTextEntry(loadConditionsFrame, function() loadConditionsFrame.RunCallback() end, 200, 20, "MapEditbox", _, _, detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE"))
mapIDLabel:SetPoint("topleft", loadConditionsFrame, "topleft", anchorPositions.map_ids[1], anchorPositions.map_ids[2])
mapIDEditbox:SetPoint("topleft", mapIDLabel, "bottomleft", 0, -2)
mapIDEditbox.DBKey = "map_ids"
mapIDEditbox.Refresh = textEntryRefresh
mapIDEditbox.tooltip = "Enter multiple IDs separating with a whitespace\nExample: 35 45 95"
mapIDEditbox:SetHook("OnEnterPressed", textEntryOnEnterPressed)
table.insert(loadConditionsFrame.AllTextEntries, mapIDEditbox)
function loadConditionsFrame.Refresh(self)
if IS_WOW_PROJECT_MAINLINE then
---@type {Name: string, ID: number, Texture: any, IsSelected: boolean}[]
local allTalents = detailsFramework:GetAllTalents()
local talentList = {}
for _, talentTable in ipairs(allTalents) do
if (talentTable.ID) then
table.insert(talentList, {
name = "", --talentTable.Name:sub(1, 15),
set = loadConditionsFrame.OnRadioCheckboxClick,
param = talentTable.ID,
get = function() return loadConditionsFrame.OptionsTable.talent[talentTable.ID] or loadConditionsFrame.OptionsTable.talent[talentTable.ID .. ""] end,
texture = talentTable.Texture,
tooltip = talentTable.Name,
})
end
end
--[=[]]
--update the talents(might have changed if the player changed its specializationid)
local talentList = {}
for _, talentTable in ipairs(detailsFramework:GetCharacterTalents()) do
if talentTable.ID then
table.insert(talentList, {
name = talentTable.Name,
set = loadConditionsFrame.OnRadioCheckboxClick,
param = talentTable.ID,
get = function() return loadConditionsFrame.OptionsTable.talent [talentTable.ID] or loadConditionsFrame.OptionsTable.talent [talentTable.ID .. ""] end,
texture = talentTable.Texture,
})
end
end
--]=]
loadConditionsFrame.TalentGroup:SetOptions(talentList)
end
if IS_WOW_PROJECT_MAINLINE then
local pvpTalentList = {}
for _, talentTable in ipairs(detailsFramework:GetCharacterPvPTalents()) do
table.insert(pvpTalentList, {
name = talentTable.Name:sub(1, 15),
set = loadConditionsFrame.OnRadioCheckboxClick,
param = talentTable.ID,
get = function() return loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID] or loadConditionsFrame.OptionsTable.pvptalent [talentTable.ID .. ""] end,
texture = talentTable.Texture,
})
end
loadConditionsFrame.PvPTalentGroup:SetOptions(pvpTalentList)
end
--refresh the radio group
for _, radioGroup in ipairs(loadConditionsFrame.AllRadioGroups) do
radioGroup:Refresh()
loadConditionsFrame.OnRadioStateChanged(radioGroup, loadConditionsFrame.OptionsTable [radioGroup.DBKey])
end
--refresh text entries
for _, textEntry in ipairs(loadConditionsFrame.AllTextEntries) do
textEntry:Refresh()
end
if IS_WOW_PROJECT_MAINLINE then
--loadConditionsFrame.CanShowTalentWarning()
--loadConditionsFrame.CanShowPvPTalentWarning()
end
end
end
--set the options table
loadConditionsFrame.OptionsTable = optionsTable
--set the callback func
loadConditionsFrame.CallbackFunc = callback
loadConditionsFrame.OptionsTable = optionsTable
--set title
loadConditionsFrame.EditingLabel:SetText(frameOptions.name)
loadConditionsFrame.Title:SetText(frameOptions.title)
--show the panel to the user
loadConditionsFrame:Show()
loadConditionsFrame:Refresh()
end
-271
View File
@@ -427,277 +427,6 @@ detailsFramework.ScriptHookMixin = {
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
+235 -1401
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -15,7 +15,7 @@ local CreateImageEditorFrame = function()
background_frame:SetSize(790, 560)
background_frame:SetClampedToScreen(true)
tinsert(UISpecialFrames, "DetailsFrameworkImageEditBackground")
table.insert(UISpecialFrames, "DetailsFrameworkImageEditBackground")
background_frame:SetResizable(true)
background_frame:SetMovable(true)
+29
View File
@@ -0,0 +1,29 @@
--Details Framework Examples for the frame.lua file
--create a frame with rounded corners
local detailsFramework = DetailsFramework
local parent = UIParent
--example of how to create a frame with rounded corners
--frame name for the example
local name = "RoundedCornerFrameExample"
--default options
local optionsTable = {
use_titlebar = true, --default false | if true creates a title bar for the frame
use_scalebar = true, --default false | if true creates a scale bar for the frame
title = "Test", --default "" | title shown in the title bar
scale = 1,
width = 800, --default 200
height = 600, --default 200
roundness = 8, --default 0 | how rounded are the corner, 0 means very rounded, 15 means no rounded
color = {.1, .1, .1, 1},
border_color = {.2, .2, .2, .5},
corner_texture = [[Interface\CHARACTERFRAME\TempPortraitAlphaMaskSmall]],
}
--create the frame and set it's position
---@type df_roundedpanel
local frame = _G[name] or detailsFramework:CreateRoundedPanel(parent, name, optionsTable)
frame:SetPoint("center", parent, "center", 0, 0)
+73 -103
View File
@@ -5,11 +5,15 @@ if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local unpack = unpack
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}
local defaultColorTable = {.98, .98, .98, 1}
local defaultBorderColorTable = {.2, .2, .2, .5}
local titleBarColor = {.2, .2, .2, .5}
local PixelUtil = PixelUtil or DFPixelUtil
---@type edgenames[]
local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"}
@@ -37,22 +41,23 @@ local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"}
---@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 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
---@field corner_texture any
---@field horizontal_border_size_offset number?
---@class df_roundedpanel_preset : table, df_roundedpanel_options
---@field border_color any
---@field color any
---@field roundness number?
---@class df_roundedcornermixin : table
---@field RoundedCornerConstructor fun(self:df_roundedpanel) --called from CreateRoundedPanel
@@ -102,7 +107,7 @@ local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"}
---@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)
PixelUtil.SetSize(thisTexture, width or 16, height or 16)
thisTexture:SetTexture(self.options.corner_texture)
--set the mask
@@ -122,30 +127,30 @@ local setCornerPoints = function(self, textures, width, height, xOffset, yOffset
if (cornerName == "TopLeft") then
thisTexture:SetTexCoord(0, 0.5, 0, 0.5)
thisTexture:SetPoint(cornerName, self, cornerName, -xOffset, yOffset)
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, -xOffset, yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18-xOffset, 16+yOffset)
PixelUtil.SetPoint(thisTexture.MaskTexture, 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)
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, xOffset, yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18+xOffset, 16+yOffset)
PixelUtil.SetPoint(thisTexture.MaskTexture, 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)
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, -xOffset, -yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18-xOffset, 16-yOffset)
PixelUtil.SetPoint(thisTexture.MaskTexture, 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)
PixelUtil.SetPoint(thisTexture, cornerName, self, cornerName, xOffset, -yOffset)
if (thisTexture.MaskTexture) then
thisTexture.MaskTexture:SetPoint(cornerName, self, cornerName, -18+xOffset, 16-yOffset)
PixelUtil.SetPoint(thisTexture.MaskTexture, cornerName, self, cornerName, -18+xOffset, 16-yOffset)
end
end
end
@@ -157,7 +162,6 @@ detailsFramework.RoundedCornerPanelMixin = {
self.CenterTextures = {}
self.BorderCornerTextures = {}
self.BorderEdgeTextures = {}
self.cornerRoundness = 0
for i = 1, #cornerNames do
@@ -170,28 +174,28 @@ detailsFramework.RoundedCornerPanelMixin = {
--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)
PixelUtil.SetPoint(topHorizontalEdge, "topleft", self.CornerTextures["TopLeft"], "topright", 0, 0)
PixelUtil.SetPoint(topHorizontalEdge, "bottomleft", self.CornerTextures["TopLeft"], "bottomright", 0, 0)
PixelUtil.SetPoint(topHorizontalEdge, "topright", self.CornerTextures["TopRight"], "topleft", 0, 0)
PixelUtil.SetPoint(topHorizontalEdge, "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)
PixelUtil.SetPoint(bottomHorizontalEdge, "topleft", self.CornerTextures["BottomLeft"], "topright", 0, 0)
PixelUtil.SetPoint(bottomHorizontalEdge, "bottomleft", self.CornerTextures["BottomLeft"], "bottomright", 0, 0)
PixelUtil.SetPoint(bottomHorizontalEdge, "topright", self.CornerTextures["BottomRight"], "topleft", 0, 0)
PixelUtil.SetPoint(bottomHorizontalEdge, "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)
PixelUtil.SetPoint(centerBlock, "topleft", self.CornerTextures["TopLeft"], "bottomleft", 0, 0)
PixelUtil.SetPoint(centerBlock, "bottomleft", self.CornerTextures["BottomLeft"], "topleft", 0, 0)
PixelUtil.SetPoint(centerBlock, "topright", self.CornerTextures["BottomRight"], "topright", 0, 0)
PixelUtil.SetPoint(centerBlock, "bottomright", self.CornerTextures["BottomRight"], "topright", 0, 0)
centerBlock:SetColorTexture(unpack(defaultColorTable))
self.CenterTextures[#self.CenterTextures+1] = topHorizontalEdge
@@ -207,7 +211,7 @@ detailsFramework.RoundedCornerPanelMixin = {
---@type height
local height = self.options.height
self:SetSize(width, height)
PixelUtil.SetSize(self, width, height)
--fill the corner and edge textures table
setCornerPoints(self, self.CornerTextures)
@@ -241,6 +245,7 @@ detailsFramework.RoundedCornerPanelMixin = {
titleBar:SetPoint("top", self, "top", 0, -4)
titleBar:SetRoundness(5)
titleBar:SetFrameLevel(9500)
titleBar:SetColor(unpack(titleBarColor))
titleBar.bIsTitleBar = true
self.TitleBar = titleBar
self.bHasTitleBar = true
@@ -293,13 +298,13 @@ detailsFramework.RoundedCornerPanelMixin = {
--set the new size of the corners on all corner textures
for _, thisTexture in pairs(self.CornerTextures) do
thisTexture:SetSize(newCornerSize-self.cornerRoundness, newCornerSize)
PixelUtil.SetSize(thisTexture, newCornerSize - (self.cornerRoundness - 2), 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)
PixelUtil.SetSize(thisTexture, newCornerSize-2, newCornerSize+2)
end
--hide the left and right edges as the corner textures already is enough to fill the frame
@@ -307,8 +312,8 @@ detailsFramework.RoundedCornerPanelMixin = {
self.BorderEdgeTextures["Right"]:Hide()
local horizontalEdgesNewSize = self:CalculateBorderEdgeSize("horizontal")
self.BorderEdgeTextures["Top"]:SetSize(horizontalEdgesNewSize, 1)
self.BorderEdgeTextures["Bottom"]:SetSize(horizontalEdgesNewSize, 1)
PixelUtil.SetSize(self.BorderEdgeTextures["Top"], horizontalEdgesNewSize + (self.options.horizontal_border_size_offset or 0), 1)
PixelUtil.SetSize(self.BorderEdgeTextures["Bottom"], horizontalEdgesNewSize + (self.options.horizontal_border_size_offset or 0), 1)
end
self.CenterBlock:Hide()
@@ -324,22 +329,22 @@ detailsFramework.RoundedCornerPanelMixin = {
self.CenterBlock:Show()
for _, thisTexture in pairs(self.CornerTextures) do
thisTexture:SetSize(cornerWidth-self.cornerRoundness, cornerHeight-self.cornerRoundness)
PixelUtil.SetSize(thisTexture, 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)
PixelUtil.SetSize(thisTexture, 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)
PixelUtil.SetSize(self.BorderEdgeTextures["Top"], horizontalEdgesNewSize, 1)
PixelUtil.SetSize(self.BorderEdgeTextures["Bottom"], horizontalEdgesNewSize, 1)
local verticalEdgesNewSize = self:CalculateBorderEdgeSize("vertical")
self.BorderEdgeTextures["Left"]:SetSize(1, verticalEdgesNewSize)
self.BorderEdgeTextures["Right"]:SetSize(1, verticalEdgesNewSize)
PixelUtil.SetSize(self.BorderEdgeTextures["Left"], 1, verticalEdgesNewSize)
PixelUtil.SetSize(self.BorderEdgeTextures["Right"], 1, verticalEdgesNewSize)
end
end
end,
@@ -389,22 +394,22 @@ detailsFramework.RoundedCornerPanelMixin = {
--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)
PixelUtil.SetPoint(topEdge, "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)
PixelUtil.SetPoint(leftEdge, "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)
PixelUtil.SetPoint(bottomEdge, "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)
PixelUtil.SetPoint(rightEdge, "left", self, "right", 0, 0)
self.BorderEdgeTextures["Right"] = rightEdge
---@type width
@@ -413,10 +418,10 @@ detailsFramework.RoundedCornerPanelMixin = {
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)
PixelUtil.SetSize(topEdge, horizontalEdgeSize, 1)
PixelUtil.SetSize(leftEdge, 1, verticalEdgeSize)
PixelUtil.SetSize(bottomEdge, horizontalEdgeSize, 1)
PixelUtil.SetSize(rightEdge, 1, verticalEdgeSize)
for edgeName, thisTexture in pairs(self.BorderEdgeTextures) do
---@cast thisTexture texture
@@ -482,7 +487,7 @@ detailsFramework.RoundedCornerPanelMixin = {
end
if (self.bHasBorder) then
if (alpha < 0.98) then
if (alpha < 0.979) 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()
@@ -504,14 +509,14 @@ local defaultOptions = {
title = "",
scale = 1,
roundness = 0,
color = defaultColorTable,
border_color = defaultColorTable,
color = {.1, .1, .1, 1},
border_color = {.2, .2, .2, .5},
corner_texture = [[Interface\CHARACTERFRAME\TempPortraitAlphaMaskSmall]],
}
local defaultPreset = {
border_color = {.1, .1, .1, 0.834},
color = {defaultRed, defaultGreen, defaultBlue},
color = {.1, .1, .1, 1},
border_color = {.2, .2, .2, .5},
roundness = 3,
}
@@ -536,7 +541,11 @@ function detailsFramework:CreateRoundedPanel(parent, name, optionsTable)
if (newRoundedPanel.options.use_titlebar) then
---@type df_roundedpanel
local titleBar = detailsFramework:CreateRoundedPanel(newRoundedPanel, "$parentTitleBar", {height = 26})
titleBar:SetColor(unpack(titleBarColor))
titleBar:SetPoint("top", newRoundedPanel, "top", 0, -7)
titleBar:SetBorderCornerColor(0, 0, 0, 0)
newRoundedPanel.TitleBar = titleBar
titleBar:SetRoundness(5)
newRoundedPanel.bHasTitleBar = true
@@ -548,8 +557,8 @@ function detailsFramework:CreateRoundedPanel(parent, name, optionsTable)
end
newRoundedPanel:SetRoundness(newRoundedPanel.options.roundness)
newRoundedPanel:SetColor(newRoundedPanel.options.color)
newRoundedPanel:SetBorderCornerColor(newRoundedPanel.options.border_color)
newRoundedPanel:SetColor(newRoundedPanel.options.color)
return newRoundedPanel
end
@@ -613,49 +622,10 @@ function detailsFramework:AddRoundedCornersToFrame(frame, preset)
--handle preset
if (preset and type(preset) == "table") then
frame.options.horizontal_border_size_offset = preset.horizontal_border_size_offset
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)
-1
View File
@@ -1,5 +1,4 @@
--stopped doing the duplicate savedTable
local detailsFramework = _G ["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
+48
View File
@@ -10,6 +10,11 @@ local unpack = table.unpack or _G.unpack
--make a namespace for schedules
DF.Schedules = DF.Schedules or {}
DF.Schedules.AfterCombatSchedules = {
withId = {},
withoutId = {},
}
---@class df_schedule : table
---@field NewTicker fun(time: number, callback: function, ...: any): timer
---@field NewLooper fun(time: number, callback: function, loopAmount: number, loopEndCallback: function?, checkPointCallback: function?, ...: any): timer
@@ -18,6 +23,24 @@ DF.Schedules = DF.Schedules or {}
---@field After fun(time: number, callback: function)
---@field SetName fun(object: timer, name: string)
---@field RunNextTick fun(callback: function)
---@field AfterCombat fun(callback:function, id:any, ...: any)
local eventFrame = CreateFrame("frame")
eventFrame:RegisterEvent("PLAYER_REGEN_ENABLED")
eventFrame:SetScript("OnEvent", function(self, event)
if (event == "PLAYER_REGEN_ENABLED") then
for _, schedule in ipairs(DF.Schedules.AfterCombatSchedules.withoutId) do
xpcall(schedule.callback, geterrorhandler(), unpack(schedule.payload))
end
for _, schedule in pairs(DF.Schedules.AfterCombatSchedules.withId) do
xpcall(schedule.callback, geterrorhandler(), unpack(schedule.payload))
end
table.wipe(DF.Schedules.AfterCombatSchedules.withoutId)
table.wipe(DF.Schedules.AfterCombatSchedules.withId)
end
end)
local triggerScheduledLoop = function(tickerObject)
if (tickerObject:IsCancelled()) then
@@ -128,6 +151,31 @@ function DF.Schedules.Cancel(tickerObject)
end
end
--schedule a task to be executed when the player leaves combat
function DF.Schedules.AfterCombat(callback, id, ...)
local bInCombatLockdown = UnitAffectingCombat("player") or InCombatLockdown()
if (not bInCombatLockdown) then
xpcall(callback, geterrorhandler(), ...)
return
end
local payload = {...}
if (id) then
DF.Schedules.AfterCombatSchedules.withId[id] = {
callback = callback,
payload = payload,
id = id,
}
else
table.insert(DF.Schedules.AfterCombatSchedules.withoutId, {
callback = callback,
payload = payload,
})
end
end
--schedule a task with an interval of @time without payload
function DF.Schedules.After(time, callback)
C_Timer.After(time, callback)
+196 -195
View File
@@ -1,233 +1,234 @@
--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
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
function DF:CreateScrollBar(master, scrollContainer, x, y)
return DF:NewScrollBar(master, scrollContainer, x, y)
end
--note: this scroll bar is using legacy code and shouldn't be used on creating new stuff
do
function detailsFramework:CreateScrollBar(master, scrollContainer, x, y)
return detailsFramework:NewScrollBar(master, scrollContainer, x, y)
end
function DF:NewScrollBar(parent, scrollContainer, x, y)
local newSlider = CreateFrame("Slider", nil, parent, "BackdropTemplate")
newSlider.scrollMax = 560
function detailsFramework: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: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.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
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")
local upButton = CreateFrame("Button", nil, parent,"BackdropTemplate")
upButton:SetPoint("BOTTOM", newSlider, "TOP", 0, -12)
upButton.x = 0
upButton.y = -12
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()
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
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()
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
parent.baixo = downDutton
parent.cima = upButton
parent.slider = newSlider
downDutton:SetScript("OnMouseDown", function(self)
if (not newSlider:IsEnabled()) then
return
end
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 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 + 2 < maxValue) then
newSlider:SetValue(current + 2)
if (current + (parent.wheel_jump or 20) < maxValue) then
newSlider:SetValue(current + (parent.wheel_jump or 20))
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)
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)
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()
function newSlider:Altura(height)
self:SetHeight(height)
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
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
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
function newSlider:cimaPoint(x, y)
upButton:SetPoint("BOTTOM", newSlider, "TOP", x, y - 12)
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)
function newSlider:baixoPoint(x, y)
downDutton:SetPoint("TOP", newSlider, "BOTTOM", x, y + 12)
end
end
function newSlider:cimaPoint(x, y)
upButton:SetPoint("BOTTOM", newSlider, "TOP", x, y - 12)
return newSlider
end
function newSlider:baixoPoint(x, y)
downDutton:SetPoint("TOP", newSlider, "BOTTOM", x, y + 12)
end
return newSlider
end
+72
View File
@@ -0,0 +1,72 @@
--documentation for scrollbox.lua
--a scrollbox is a frame with a scrollbar and lines, these lines can be used to show data or show more frames in the case of a grid frame
--a grid of frames if a frame with lines and columns, each line can have multiple columns, a column is a frame
--------Start of the Grid Scroll Box Example--------
local parent = UIParent
local name = "GridScrollBoxExample"
--declare a function which receives a frame and the data which will be used to refresh it
local refreshOptionFunc = function(optionButton, data)
optionButton.text:SetText(data.text)
optionButton:SetScript("OnClick", function(self) print("clicked option " .. data.text) end)
optionButton:Show()
end
--declare a function to create a column within a scroll line
--this function will receive the line, the line index within the scrollbox and the column index within the line
local createOptionFrameFunc = function(line, lineIndex, columnIndex)
local optionButton = CreateFrame("button", "$parentOptionFrame" .. lineIndex .. columnIndex, line)
optionButton:SetSize(100, 20)
optionButton.text = optionButton:CreateFontString(nil, "overlay", "GameFontNormal")
optionButton.text:SetPoint("center", optionButton, "center", 0, 0)
optionButton.text:SetText("Option " .. lineIndex .. columnIndex)
local highlightTexture = optionButton:CreateTexture(nil, "highlight")
highlightTexture:SetAllPoints()
highlightTexture:SetColorTexture(1, 1, 1, 0.2)
DetailsFramework:ApplyStandardBackdrop(optionButton)
return optionButton
end
--when creatin a grid scrollbox, some of the settings for the grid is clared into a table to be passed as an argument
local options = {
width = 600,
height = 400,
--amount of horizontal lines
line_amount = 12,
--amount of columns per line
columns_per_line = 4,
--height of each line
line_height = 30,
auto_amount = false,
no_scroll = false,
no_backdrop = false,
}
--grid scrollbox data, can also be set with gridScrollBox:SetData(data) if the data is only available later on
--the data table is passed within the optionFrame when calling the refresh function
local data = {
{text = "1"}, {text = "2"}, {text = "3"}, {text = "4"}, {text = "5"}, {text = "6"}, {text = "7"}, {text = "8"}, {text = "9"}, {text = "10"},
{text = "11"}, {text = "12"}, {text = "13"}, {text = "14"}, {text = "15"}, {text = "16"}, {text = "17"}, {text = "18"}, {text = "19"}, {text = "20"},
{text = "21"}, {text = "22"}, {text = "23"}, {text = "24"}, {text = "25"}, {text = "26"}, {text = "27"}, {text = "28"}, {text = "29"}, {text = "30"},
{text = "31"}, {text = "32"}, {text = "33"}, {text = "34"}, {text = "35"}, {text = "36"}, {text = "37"}, {text = "38"}, {text = "39"}, {text = "40"},
{text = "41"}, {text = "42"}, {text = "43"}, {text = "44"}, {text = "45"}, {text = "46"}, {text = "47"}, {text = "48"}, {text = "49"}, {text = "50"},
{text = "51"}, {text = "52"}, {text = "53"}, {text = "54"}, {text = "55"}, {text = "56"}, {text = "57"}, {text = "58"}, {text = "59"}, {text = "60"},
{text = "61"}, {text = "62"}, {text = "63"}, {text = "64"}, {text = "65"}, {text = "66"}, {text = "67"}, {text = "68"}, {text = "69"}, {text = "70"},
{text = "71"}, {text = "72"}, {text = "73"}, {text = "74"}, {text = "75"}, {text = "76"}, {text = "77"}, {text = "78"}, {text = "79"}, {text = "80"},
{text = "81"}, {text = "82"}, {text = "83"}, {text = "84"}, {text = "85"}, {text = "86"}, {text = "87"}, {text = "88"}, {text = "89"}, {text = "90"},
{text = "91"}, {text = "92"}, {text = "93"}, {text = "94"}, {text = "95"}, {text = "96"}, {text = "97"}, {text = "98"}, {text = "99"}, {text = "100"},
}
--create the grid scrollbox
local gridScrollBox = DetailsFramework:CreateGridScrollBox(parent, name, refreshOptionFunc, data, createOptionFrameFunc, options)
gridScrollBox:SetPoint("center", parent, "center", 0, 0)
gridScrollBox:Refresh()
--------End of the Grid Scroll Box Example--------
+622
View File
@@ -0,0 +1,622 @@
---@type detailsframework
local detailsFramework = _G["DetailsFramework"]
if (not detailsFramework or not DetailsFrameworkCanLoad) then
return
end
local CreateFrame = CreateFrame
local GetSpellInfo = GetSpellInfo
local GameTooltip = GameTooltip
local unpack = unpack
---mixin to use with DetailsFramework:Mixin(table, detailsFramework.SortFunctions)
---add methods to be used on scrollframes
---@class df_scrollboxmixin
detailsFramework.ScrollBoxFunctions = {
--set a function to run right before the refresh function (scroll:Refresh())
--this function receives the same parameters as the refresh function
SetPreRefreshFunction = function(self, func)
self.pre_refresh_func = func
end,
---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
if (self.pre_refresh_func) then
detailsFramework:Dispatch(self.pre_refresh_func, self, self.data, offset, self.LineAmount)
end
--call the refresh function
detailsFramework:Dispatch(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
table.insert(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
if (self.OnSetData) then
detailsFramework:CoreDispatch((self:GetName() or "ScrollBox") .. ":OnSetData()", self.OnSetData, self, self.data)
end
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 = math.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, lineHeight, updateFunction)
local scrollbar = self:GetChildFramesFaux()
scrollbar:SetValue(value)
self.offset = math.floor((value / lineHeight) + 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,
}
---@class df_gridscrollbox_options : table
---@field width number?
---@field height number?
---@field line_amount number?
---@field line_height number?
---@field columns_per_line number?
---@field auto_amount boolean?
---@field no_scroll boolean?
---@field vertical_padding number?
---@field no_backdrop boolean?
---@type df_gridscrollbox_options
local grid_scrollbox_options = {
width = 600,
height = 400,
line_amount = 10,
line_height = 30,
columns_per_line = 4,
no_scroll = false,
vertical_padding = 1,
no_backdrop = false,
}
---@class df_gridscrollbox : df_scrollbox
---create a scrollbox with a grid layout
---@param parent frame
---@param name string
---@param refreshFunc function
---@param data table
---@param createColumnFrameFunc function
---@param options df_gridscrollbox_options?
---@return unknown
function detailsFramework:CreateGridScrollBox(parent, name, refreshFunc, data, createColumnFrameFunc, options)
options = options or {}
local width = options.width or grid_scrollbox_options.width
local height = options.height or grid_scrollbox_options.height
local lineAmount = options.line_amount or grid_scrollbox_options.line_amount
local lineHeight = options.line_height or grid_scrollbox_options.line_height
local columnsPerLine = options.columns_per_line or grid_scrollbox_options.columns_per_line
local autoAmount = options.auto_amount
local noScroll = options.no_scroll
local noBackdrop = options.no_backdrop
local verticalPadding = options.vertical_padding or grid_scrollbox_options.vertical_padding
local createLineFunc = function(scrollBox, lineIndex)
local line = CreateFrame("frame", "$parentLine" .. lineIndex, scrollBox)
line:SetSize(width, lineHeight)
line:SetPoint("top", scrollBox, "top", 0, -((lineIndex-1) * (lineHeight + verticalPadding)))
line.optionFrames = {}
for columnIndex = 1, columnsPerLine do
--dispatch payload: line, lineIndex, columnIndex
local optionFrame = createColumnFrameFunc(line, lineIndex, columnIndex)
line.optionFrames[columnIndex] = optionFrame
optionFrame:SetPoint("left", line, "left", (columnIndex-1) * (width/columnsPerLine), 0)
end
return line
end
local onSetData = function(self, data)
local newData = {}
for i = 1, #data, columnsPerLine do
local thisColumnData = {}
for o = 1, columnsPerLine do
local index = i + (o-1)
local thisData = data[index]
if (thisData) then
thisColumnData[#thisColumnData+1] = thisData
end
end
newData[#newData+1] = thisColumnData
end
self.data = newData
end
local refreshGrid = function(scrollBox, thisData, offset, totalLines)
for i = 1, totalLines do
local index = i + offset
local lineData = thisData[index]
if (lineData) then
local line = scrollBox:GetLine(i)
for o = 1, columnsPerLine do
local optionFrame = line.optionFrames[o]
local data = lineData[o]
if (data) then
detailsFramework:Dispatch(refreshFunc, optionFrame, data)
optionFrame:Show()
line:Show()
else
optionFrame:Hide()
end
end
end
end
end
local scrollBox = detailsFramework:CreateScrollBox(parent, name, refreshGrid, data, width, height, lineAmount, lineHeight, createLineFunc, autoAmount, noScroll, noBackdrop)
scrollBox:CreateLines(createLineFunc, lineAmount)
detailsFramework:ReskinSlider(scrollBox)
scrollBox.OnSetData = onSetData
onSetData(scrollBox, data)
return scrollBox
end
--aura scroll box
--default settings
local auraScrollDefaultSettings = {
line_height = 18,
line_amount = 18,
width = 300,
height = 500,
vertical_padding = 1,
show_spell_tooltip = false,
remove_icon_border = true,
no_scroll = false,
no_backdrop = false,
backdrop_onenter = {.8, .8, .8, 0.2},
backdrop_onleave = {.8, .8, .8, 0.4},
font_size = 12,
}
function detailsFramework:CreateAuraScrollBox(parent, name, refreshFunc, data, onAuraRemoveCallback, options)
--hack the construction of the options table here, as the scrollbox is created much later
local scrollOptions = {}
detailsFramework.OptionsFunctions.BuildOptionsTable(scrollOptions, auraScrollDefaultSettings, options)
options = scrollOptions.options
local refreshAuraLines = function(self, data, offset, totalLines)
for i = 1, totalLines do
local index = i + offset
local auraTable = data[index]
if (auraTable) then
local line = self:GetLine(i)
local spellId, spellName, spellIcon, lowerSpellName, flag = unpack(auraTable)
line.SpellID = spellId
line.SpellName = spellName
line.SpellNameLower = lowerSpellName
line.SpellIcon = spellIcon
line.Flag = flag
if (flag) then
line.name:SetText(spellName)
else
line.name:SetText(spellName .. "(" .. spellId .. ")")
end
line.icon:SetTexture(spellIcon)
if (options.remove_icon_border) then
line.icon:SetTexCoord(.1, .9, .1, .9)
else
line.icon:SetTexCoord(0, 1, 0, 1)
end
end
end
end
local onLeaveAuraLine = function(self)
self:SetBackdropColor(unpack(options.backdrop_onleave))
GameTooltip:Hide()
end
local onEnterAuraLine = function(line, capsule, value)
if (options.show_spell_tooltip and line.SpellID and GetSpellInfo(line.SpellID)) then
GameTooltip:SetOwner(line, "ANCHOR_CURSOR")
GameTooltip:SetSpellByID(line.SpellID)
GameTooltip:AddLine(" ")
GameTooltip:Show()
end
line:SetBackdropColor(unpack(options.backdrop_onenter))
local bAddedBySpellName = line.Flag
value = value or line.SpellID
if (not bAddedBySpellName) then
GameCooltip:Preset(2)
GameCooltip:SetOwner(line, "left", "right", 2, 0)
GameCooltip:SetOption("TextSize", 10)
local spellName, _, spellIcon = GetSpellInfo(value)
if (spellName) then
GameCooltip:AddLine(spellName .. " (" .. value .. ")")
GameCooltip:AddIcon(spellIcon, 1, 1, 14, 14, .1, .9, .1, .9)
end
GameCooltip:Show()
else
local spellName = GetSpellInfo(value)
if (spellName) then
local spellsWithSameName = db.aura_cache_by_name[string.lower(spellName)]
if (not spellsWithSameName) then
same_name_spells_add(value)
spellsWithSameName = db.aura_cache_by_name[string.lower(spellName)]
end
if (spellsWithSameName) then
GameCooltip:Preset(2)
GameCooltip:SetOwner(line, "left", "right", 2, 0)
GameCooltip:SetOption("TextSize", 10)
for i, spellId in ipairs(spellsWithSameName) do
local spellName, _, spellIcon = GetSpellInfo(spellId)
if (spellName) then
GameCooltip:AddLine(spellName .. "(" .. spellId .. ")")
GameCooltip:AddIcon(spellIcon, 1, 1, 14, 14, .1, .9, .1, .9)
end
end
GameCooltip:Show()
end
end
end
end
local onClickAuraRemoveButton = function(self)
local spellId = self:GetParent().SpellID
if (spellId and type(spellId) == "number") then
data[spellId] = nil
data["" .. (spellId or "")] = nil -- cleanup...
--button > line > scrollbox
self:GetParent():GetParent():DoRefresh()
if (onAuraRemoveCallback) then --upvalue
detailsFramework:QuickDispatch(onAuraRemoveCallback, spellId)
end
end
end
local createLineFunc = function(self, index)
local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate")
local scrollBoxWidth = options.width
local lineHeight = options.line_height
local verticalPadding = options.vertical_padding
line:SetPoint("topleft", self, "topleft", 1, -((index-1) * (lineHeight + verticalPadding)) - 1)
line:SetSize(scrollBoxWidth - 2, lineHeight)
line:SetScript("OnEnter", onEnterAuraLine)
line:SetScript("OnLeave", onLeaveAuraLine)
line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true})
line:SetBackdropColor(options.backdrop_onleave)
local iconTexture = line:CreateTexture("$parentIcon", "overlay")
iconTexture:SetSize(lineHeight - 2, lineHeight - 2)
local spellNameFontString = line:CreateFontString("$parentName", "overlay", "GameFontNormal")
detailsFramework:SetFontSize(spellNameFontString, options.font_size)
local removeButton = CreateFrame("button", "$parentRemoveButton", line, "UIPanelCloseButton")
removeButton:SetSize(16, 16)
removeButton:SetScript("OnClick", onClickAuraRemoveButton)
removeButton:SetPoint("topright", line, "topright", 0, 0)
removeButton:GetNormalTexture():SetDesaturated(true)
iconTexture:SetPoint("left", line, "left", 2, 0)
spellNameFontString:SetPoint("left", iconTexture, "right", 3, 0)
line.icon = iconTexture
line.name = spellNameFontString
line.removebutton = removeButton
return line
end
---@class df_aurascrollbox : df_scrollbox
---@field RefreshMe fun(self:df_aurascrollbox)
---@field TransformAuraData fun(self:df_aurascrollbox)
---@field data_original table
data = data or {}
local auraScrollBox = detailsFramework:CreateScrollBox(parent, name, refreshAuraLines, data, options.width, options.height, options.line_amount, options.line_height)
detailsFramework:ReskinSlider(auraScrollBox)
---@cast auraScrollBox df_aurascrollbox
function auraScrollBox:TransformAuraData()
local newData = {}
local added = {}
for spellId, bAddedBySpellName in pairs(self.data) do
local spellName, _, spellIcon = GetSpellInfo(spellId)
if (spellName and not added[tonumber(spellId) or 0]) then
local lowerSpellName = spellName:lower()
table.insert(newData, {spellId, spellName, spellIcon, lowerSpellName, bAddedBySpellName})
added[tonumber(spellId) or 0] = true
end
end
table.sort(newData, function(t1, t2) return t1[4] < t2[4] end)
self.data = newData
end
auraScrollBox.data_original = data
auraScrollBox.SetData = function(self, data)
self.data_original = data
self.data = data
auraScrollBox:TransformAuraData()
end
auraScrollBox.GetData = function(self)
return self.data_original
end
auraScrollBox:SetData(data)
end
+32
View File
@@ -223,6 +223,10 @@ DF:Mixin(DFSliderMetaFunctions, DF.ScriptHookMixin)
rawset(self, "FixedValue", value)
end
function DFSliderMetaFunctions:GetFixedParameter()
return rawget(self, "FixedValue")
end
--set value
function DFSliderMetaFunctions:SetValue(value)
return self(value)
@@ -799,6 +803,10 @@ local switch_set_fixparameter = function(self, value)
rawset(self, "FixedValue", value)
end
local switch_get_fixparameter = function(self)
return rawget(self, "FixedValue")
end
local switch_disable = function(self)
if (self.is_checkbox) then
self.checked_texture:Hide()
@@ -841,6 +849,10 @@ local set_switch_func = function(self, newFunction)
self.OnSwitch = newFunction
end
local get_switch_func = function(self)
return self.OnSwitch
end
local set_as_checkbok = function(self)
if self.is_checkbox and self.checked_texture then return end
local checked = self:CreateTexture(self:GetName() .. "CheckTexture", "overlay")
@@ -871,11 +883,29 @@ local set_as_checkbok = function(self)
end
end
---@class df_checkbox : df_button
---@field OnSwitch fun(self:df_checkbox, fixedValue:any, value:boolean)
---@field SetValue fun(self:df_button, value:boolean)
---@field GetValue fun(self:df_button):boolean
---@field SetFixedParameter fun(self:df_button, value:any)
---@field GetFixedParameter fun(self:df_button):any
---@field Disable fun(self:df_button)
---@field Enable fun(self:df_button)
---@field SetAsCheckBox fun(self:df_button)
---@field SetTemplate fun(self:df_button, template: table)
---@field GetSwitchFunction fun(self:df_button):function
---@field SetSwitchFunction fun(self:df_button, newOnSwitchFunction: function)
---@field GetCapsule fun(self:df_button):df_button capsule only exists in the actual frame of the encapsulated widget
function DF:CreateSwitch(parent, onSwitch, defaultValue, width, height, leftText, rightText, member, name, colorInverted, switchFunc, returnFunc, withLabel, switch_template, label_template)
local switch, label = DF:NewSwitch(parent, parent, name, member, width or 60, height or 20, leftText, rightText, defaultValue, colorInverted, switchFunc, returnFunc, withLabel, switch_template, label_template)
if (onSwitch) then
switch.OnSwitch = onSwitch
end
---@cast switch df_checkbox
---@cast label df_label
return switch, label
end
@@ -909,11 +939,13 @@ function DF:NewSwitch(parent, container, name, member, width, height, leftText,
slider.SetValue = switch_set_value
slider.GetValue = switch_get_value
slider.SetFixedParameter = switch_set_fixparameter
slider.GetFixedParameter = switch_get_fixparameter
slider.Disable = switch_disable
slider.Enable = switch_enable
slider.SetAsCheckBox = set_as_checkbok
slider.SetTemplate = DFSliderMetaFunctions.SetTemplate
slider.SetSwitchFunction = set_switch_func
slider.GetSwitchFunction = get_switch_func
if (member) then
parent[member] = slider
+4 -3
View File
@@ -957,6 +957,7 @@ DF.CrowdControlSpells = {
[15487] = "PRIEST", --Silence
[2094] = "ROGUE", --Blind
[427773] = "ROGUE", --Blind (AoE)
[1833] = "ROGUE", --Cheap Shot
[408] = "ROGUE", --Kidney Shot
[1766] = "ROGUE", --Kick
@@ -1448,15 +1449,15 @@ function DF:GetSpellsForEncounterFromJournal (instanceEJID, encounterEJID)
if (sectionInfo) then
if (sectionInfo.spellID and type(sectionInfo.spellID) == "number" and sectionInfo.spellID ~= 0) then
tinsert(spellIDs, sectionInfo.spellID)
table.insert(spellIDs, sectionInfo.spellID)
end
local nextChild, nextSibling = sectionInfo.firstChildSectionID, sectionInfo.siblingSectionID
if (nextSibling) then
tinsert(nextID, nextSibling)
table.insert(nextID, nextSibling)
end
if (nextChild) then
tinsert(nextID, nextChild)
table.insert(nextID, nextChild)
end
else
break
+53 -6
View File
@@ -245,8 +245,8 @@ detailsFramework.TextEntryCounter = detailsFramework.TextEntryCounter or 1
self.editbox:Disable()
self.editbox:SetBackdropBorderColor(.5, .5, .5, .5)
self.editbox:SetBackdropColor(.5, .5, .5, .5)
self.editbox:SetBackdropBorderColor(0, 0, 0, 1)
self.editbox:SetBackdropColor(.1, .1, .1, .834)
self.editbox:SetTextColor(.5, .5, .5, .5)
if (self.editbox.borderframe) then
@@ -531,8 +531,30 @@ end
------------------------------------------------------------------------------------------------------------
--object constructor
---@class df_textentry : table, frame
---@class df_textentry : editbox
---@field widget editbox
---@field tooltip any
---@field show any
---@field hide any
---@field width any
---@field height any
---@field text any
---@field multiline any
---@field align any
---@field SetTemplate fun(self:df_textentry, template:table)
---@field Disable fun(self:df_textentry)
---@field Enable fun(self:df_textentry)
---@field SetCommitFunction fun(self:df_textentry, func:function)
---@field SetNext fun(self:df_textentry, next:df_textentry)
---@field SetLabelText fun(self:df_textentry, text:string)
---@field SelectAll fun(self:df_textentry)
---@field SetAutoSelectTextOnFocus fun(self:df_textentry, value:boolean)
---@field Blink fun(self:df_textentry)
---@field SetText fun(self:df_textentry, text:string)
---@field GetText fun(self:df_textentry)
---@field SetEnterFunction fun(self:df_textentry, func:function, param1:any, param2:any)
---@field SetHook fun(self:df_textentry, hookName:string, func:function)
---@field SetAsSearchBox fun(self:df_textentry)
---@param parent frame
---@param textChangedCallback function
@@ -955,9 +977,34 @@ local set_speciallua_editor_font_size = function(borderFrame, newSize)
borderFrame.editboxlines:SetFont(file, newSize, flags)
end
---@class df_luaeditor : frame
---@field scroll scrollframe
---@field editbox editbox
---@field scrollnumberlines number
---@field editboxlines editbox
---@field SetTemplate fun(self:df_luaeditor, template:table)
---@field Disable fun(self:df_luaeditor)
---@field Enable fun(self:df_luaeditor)
---@field SetText fun(self:df_luaeditor, text:string)
---@field GetText fun(self:df_luaeditor):string
---@field SetTextSize fun(self:df_luaeditor, size:number)
---@field ClearFocus fun(self:df_luaeditor)
---@field SetFocus fun(self:df_luaeditor)
---create a text box to edit lua code
---if 'nointent' is true, the lua code will not be indented / highlighted / colored
---@param parent frame
---@param width number
---@param height number
---@param member string?
---@param name string?
---@param nointent boolean?
---@param showLineNumbers boolean?
---@param bNoName boolean?
---@return df_luaeditor
function detailsFramework:NewSpecialLuaEditorEntry(parent, width, height, member, name, nointent, showLineNumbers, bNoName)
if (not bNoName) then
if (name:find("$parent")) then
if (name and name:find("$parent")) then
local parentName = detailsFramework.GetParentName(parent)
name = name:gsub("$parent", parentName)
end
@@ -1061,13 +1108,13 @@ function detailsFramework:NewSpecialLuaEditorEntry(parent, width, height, member
--set the line text into a fontstring to get its width
local thisText = textInArray[i]
stringLengthFontString:SetText(thisText)
local lineTextLength = ceil(stringLengthFontString:GetStringWidth())
local lineTextLength = math.ceil(stringLengthFontString:GetStringWidth())
if (lineTextLength < maxStringWidth) then
resultText = resultText .. i .. "\n"
else
--if the text width is bigger than the editbox width, add a blank line into the line counter
local linesToOccupy = floor(lineTextLength / maxStringWidth)
local linesToOccupy = math.floor(lineTextLength / maxStringWidth)
local fillingText = i .. ""
for o = 1, linesToOccupy do
fillingText = fillingText .. "\n"
+25 -1
View File
@@ -11,6 +11,9 @@
--guadians: represents a npc, the server has the possess of the controller, don't accept commands like pets, helps attacking the enemies of the npc or player.
--role: is a string that represents the role of a unit, such as tank, healer, or damage dealer. only players can have a role.
---@alias auratype
---| "BUFF"
---| "DEBUFF"
---@alias role
---| "TANK"
@@ -305,7 +308,7 @@
---@field GetScale fun(self: uiobject) : scale|number
---@field GetAlpha fun(self: uiobject) : alpha|number
---@field GetSize fun(self: uiobject) : width|number, height|number
---@field GetParent fun(self: uiobject) : frame
---@field GetParent fun(self: uiobject) : any
---@field GetPoint fun(self: uiobject, index: number): string, frame, string, number, number
---@field GetCenter fun(self: uiobject): number, number
---@field SetPoint fun(self: uiobject, point: anchorpoint, relativeFrame: uiobject, relativePoint: anchorpoint, xOffset: number, yOffset: number)
@@ -363,6 +366,7 @@
---@field SetThickness fun(self: line, thickness: number)
---@class frame : uiobject
---@field __background texture
---@field CreateLine fun(self: frame, name: string?, drawLayer: drawlayer, templateName: string?, subLevel: number?) : line
---@field SetID fun(self: frame, id: number) set an ID for the frame
---@field SetAttribute fun(self: frame, name: string, value: any)
@@ -544,6 +548,7 @@
---@class texture : region
---@field SetDrawLayer fun(self: texture, layer: drawlayer, subLayer: number?)
---@field GetTexture fun(self: texture) : any
---@field SetTexture fun(self: texture, path: textureid|texturepath, horizontalWrap: texturewrap?, verticalWrap: texturewrap?, filter: texturefilter?)
---@field SetAtlas fun(self: texture, atlas: string)
---@field SetColorTexture fun(self: texture, r: red|number, g: green|number, b: blue|number, a: alpha|number?)
@@ -583,3 +588,22 @@
---@field GetBlendMode fun(self: texture) : string
---@field GetVertexColor fun(self: texture) : number, number, number, number
---@class editbox : frame
---@field SetText fun(self: editbox, text: string)
---@field GetText fun(self: editbox) : string
---@field SetCursorPosition fun(self: editbox, position: number)
---@field GetCursorPosition fun(self: editbox) : number
---@field SetMaxLetters fun(self: editbox, maxLetters: number)
---@field GetMaxLetters fun(self: editbox) : number
---@field SetNumeric fun(self: editbox, numeric: boolean)
---@field GetNumeric fun(self: editbox) : boolean
---@field SetMultiLine fun(self: editbox, multiLine: boolean)
---@field GetMultiLine fun(self: editbox) : boolean
---@field SetAutoFocus fun(self: editbox, autoFocus: boolean)
---@field GetAutoFocus fun(self: editbox) : boolean
---@field SetFont fun(self: editbox, font: string, size: number, flags: string)
---@field SetFontObject fun(self: editbox, fontString: fontstring)
---@field GetFont fun(self: editbox) : string, number, string
---@field SetTextColor fun(self: editbox, r: red|number, g: green|number, b: blue|number, a: alpha|number?)
---@field SetJustifyH fun(self:editbox, alignment:string)
---@field SetTextInsets fun(self:editbox, left:number, right:number, top:number, bottom:number)
@@ -367,7 +367,7 @@ do
[216331] = {cooldown = 120, duration = 20, specs = {65}, talent = false, charges = 1, class = "PALADIN", type = 1}, --Avenging Crusader
[31884] = {cooldown = 120, duration = 20, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 1}, --Avenging Wrath
[1044] = {cooldown = 25, duration = 8, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 5}, --Blessing of Freedom
[1022] = {cooldown = 300, duration = 10, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 3, shareid = 204018}, --Blessing of Protection
[1022] = {cooldown = 300, duration = 10, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 3, shareid = 1022}, --Blessing of Protection
[6940] = {cooldown = 120, duration = 12, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 3}, --Blessing of Sacrifice
[204018] = {cooldown = 180, duration = 10, specs = {66}, talent = false, charges = 1, class = "PALADIN", type = 3, shareid = 1022}, --Blessing of Spellwarding
[115750] = {cooldown = 90, duration = 6, specs = {65, 66, 70}, talent = false, charges = 1, class = "PALADIN", type = 8}, --Blinding Light
@@ -984,4 +984,4 @@ do
end
end)
loadLibDatabase()
end
end