diff --git a/Libs/DF/definitions.lua b/Libs/DF/definitions.lua index de2f49774..906d3d9eb 100644 --- a/Libs/DF/definitions.lua +++ b/Libs/DF/definitions.lua @@ -11,10 +11,18 @@ ---@field removeduplicate fun(tbl1:table, tbl2:table) remove the keys from table1 which also exists in table2 with the same value ---@field dump fun(tbl:table) : string dump a table to a string +---@alias templatetype +---| "font" +---| "dropdown" +---| "button" +---| "switch" +---| "slider" + ---@class detailsframework ---@field OptionsFunctions df_optionsmixin ---@field RoundedCornerPanelMixin df_roundedcornermixin ---@field Schedules df_schedule +---@field HeaderFunctions df_headerfunctions ---@field Math df_math ---@field table df_table_functions ---@field Dispatch fun(self:table, callback:function, ...) : any dispatch a function call using xpcall @@ -52,4 +60,11 @@ ---@field CreateDropDown fun(self:table, parent:frame, func:function, default:any, width:number?, height:number?, member:string?, name:string?, template:table?) : df_dropdown ---@field CreateTextEntry fun(self:table, parent:frame, textChangedCallback:function, width:number, height:number, member:string?, name:string?, labelText:string?, textentryTemplate:table?, labelTemplate:table?) : df_textentry ---@field ReskinSlider fun(self:table, slider:frame) +---@field GetAvailableSpells fun(self:table) : table +---@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 GetTemplate fun(self:table, templateType:templatetype, templateName:string) : table ---@field + diff --git a/Libs/DF/fw.lua b/Libs/DF/fw.lua index e43657702..6b1921367 100644 --- a/Libs/DF/fw.lua +++ b/Libs/DF/fw.lua @@ -1,6 +1,6 @@ -local dversion = 468 +local dversion = 470 local major, minor = "DetailsFramework-1.0", dversion local DF, oldminor = LibStub:NewLibrary(major, minor) @@ -1434,6 +1434,118 @@ function DF:GetSpellBookSpells() return spellNamesInSpellBook, spellIdsInSpellBook end +---return a table where keys are spellIds (number) and the value is true +---@return table +function DF:GetAvailableSpells() + local completeListOfSpells = {} + + --this line might not be compatible with classic + --local specId, specName, _, specIconTexture = GetSpecializationInfo(GetSpecialization()) + --local classNameLoc, className, classId = UnitClass("player") --not in use + local locPlayerRace, playerRace, playerRaceId = UnitRace("player") + + --get racials from the general tab + local generalTabIndex = 1 + local tabName, tabTexture, offset, numSpells, isGuild, offspecId = GetSpellTabInfo(generalTabIndex) + offset = offset + 1 + local tabEnd = offset + numSpells + for entryOffset = offset, tabEnd - 1 do + local spellType, spellId = GetSpellBookItemInfo(entryOffset, "player") + local spellData = LIB_OPEN_RAID_COOLDOWNS_INFO[spellId] + if (spellData) then + local raceId = spellData.raceid + if (raceId) then + if (type(raceId) == "table") then + if (raceId[playerRaceId]) then + spellId = C_SpellBook.GetOverrideSpell(spellId) + local spellName = GetSpellInfo(spellId) + local bIsPassive = IsPassiveSpell(spellId, "player") + if (spellName and not bIsPassive) then + completeListOfSpells[spellId] = true + end + end + + elseif (type(raceId) == "number") then + if (raceId == playerRaceId) then + spellId = C_SpellBook.GetOverrideSpell(spellId) + local spellName = GetSpellInfo(spellId) + local bIsPassive = IsPassiveSpell(spellId, "player") + if (spellName and not bIsPassive) then + completeListOfSpells[spellId] = true + end + end + end + end + end + end + + --get spells from the Spec spellbook + local amountOfTabs = GetNumSpellTabs() + for i = 2, amountOfTabs-1 do --starting at index 2 to ignore the general tab + local tabName, tabTexture, offset, numSpells, isGuild, offSpecId, shouldHide, specID = GetSpellTabInfo(i) + local bIsOffSpec = offSpecId ~= 0 + offset = offset + 1 + local tabEnd = offset + numSpells + for entryOffset = offset, tabEnd - 1 do + local spellType, spellId = GetSpellBookItemInfo(entryOffset, "player") + if (spellId) then + if (spellType == "SPELL") then + spellId = C_SpellBook.GetOverrideSpell(spellId) + local spellName = GetSpellInfo(spellId) + local bIsPassive = IsPassiveSpell(spellId, "player") + if (spellName and not bIsPassive) then + completeListOfSpells[spellId] = bIsOffSpec == false + end + end + end + end + end + + --get class shared spells from the spell book + --[=[ + local tabName, tabTexture, offset, numSpells, isGuild, offSpecId = GetSpellTabInfo(2) + local bIsOffSpec = offSpecId ~= 0 + offset = offset + 1 + local tabEnd = offset + numSpells + for entryOffset = offset, tabEnd - 1 do + local spellType, spellId = GetSpellBookItemInfo(entryOffset, "player") + if (spellId) then + if (spellType == "SPELL") then + spellId = C_SpellBook.GetOverrideSpell(spellId) + local spellName = GetSpellInfo(spellId) + local bIsPassive = IsPassiveSpell(spellId, "player") + + if (spellName and not bIsPassive) then + completeListOfSpells[spellId] = bIsOffSpec == false + end + end + end + end + --]=] + + local getNumPetSpells = function() + --'HasPetSpells' contradicts the name and return the amount of pet spells available instead of a boolean + return HasPetSpells() + end + + --get pet spells from the pet spellbook + local numPetSpells = getNumPetSpells() + if (numPetSpells) then + for i = 1, numPetSpells do + local spellName, _, unmaskedSpellId = GetSpellBookItemName(i, "pet") + if (unmaskedSpellId) then + unmaskedSpellId = C_SpellBook.GetOverrideSpell(unmaskedSpellId) + local bIsPassive = IsPassiveSpell(unmaskedSpellId, "pet") + if (spellName and not bIsPassive) then + completeListOfSpells[unmaskedSpellId] = true + end + end + end + end + + return completeListOfSpells +end + ------------------------------------------------------------------------------------------------------------------------ --flash animation @@ -4730,7 +4842,7 @@ end --[=[ DF:CoreDispatch(func, context, ...) - safe call a function making a error window with what caused, the context and traceback of the error + safe call a function making an error window with what caused, context and traceback of the error this func is only used inside the framework for sensitive calls where the func must run without errors @func = the function which will be called @context = what made the function be called diff --git a/Libs/DF/keybind.lua b/Libs/DF/keybind.lua index b7404d97b..d1fdab0b1 100644 --- a/Libs/DF/keybind.lua +++ b/Libs/DF/keybind.lua @@ -6,18 +6,84 @@ end local _ local CreateFrame = CreateFrame +local GetSpellInfo = GetSpellInfo +local unpack = unpack + +---@class df_keybindscroll : df_scrollbox +---@field UpdateScroll fun(self:df_keybindscroll) + +---@class df_keybinddata : table ---@class df_keybindframe : frame, df_optionsmixin ---@field options table +---@field data table +---@field keybindData table +---@field Header df_headerframe +---@field actionId number? the actionId is the spell Id or an actionId or a macro text +---@field button button? the button which got clicked to start editing a keybind +---@field bIsListening boolean if the frame is wayting the user to press a keybind (listening key inputs) ---@field bIsKeybindFrame boolean ----@field CreateSpecButtons fun(self:df_keybindframe) +---@field keybindScroll df_keybindscroll +---@field keybindListener frame +---@field callback function +---@field CreateKeybindScroll fun(self:df_keybindframe) +---@field CreateKeybindListener fun(self:df_keybindframe) +---@field GetListeningActionId fun(self:df_keybindframe) : number +---@field GetListeningState fun(self:df_keybindframe) : boolean, number, button +---@field GetKeybindData fun(self:df_keybindframe) : df_keybinddata +---@field GetKeybindListener fun(self:df_keybindframe) : frame +---@field GetKeybindScroll fun(self:df_keybindframe) : df_keybindscroll +---@field GetKeybindCallback fun(self:df_keybindframe):function +---@field IsListening fun(self:df_keybindframe) : boolean +---@field OnKeybindChanged fun(self:df_keybindframe, actionId:number, keybind:string?) +---@field SaveKeybind fun(self:df_keybindframe, key:string) +---@field SetListeningState fun(self:df_keybindframe, value:boolean, actionId:number?, button:button?) +---@field SetKeybindData fun(self:df_keybindframe, keybindData:table) +---@field SetKeybindCallback fun(self:df_keybindframe, callback:function) ---@field SwitchSpec fun(self:button, button:string, newSpecId:number) +---@field CreateKeybindScrollLine fun(self:df_keybindframe, index:number) +---@field ClearKeybind fun(self:df_keybindframe, actionId:number) +---@field + +---@class keybind_scroll_data : table +---@field key1 spellname +---@field key2 textureid +---@field key3 any +---@field key4 string keybind +---@field key5 boolean is available +---@field key6 number sort value + +detailsFramework:NewColor("BLIZZ_OPTIONS_COLOR", 1, 0.8196, 0, 1) -local mainStartX, mainStartY, mainHeightSize = 10, -100, 600 +local DARK_BUTTON_TEMPLATE = detailsFramework:InstallTemplate("button", "DARK_BUTTON_TEMPLATE", {backdropcolor = {.1, .1, .1, .7}}, "OPTIONS_BUTTON_TEMPLATE") local default_options = { - width = 800, - height = 600, + width = 550, + height = 500, + scroll_width = 550 - 10, + scroll_height = 500 - 20, + amount_lines = 18, + line_height = 26, + show_spells = true, + show_unitcontrols = true, + can_modify_keybind_data = true, --if false, won't change the data table passed on the constructor or the one returned by GetKeybindData +} + +local headerTable = { + {text = "", width = 34}, --spell icon + {text = "Ability Name", width = 200}, + {text = "Keybind", width = 260}, + {text = "Clear", width = 40}, +} +local headerOptions = { + padding = 2, +} + +---@type {name: string, keybind: string, icon: string, localizedName: string}[] +local unitControlKeybinds = { + {name = "target", localizedName = TARGET, keybind = "type1", icon = [[Interface\MINIMAP\TRACKING\Target]]}, --default: left mouse button + {name = "menu", localizedName = "menu", keybind = "type2", icon = [[Interface\BUTTONS\UI-GuildButton-PublicNote-Up]]}, --default: right mouse button + {name = "focus", localizedName = FOCUS, keybind = "type3", icon = [[Interface\MINIMAP\TRACKING\Focus]]} --default: middle mouse button } local defaultSpecKeybindList = { @@ -30,12 +96,12 @@ local defaultSpecKeybindList = { [1468] = { {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, - {key = "type3", action = "_taunt", actiontext = ""}, + {key = "type3", action = "_taunt", actiontext = ""}, }, [1473] = { --aug {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, - {key = "type3", action = "_taunt", actiontext = ""}, + {key = "type3", action = "_taunt", actiontext = ""}, }, }, @@ -44,7 +110,7 @@ local defaultSpecKeybindList = { {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, {key = "type3", action = "_taunt", actiontext = ""}, - }, + }, [581] = {--> vengeance demon hunter {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, @@ -111,7 +177,7 @@ local defaultSpecKeybindList = { [260] = { --> rogue combat {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, - }, + }, [261] = { --> rogue sub {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, @@ -145,7 +211,7 @@ local defaultSpecKeybindList = { }, [254] = { --> hunter marks {key = "type1", action = "_target", actiontext = ""}, - }, + }, [255] = { --> hunter survivor {key = "type1", action = "_target", actiontext = ""}, }, @@ -214,16 +280,16 @@ local defaultSpecKeybindList = { {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, {key = "type3", action = "_taunt", actiontext = ""}, - }, + }, [269] = {--> monk ww {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_interrupt", actiontext = ""}, {key = "type3", action = "_taunt", actiontext = ""}, - }, + }, [270] = {--> monk mw {key = "type1", action = "_target", actiontext = ""}, {key = "type2", action = "_dispel", actiontext = ""}, - }, + }, }, } @@ -236,7 +302,7 @@ local ignoredKeys = { ["RALT"] = true, ["UNKNOWN"] = true, } -local mouseKeys = { +local mouseButtonToClickType = { ["LeftButton"] = "type1", ["RightButton"] = "type2", ["MiddleButton"] = "type3", @@ -254,7 +320,7 @@ local mouseKeys = { ["Button15"] = "type15", ["Button16"] = "type16", } -local keysToMouse = { +local clickTypeToMouseButton = { ["type1"] = "LeftButton", ["type2"] = "RightButton", ["type3"] = "MiddleButton", @@ -273,6 +339,56 @@ local keysToMouse = { ["type16"] = "Button16", } +local clickTypeAlias = { + ["type1"] = "Left Mouse Button", + ["type2"] = "Right Mouse Button", + ["type3"] = "Middle Mouse Button", + ["type4"] = "Mouse Button 4", + ["type5"] = "Mouse Button 5", + ["type6"] = "Mouse Button 6", + ["type7"] = "Mouse Button 7", + ["type8"] = "Mouse Button 8", + ["type9"] = "Mouse Button 9", + ["type10"] = "Mouse Button 10", + ["type11"] = "Mouse Button 11", + ["type12"] = "Mouse Button 12", + ["type13"] = "Mouse Button 13", + ["type14"] = "Mouse Button 14", + ["type15"] = "Mouse Button 15", + ["type16"] = "Mouse Button 16", +} + +local tauntList = { + ["DEATHKNIGHT"] = 56222, --Dark Command + ["DEMONHUNTER"] = 185245, --Torment + ["WARRIOR"] = 355, --Taunt + ["PALADIN"] = 62124, --Hand of Reckoning + ["MONK"] = 115546, --Provoke + ["DRUID"] = 6795, --Growl +} + +local interruptList = { + ["DEATHKNIGHT"] = 47528, --Mind Freeze + ["DEMONHUNTER"] = 183752, --Consume Magic + ["WARRIOR"] = 6552, --Pummel + ["PALADIN"] = 96231, --Rebuke + ["MONK"] = 116705, --Spear Hand Strike + ["HUNTER"] = 147362, --Counter Shot + ["MAGE"] = 2139, --Counterspell + ["DRUID"] = 106839, --Skull Bash - + ["ROGUE"] = 1766, --Kick + ["SHAMAN"] = 57994, --Wind Shear + ["PRIEST"] = 15487, --Silence +} + +local dispelList = { + ["PALADIN"] = {[65] = 4987, [66] = 213644, [70] = 213644}, --Cleanse - Cleanse Toxins - so holy tem 'cleanse' tank e dps tem o toxins + ["MONK"] = 115450, --Detox + ["DRUID"] = {[102] = 2782, [103] = 2782, [104] = 2782, [105] = 88423}, --Nature's Cure - Remove Corruption -so restoration tem o natures cure + ["SHAMAN"] = {[262] = 51886, [263] = 51886, [264] = 77130}, --elemental melee Cleanse Spirit - resto Purify Spirit + ["PRIEST"] = {[256] = 527, [257] = 527, [258] = 213634}, --Purify holy disc - Purify Disease shadow +} + local lock_textentry = { ["_target"] = true, ["_taunt"] = true, @@ -282,178 +398,239 @@ local lock_textentry = { ["_macro"] = false, } +local roundedCornerPreset = { + roundness = 5, + color = {.075, .075, .075, 0.98}, + border_color = {.05, .05, .05, 0}, +} + --> helpers local getMainFrame = function(UIObject) + if (UIObject.bIsKeybindFrame) then + return UIObject + end + local parentFrame = UIObject:GetParent() + for i = 1, 5 do if (parentFrame.bIsKeybindFrame) then return parentFrame end parentFrame = parentFrame:GetParent() end - return nil end +---@class df_keybindmixin detailsFramework.KeybindMixin = { - IsListening = false, - EditingSpec = 0, + bIsListening = false, CurrentKeybindEditingSet = {}, - AllSpecButtons = {}, - - SwitchSpec = function(self, button, newSpecId) --switch_spec - self.EditingSpec = newSpecId - self.CurrentKeybindEditingSet = EnemyGridDBChr.KeyBinds[newSpecId] --!need to get from the addon database - - for _, button in ipairs (self.AllSpecButtons) do - button.selectedTexture:Hide() - end - self.MyObject.selectedTexture:Show() - + + ---and the player change spec, the list of spells will change, hence need to update the keybind list if the panel is open + --if isn't open, the keybinds will be updated when the panel is opened + OnSpecChanged = function(self, button, newSpecId) --switch_spec --quick hide and show as a feedback to the player that the spec was changed - C_Timer.After (.04, function() EnemyGridOptionsPanelFrameKeybindScroill:Hide() end) --!need to defined the scroll frame - C_Timer.After (.06, function() EnemyGridOptionsPanelFrameKeybindScroill:Show() end) --!need to defined the scroll frame - - --atualiza a scroll - EnemyGridOptionsPanelFrameKeybindScroill:UpdateScroll() --!need to defined the scroll frame + --C_Timer.After (.04, function() EnemyGridOptionsPanelFrameKeybindScroill:Hide() end) --!need to defined the scroll frame + --C_Timer.After (.06, function() EnemyGridOptionsPanelFrameKeybindScroill:Show() end) --!need to defined the scroll frame + --EnemyGridOptionsPanelFrameKeybindScroill:UpdateScroll() --!need to defined the scroll frame end, - CreateSpecButtons = function(self) - local specsTitle = detailsFramework:CreateLabel(self, "Config keys for spec:", 12, "silver") - specsTitle:SetPoint("topleft", self, "topleft", 10, mainStartY) + ---return true if the keybindFrame is waiting for the player to press a keybind + ---@param self df_keybindframe + ---@return boolean bIsListening + IsListening = function(self) + return self.bIsListening + end, - local allSpecButtons = self.AllSpecButtons + ---return the actionId which the frame is currently listening for a keybind + ---@param self df_keybindframe + GetListeningActionId = function(self) + return self.actionId + end, - local options_text_template = detailsFramework:GetTemplate("font", "OPTIONS_FONT_TEMPLATE") - local options_dropdown_template = detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE") - local options_switch_template = detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_TEMPLATE") - local options_slider_template = detailsFramework:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE") - local options_button_template = detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE") + ---set the keybindFrame to listen for a keybind + ---@param self df_keybindframe + ---@param value boolean + ---@param actionId number? + ---@param button button? + SetListeningState = function(self, value, actionId, button) + self.bIsListening = value + self.actionId = actionId + self.button = button + end, - for i = 1, 4 do - local newSpecButton = detailsFramework:CreateButton(self, self.SwitchSpec, 160, 20, "Spec1 Placeholder Text", 1, nil, nil, "specButton" .. i, nil, 0, options_button_template, options_text_template) - table.insert(allSpecButtons, newSpecButton) - self["SpecButton" .. i] = newSpecButton - - newSpecButton:SetPoint("topleft", specsTitle, "bottomleft", 0, -10 + (20*(i-1))) - spec2:SetPoint ("topleft", specsTitle, "bottomleft", 0, -30) - spec3:SetPoint ("topleft", specsTitle, "bottomleft", 0, -50) - if (class == "DRUID") then - spec4:SetPoint ("topleft", specsTitle, "bottomleft", 0, -70) - end - end + ---get the listening state + ---@param self df_keybindframe + ---@return boolean + ---@return number + ---@return button + GetListeningState = function(self) + return self.bIsListening, self.actionId, self.button + end, - local classLocName, class = UnitClass("player") - local i = 1 - for specId in pairs(defaultSpecKeybindList[class]) do - local button = self["SpecButton" .. i] - local _, specName, _, specIcon = DF.GetSpecializationInfoByID(specId) --classic return nil - - if (specName) then - button.text = specName - button:SetClickFunction(self.SwitchSpec, specId) - button:SetIcon(specIcon) - button.specID = specId - - local selectedTexture = button:CreateTexture(nil, "background") - selectedTexture:SetAllPoints() - selectedTexture:SetColorTexture(1, 1, 1, 0.5) - if (specId ~= self.EditingSpec) then - selectedTexture:Hide() - end + ---return the frame which wait for keybinds + ---@param self df_keybindframe + ---@return frame + GetKeybindListener = function(self) + return self.keybindListener + end, - button.selectedTexture = selectedTexture - i = i + 1 - else - button:Hide() - end - end + ---get the scroll frame + ---@param self df_keybindframe + ---@return df_keybindscroll + GetKeybindScroll = function(self) + return self.keybindScroll + end, + + ---keybind listener is the frame which reads the key pressed by the player when setting a keybind for an ability + CreateKeybindListener = function(self) + local keybindListener = CreateFrame ("frame", nil, self, "BackdropTemplate") + keybindListener:SetFrameStrata("tooltip") + keybindListener:SetSize(200, 60) + detailsFramework:ApplyStandardBackdrop(keybindListener) + self.keybindListener = keybindListener + + keybindListener.text = detailsFramework:CreateLabel(keybindListener, "- Press a keyboard key to bind.\n- Click to bind a mouse button.\n- Press escape to cancel.", 11, "orange") + keybindListener.text:SetPoint("center", keybindListener, "center", 0, 0) + keybindListener:Hide() end, - CreateKeybindListener = function(self) - local enter_the_key = CreateFrame ("frame", nil, self, "BackdropTemplate") - enter_the_key:SetFrameStrata("tooltip") - enter_the_key:SetSize(200, 60) - detailsFramework:ApplyStandardBackdrop(enter_the_key) - enter_the_key.text = detailsFramework:CreateLabel(enter_the_key, "- Press a keyboard key to bind.\n- Click to bind a mouse button.\n- Press escape to cancel.", 11, "orange") - enter_the_key.text:SetPoint("center", enter_the_key, "center", 0, 0) - enter_the_key:Hide() + ---callback from the clear button + ---@param self button + ---@param button any + ---@param keyBindFrame df_keybindframe + ClearKeybind = function(self, button, actionId, keyBindFrame) + local keybindData = keyBindFrame:GetKeybindData() + keybindData[actionId] = nil + keyBindFrame:OnKeybindChanged(actionId, nil) + local keybindScroll = keyBindFrame:GetKeybindScroll() + keybindScroll:UpdateScroll() + end, + + ---comment + ---@param self df_keybindframe + ---@param key any + SaveKeybind = function(self, key) --where this is called? : from OnClickSetKeybindButton and from OnKeyDown() script + --if the player presses a control key, ignore it + if (ignoredKeys[key]) then + return + end + local keybindListener = self:GetKeybindListener() + --exit the process if 'esc' is pressed + if (key == "ESCAPE") then + self:SetListeningState(false) + keybindListener:Hide() + self:SetScript("OnKeyDown", nil) + return + end - end, + local modifier = (IsShiftKeyDown() and "SHIFT-" or "") .. (IsControlKeyDown() and "CTRL-" or "") .. (IsAltKeyDown() and "ALT-" or "") + local newKeybind = modifier .. key + local bIsListening, actionId, frameButton = self:GetListeningState() - set_keybind_key = function(self, button, keybindIndex) - if (keyBindListener.IsListening) then - key = mouseKeys [button] or button - return registerKeybind (keyBindListener, key) + if (self.options.can_modify_keybind_data) then + ---@type table + local keybindData = self:GetKeybindData() --from savedVariables + keybindData[actionId] = newKeybind end - keyBindListener.IsListening = true - keyBindListener.keybindIndex = keybindIndex - keyBindListener:SetScript ("OnKeyDown", registerKeybind) - - enter_the_key:Show() - enter_the_key:SetPoint ("bottom", self, "top") + + self:OnKeybindChanged(actionId, newKeybind) + + self:SetListeningState(false) + self:SetScript("OnKeyDown", nil) + keybindListener:Hide() + + --dumpt({"modifier", modifier, "newKeybind", newKeybind, "actionId", actionId}) + + local keybindScroll = self:GetKeybindScroll() + keybindScroll:UpdateScroll() + end, + + ---callback for the OnClickSetKeybindButton function on the scrollframe + ---@param self button + ---@param button any + ---@param actionId number + ---@param keyBindFrame df_keybindframe + OnClickSetKeybindButton = function(self, button, actionId, keyBindFrame) + local bIsListening, _, frameButton = keyBindFrame:GetListeningState() + + --if the listener is already listening for a keybind while the player clicks on another OnClickSetKeybindButton button, then cancel the previous listener + if (bIsListening and (self == frameButton)) then + --if the frame is already listening, it could be a mouse click to set the keybind + local clickType = mouseButtonToClickType[button] + print("mouse click:", button, clickType) + keyBindFrame:SaveKeybind(clickType) + return + end + + keyBindFrame:SetListeningState(true, actionId, self) + keyBindFrame:SetScript("OnKeyDown", keyBindFrame.SaveKeybind) + + local keybindListener = keyBindFrame:GetKeybindListener() + keybindListener:ClearAllPoints() + keybindListener:SetPoint("bottom", self, "top", 0, 0) + keybindListener:Show() end, - RefreshKeybindScroll = function(self, data, offset, totalLines) + RefreshKeybindScroll = function(self, scrollData, offset, totalLines) --~refresh local keyBindFrame = getMainFrame(self) - local keybinds = keyBindFrame.CurrentKeybindEditingSet for i = 1, totalLines do local index = i + offset - local keybindData = data[index] + local keybindScrollData = scrollData[index] - if (keybindData) then + if (keybindScrollData) then local line = self:GetLine(i) - --index - line.Index.text = index - - --keybind - local keyBindText = keysToMouse[keybindData.key] or keybindData.key - - keyBindText = keyBindText:gsub("type1", "LeftButton") - keyBindText = keyBindText:gsub("type2", "RightButton") - keyBindText = keyBindText:gsub("type3", "MiddleButton") - - line.KeyBind.text = keyBindText - line.KeyBind:SetClickFunction(keyBindFrame.set_keybind_key, index, nil, "left") - line.KeyBind:SetClickFunction(keyBindFrame.set_keybind_key, index, nil, "right") + + --actionId can be a actionId or an action name, e.g. "target" + ---@type string, number, number, string, boolean + local actionName, iconTexture, actionId, keybind, bIsAvailable = unpack(keybindScrollData) + + --if the keybind isn't set, it is an empty string + local keyBindText = keybind + keyBindText = keyBindText:gsub("type1", "Left Mouse Button") + keyBindText = keyBindText:gsub("type2", "Right Mouse Button") + keyBindText = keyBindText:gsub("type3", "Middle Mouse Button") + keyBindText = keyBindText:gsub("type4", "Mouse Button 4") + keyBindText = keyBindText:gsub("type5", "Mouse Button 5") + keyBindText = keyBindText:gsub("%-", " - ") + + line.setKeybindButton.text = keyBindText + line.setKeybindButton:SetClickFunction(keyBindFrame.OnClickSetKeybindButton, actionId, keyBindFrame, "left") + line.setKeybindButton:SetClickFunction(keyBindFrame.OnClickSetKeybindButton, actionId, keyBindFrame, "right") + + line.clearKeybindButton:SetClickFunction(keyBindFrame.ClearKeybind, actionId, keyBindFrame) + + line.spellIconTexture:SetTexture(iconTexture) + line.spellIconTexture:SetDesaturated(not bIsAvailable) + line.spellIconTexture:SetTexCoord(.1, .9, .1, .9) + line.spellNameFontString:SetText(actionName) --action - line.ActionDrop:SetFixedParameter(index) - line.ActionDrop:Select(keybindData.action) + --line.ActionDrop:SetFixedParameter(index) + --line.ActionDrop:Select(keybindData.action) --action text - line.ActionText.text = keybindData.actiontext - line.ActionText:SetEnterFunction(set_action_text, index) - line.ActionText.CurIndex = index - - if (lock_textentry[keybindData.action]) then - line.ActionText:Disable() + --line.ActionText.text = keybind --keybindData.actiontext + --line.ActionText:SetEnterFunction(set_action_text, index) + --line.ActionText.CurIndex = index + + if (lock_textentry[keybindScrollData.action]) then + --line.ActionText:Disable() else - line.ActionText:Enable() + --line.ActionText:Enable() end - - --delete - line.Delete:SetClickFunction(keyBindFrame.delete_keybind, index) end end end, - delete_keybind = function(self, button, keybindIndex) - local keyBindFrame = getMainFrame(self) - tremove(keyBindFrame.CurrentKeybindEditingSet, keybindIndex) - keyBindFrame.keybindScroll:UpdateScroll() - --EnemyGrid.UpdateKeyBinds() - end, - change_key_action = function(self, keybindIndex, value) local keyBindFrame = getMainFrame(self) local keybind = keyBindFrame.CurrentKeybindEditingSet[keybindIndex] keybind.action = value keyBindFrame.keybindScroll:UpdateScroll() - --EnemyGrid.UpdateKeyBinds() end, set_action_on_espace_press = function (textentry, capsule) @@ -461,63 +638,91 @@ detailsFramework.KeybindMixin = { capsule = capsule or textentry.MyObject local keybind = keyBindFrame.CurrentKeybindEditingSet[capsule.CurIndex] textentry:SetText (keybind.actiontext) - --EnemyGrid.UpdateKeyBinds() - end, + end, fill_action_dropdown = function(dropdownObject) local keyBindFrame = getMainFrame(dropdownObject) - local locClass, class = UnitClass("player") - - local taunt = tauntList[class] and GetSpellInfo(tauntList[class]) or "" - local interrupt = interruptList[class] and GetSpellInfo(interruptList [class]) or "" - local dispel = dispelList[class] - - if (type (dispel) == "table") then - local dispelString = "\n" - for specId, spellid in pairs(dispel) do - local _, specName = GetSpecializationInfoByID(specId) --!classic versions incompatible - local spellName = GetSpellInfo(spellid) - dispelString = dispelString .. "|cFFE5E5E5" .. specName .. "|r: |cFFFFFFFF" .. spellName .. "\n" - end - dispel = dispelString - else - dispel = GetSpellInfo(dispel) or "" - end - + return { {value = "_target", label = "Target", onclick = keyBindFrame.change_key_action, desc = "Target the unit"}, - {value = "_taunt", label = "Taunt", onclick = keyBindFrame.change_key_action, desc = "Cast the taunt spell for your class\n\n|cFFFFFFFFSpell: " .. taunt}, - {value = "_interrupt", label = "Interrupt", onclick = keyBindFrame.change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. interrupt}, - {value = "_dispel", label = "Dispel", onclick = keyBindFrame.change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. dispel}, + --{value = "_taunt", label = "Taunt", onclick = keyBindFrame.change_key_action, desc = "Cast the taunt spell for your class\n\n|cFFFFFFFFSpell: " .. taunt}, + --{value = "_interrupt", label = "Interrupt", onclick = keyBindFrame.change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. interrupt}, + --{value = "_dispel", label = "Dispel", onclick = keyBindFrame.change_key_action, desc = "Cast the interrupt spell for your class\n\n|cFFFFFFFFSpell: " .. dispel}, {value = "_spell", label = "Cast Spell", onclick = keyBindFrame.change_key_action, desc = "Type the spell name in the text box"}, {value = "_macro", label = "Macro", onclick = keyBindFrame.change_key_action, desc = "Type your macro in the text box"}, } end, - ---@param keyBindFrame df_keybindframe + ---run when the mouse enters a scroll line + OnEnterScrollLine = function(self) + local highlightTexture = self.highlightTexture + if (not highlightTexture) then + highlightTexture = self:GetParent().highlightTexture + end + highlightTexture:Show() + end, + + ---run when the mouse leaves a scroll line + OnLeaveScrollLine = function(self) + local highlightTexture = self.highlightTexture + if (not highlightTexture) then + highlightTexture = self:GetParent().highlightTexture + end + highlightTexture:Hide() + end, + + ---@param keybindScroll frame ---@param index number - CreateKeybindScrollLine = function(keyBindFrame, index) + CreateKeybindScrollLine = function(keybindScroll, index) --~create + local keyBindFrame = getMainFrame(keybindScroll) local line = CreateFrame("frame", "$parentLine" .. index, keybindScroll) - line:SetSize(1009, 20) - line:SetPoint("topleft", keyBindFrame, "topleft", 0, -(index-1)*29) - detailsFramework:ApplyStandardBackdrop(line, index % 2 == 0) + line:SetSize(keyBindFrame.options.width - 10, keyBindFrame.options.line_height) + line:SetPoint("topleft", keyBindFrame, "topleft", 1, -22 - (index-1) * keyBindFrame.options.line_height) + line:EnableMouse(true) + + --detailsFramework:ApplyStandardBackdrop(line, index % 2 == 0) + --line:SetBackdropBorderColor(0, 0, 0, 0) + + line.highlightTexture = line:CreateTexture(nil, "border") + line.highlightTexture:SetAllPoints() + line.highlightTexture:SetColorTexture(1, 1, 1, .1) + line.highlightTexture:Hide() + + line:SetScript("OnEnter", keyBindFrame.OnEnterScrollLine) + line:SetScript("OnLeave", keyBindFrame.OnLeaveScrollLine) + detailsFramework:Mixin(line, detailsFramework.HeaderFunctions) - + local options_text_template = detailsFramework:GetTemplate("font", "OPTIONS_FONT_TEMPLATE") local options_dropdown_template = detailsFramework:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE") local options_switch_template = detailsFramework:GetTemplate("switch", "OPTIONS_CHECKBOX_TEMPLATE") local options_slider_template = detailsFramework:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE") local options_button_template = detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE") - line.Index = detailsFramework:CreateLabel(line, "place holder") - line.KeyBind = detailsFramework:CreateButton(line, function()end, 100, 20, "", nil, nil, nil, "SetNewKeybindButton", "$parentSetNewKeybindButton", 0, options_button_template, options_text_template) - line.ActionDrop = detailsFramework:CreateDropDown(line, keyBindFrame.fill_action_dropdown, 0, 120, 20, "ActionDropdown", "$parentActionDropdown", options_dropdown_template) - line.ActionText = detailsFramework:CreateTextEntry(line, function()end, 660, 20, "TextBox", "$parentActionText", nil, options_dropdown_template) - line.Delete = detailsFramework:CreateButton(line, keyBindFrame.delete_keybind, 16, 20, "", nil, nil, nil, "DeleteKeybindButton", "$parentDeleteKeybindButton", 2, options_button_template, options_text_template) - line.Delete:SetIcon([[Interface\Buttons\UI-StopButton]], nil, nil, nil, nil, nil, nil, 4) - line.Delete.tooltip = "erase this keybind" - + line.spellIconTexture = line:CreateTexture("$parentIcon", "overlay") + line.spellIconTexture:SetSize(keyBindFrame.options.line_height - 2, keyBindFrame.options.line_height - 2) + + line.spellNameFontString = line:CreateFontString("$parentName", "overlay", "GameFontNormal") + detailsFramework:SetFontColor(line.spellNameFontString, "BLIZZ_OPTIONS_COLOR") + detailsFramework:SetFontSize(line.spellNameFontString, 12) + + line.setKeybindButton = detailsFramework:CreateButton(line, function()end, headerTable[3].width, keyBindFrame.options.line_height-2, "", nil, nil, nil, "SetNewKeybindButton", "$parentSetNewKeybindButton", 0, DARK_BUTTON_TEMPLATE_, options_text_template) + detailsFramework:AddRoundedCornersToFrame(line.setKeybindButton, roundedCornerPreset) + line.setKeybindButton.textcolor = "white" + line.setKeybindButton.textsize = 10 + line.setKeybindButton:SetHook("OnEnter", keyBindFrame.OnEnterScrollLine) + line.setKeybindButton:SetHook("OnLeave", keyBindFrame.OnLeaveScrollLine) + + --line.ActionDrop = detailsFramework:CreateDropDown(line, keyBindFrame.fill_action_dropdown, 0, 120, 20, "ActionDropdown", "$parentActionDropdown", options_dropdown_template) + --line.ActionText = detailsFramework:CreateTextEntry(line, function()end, 660, 20, "TextBox", "$parentActionText", nil, options_dropdown_template) + + line.clearKeybindButton = detailsFramework:CreateButton(line, keyBindFrame.ClearKeybind, 16, keyBindFrame.options.line_height-2, "", nil, nil, nil, "DeleteKeybindButton", "$parentDeleteKeybindButton", 2, DARK_BUTTON_TEMPLATE_, options_text_template) + line.clearKeybindButton:SetBackdropBorderColor(0, 0, 0, 0) + line.clearKeybindButton:SetIcon([[Interface\Buttons\UI-StopButton]], nil, nil, nil, nil, nil, nil, 4) + line.clearKeybindButton.tooltip = "erase this keybind" + --editbox + --[=[ line.ActionText:SetJustifyH("left") line.ActionText:SetHook("OnEscapePressed", keyBindFrame.set_action_on_espace_press) line.ActionText:SetHook("OnEditFocusGained", function() @@ -525,88 +730,178 @@ detailsFramework.KeybindMixin = { local tab, tabTex, offset, numSpells = GetSpellTabInfo(2) for i = 1, numSpells do local index = offset + i - local spellType, spellId = GetSpellBookItemInfo(index, "player") + local spellType, actionId = GetSpellBookItemInfo(index, "player") if (spellType == "SPELL") then - local spellName = GetSpellInfo(spellId) + local spellName = GetSpellInfo(actionId) tinsert(playerSpells, spellName) end end line.ActionText.WordList = playerSpells end) - + line.ActionText:SetAsAutoComplete("WordList") + --]=] + line:AddFrameToHeaderAlignment(line.spellIconTexture) + line:AddFrameToHeaderAlignment(line.spellNameFontString) + line:AddFrameToHeaderAlignment(line.setKeybindButton) + --line:AddFrameToHeaderAlignment(line.ActionDrop) + --line:AddFrameToHeaderAlignment(line.ActionText) + line:AddFrameToHeaderAlignment(line.clearKeybindButton) - line:AddFrameToHeaderAlignment(line.Index) - line:AddFrameToHeaderAlignment(line.KeyBind) - line:AddFrameToHeaderAlignment(line.ActionDrop) - line:AddFrameToHeaderAlignment(line.ActionText) - line:AddFrameToHeaderAlignment(line.Delete) - line:AlignWithHeader(keyBindFrame.Header, "left") + + return line end, ---comment ---@param self df_keybindframe - CreateKeybindScroll = function(self) - local scroll_width = self.options.width - 10 - local scroll_height = self.options.height - 40 + CreateKeybindScroll = function(self) --~scroll + local scroll_width = self.options.scroll_width + local scroll_height = self.options.scroll_height local scroll_lines = self.options.amount_lines local scroll_line_height = self.options.line_height - --header - local headerTable = { - {text = "", width = 20}, --index - {text = "", width = 20}, --spell icon - {text = "Ability Name", width = 120}, - {text = "Keybind", width = 60}, - {text = "Action Type", width = 60}, - {text = "Action Text", width = 45}, - {text = "Clear Keybind", width = 80}, - } - local headerOptions = { - padding = 2, - } - + --~header ---@type df_headerframe self.Header = DetailsFramework:CreateHeader(self, headerTable, headerOptions) - self.Header:SetPoint("topleft", self, "topleft", 5, -25) + self.Header:SetPoint("topleft", self, "topleft", 0, 0) local keybindScroll = detailsFramework:CreateScrollBox(self, "$parentScrollBox", detailsFramework.KeybindMixin.RefreshKeybindScroll, {}, scroll_width, scroll_height, scroll_lines, scroll_line_height) + ---@cast keybindScroll df_keybindscroll + detailsFramework:ReskinSlider(keybindScroll) - keybindScroll:SetPoint("topleft", self.Header, "bottomleft", 0, -2) + keybindScroll:SetPoint("topleft", self.Header, "bottomleft", 0, -5) self.keybindScroll = keybindScroll + keybindScroll:SetBackdropColor(0, 0, 0, 0) + keybindScroll:SetBackdropBorderColor(0, 0, 0, 0) + keybindScroll.__background:SetAlpha(0) + for i = 1, scroll_lines do keybindScroll:CreateLine(self.CreateKeybindScrollLine) end + + function keybindScroll.UpdateScroll() --~update + --keybind data from saved variables + local data = self:GetKeybindData() + + ---@type keybind_scroll_data[] + local scrollData = {} + + if (self.options.show_spells) then + --the a list of all spells + local allPlayerSpells = detailsFramework:GetAvailableSpells() + --bIsAvailable is a boolean that tells if the spell is from the spec the player is currently using (spells grayed out on the spellbook would be false here) + for spellId, bIsAvailable in pairs(allPlayerSpells) do + local spellName, _, spellIcon = GetSpellInfo(spellId) + if (spellName) then + local keybind = data[spellId] or "" + local sortScore = (bIsAvailable and 0 or 200) + string.byte(spellName) -- + (keybind ~= "" and 100 or 0) + local actionId = spellId + scrollData[#scrollData+1] = {spellName, spellIcon, actionId, keybind, bIsAvailable, sortScore} + end + end + + table.sort(scrollData, function(a, b) return a[6] < b[6] end) + end + + if (self.options.show_unitcontrols) then + for i, actionKeyInfo in ipairs(unitControlKeybinds) do + local actionName = actionKeyInfo.localizedName + local defaultKeybind = actionKeyInfo.keybind + local keybind = data[actionName] or defaultKeybind + local icon = actionKeyInfo.icon + local actionId = actionKeyInfo.name + table.insert(scrollData, 1, {actionName, icon, actionId, keybind, defaultKeybind, 0}) + end + end + + keybindScroll:SetData(scrollData) + keybindScroll:Refresh() + end end, -} + ---return the keybind data + ---@param self df_keybindframe + ---@return df_keybinddata + GetKeybindData = function(self) + return self.data + end, + ---set the keybind data from a profile + ---data consists in a table where the actionId (any) is the key and the value is the keybind (string) + ---@param self df_keybindframe + ---@param newData df_keybinddata + SetKeybindData = function(self, newData) + self.data = newData + local keybindScroll = self:GetKeybindScroll() + keybindScroll:UpdateScroll() + end, + + ---set the callback function to be called when the player set or clear a keybind + ---@param self df_keybindframe + ---@param callback function + SetKeybindCallback = function(self, callback) + self.callback = callback + local keybindScroll = self:GetKeybindScroll() + keybindScroll:UpdateScroll() + end, + + ---@param self df_keybindframe + ---@return function + GetKeybindCallback = function(self) + return self.callback + end, + + OnKeybindChanged = function(self, actionId, keybind) + local callbackFunc = self:GetKeybindCallback() + if (callbackFunc) then + detailsFramework:Dispatch(callbackFunc, actionId, keybind) + end + end, +} ---@param parent frame ---@param name string? ---@param options table? -function detailsFramework:CreateKeybindFrame(parent, name, options) +---@param setKeybindCallback function? +---@param keybindData table? +function detailsFramework:CreateKeybindFrame(parent, name, options, setKeybindCallback, keybindData) ---@type df_keybindframe local keyBindFrame = CreateFrame("frame", name, parent, "BackdropTemplate") keyBindFrame.bIsKeybindFrame = true detailsFramework:Mixin(keyBindFrame, detailsFramework.OptionsFunctions) + detailsFramework:Mixin(keyBindFrame, detailsFramework.KeybindMixin) options = options or {} keyBindFrame:BuildOptionsTable(default_options, options) - keyBindFrame:SetSize(keyBindFrame.options.width, keyBindFrame.options.height) + if (keyBindFrame.options.width ~= default_options.width or keyBindFrame.options.height ~= default_options.height) then + local lineHeight = keyBindFrame.options.line_height + keyBindFrame.options.amount_lines = math.floor((keyBindFrame.options.height - 20) / lineHeight) + keyBindFrame.options.scroll_height = keyBindFrame.options.height - 20 + keyBindFrame.options.scroll_width = keyBindFrame.options.width - 10 + end - keyBindFrame:CreateSpecButtons() + keyBindFrame:SetSize(keyBindFrame.options.width, keyBindFrame.options.height) keyBindFrame:SetScript("OnHide", function() - if (keyBindFrame.IsListening) then - keyBindFrame.IsListening = false - keyBindFrame:SetScript("OnKeyDown", nil) + if (keyBindFrame:IsListening()) then + keyBindFrame:SetListeningState(false) + local keybindListener = keyBindFrame:GetKeybindListener() + keybindListener:SetScript("OnKeyDown", nil) end end) + keyBindFrame:CreateKeybindScroll() + keyBindFrame:CreateKeybindListener() + + keyBindFrame:SetKeybindData(keybindData or {}) + + if (setKeybindCallback) then + keyBindFrame:SetKeybindCallback(setKeybindCallback) + end + return keyBindFrame end diff --git a/Libs/DF/mixins.lua b/Libs/DF/mixins.lua index 9a949eb48..d7b710e43 100644 --- a/Libs/DF/mixins.lua +++ b/Libs/DF/mixins.lua @@ -711,7 +711,8 @@ end ---mixin to use with DetailsFramework:Mixin(table, detailsFramework.SortFunctions) ---adds the method Sort() to a table, this method can be used to sort another table by a member, can't sort itself ----@class DetailsFramework.SortFunctions + +---@class df_sortmixin detailsFramework.SortFunctions = { ---sort a table by a member ---@param self table diff --git a/Libs/DF/panel.lua b/Libs/DF/panel.lua index e377a5ab9..5864bab98 100644 --- a/Libs/DF/panel.lua +++ b/Libs/DF/panel.lua @@ -3687,6 +3687,22 @@ end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ -- ~scrollbox +---@class df_scrollbox : scrollframe, df_sortmixin, df_scrollboxmixin +---@field data table +---@field Header df_headerframe? +---@field LineAmount number +---@field LineHeight number +---@field IsFauxScroll boolean +---@field HideScrollBar boolean +---@field Frames frame[] +---@field ReajustNumFrames number +---@field DontHideChildrenOnPreRefresh boolean +---@field refresh_func fun(self:df_scrollbox, data:table, offset:number, numlines:number) +---@field CreateLineFunc fun(self:df_scrollbox, index:number) : frame +---@field CreateLine fun(self:df_scrollbox, func:function) +---@field +---@field + ---create a scrollbox with the methods :Refresh() :SetData() :CreateLine() ---@param parent table ---@param name string @@ -3699,9 +3715,10 @@ end ---@param createLineFunc function|nil ---@param autoAmount boolean|nil ---@param noScroll boolean|nil ----@return table +---@return df_scrollbox function detailsFramework:CreateScrollBox(parent, name, refreshFunc, data, width, height, lineAmount, lineHeight, createLineFunc, autoAmount, noScroll) --create the scrollframe, it is the base of the scrollbox + ---@type df_scrollbox local scroll = CreateFrame("scrollframe", name, parent, "FauxScrollFrameTemplate, BackdropTemplate") --apply the standard background color @@ -4355,9 +4372,10 @@ end ---for the background it uses UI-Tooltip-Background with detailsFramework:GetDefaultBackdropColor() color ---for the border it uses Interface\Buttons\WHITE8X8 ---also creates an additional texture frame.__background = texture with the same setting of the backdrop background ----@param frame table ----@param bUseSolidColor any ----@param alphaScale number +---@param self table +---@param frame frame +---@param bUseSolidColor boolean? +---@param alphaScale number? function detailsFramework:ApplyStandardBackdrop(frame, bUseSolidColor, alphaScale) alphaScale = alphaScale or 0.95 diff --git a/Libs/DF/tabcontainer.lua b/Libs/DF/tabcontainer.lua index 830d8c2fd..e058f2410 100644 --- a/Libs/DF/tabcontainer.lua +++ b/Libs/DF/tabcontainer.lua @@ -9,7 +9,7 @@ local unpack = unpack local CreateFrame = CreateFrame local PixelUtil = PixelUtil ----@class df_tabinfotable : {name: string, text: string} +---@class df_tabinfotable : {name: string, text: string, createOnDemandFunc:function?} ---@class df_tabcontainer : frame ---@field AllFrames df_tabcontainerframe[] @@ -229,6 +229,24 @@ detailsFramework.TabContainerFrameMixin = { end, } +---@class df_tabcontaineroptions : table +---@field width number? +---@field height number? +---@field button_border_color table? +---@field button_selected_border_color table? +---@field right_click_y number? +---@field hide_click_label boolean? +---@field close_text_alpha number? +---@field rightbutton_always_close boolean? +---@field right_click_interact boolean? +---@field y_offset number? +---@field button_width number? +---@field button_height number? +---@field button_x number? +---@field button_y number? +---@field button_text_size number? +---@field container_width_offset number? + ---creates a frame called tabContainer which is used as base for the tab container object ---the function receives a table called tabList which contains sub tables with two keys 'name' and 'text', name is the frame name and text is the text displayed on the button ---then the function iterate amongst the tabList and create a frame and a button for each entry using the value of the 'text' key as the text for the button and 'name' for the name of the frame @@ -237,8 +255,8 @@ detailsFramework.TabContainerFrameMixin = { ---@param title string a string to use as the title of the tab container, the title is always shown ---@param frameName string the frame name to pass into the CreateFrame function ---@param tabList df_tabinfotable[] the list of tabs to create, each entry has a 'name' and 'text' keys ----@param optionsTable {button_border_color: table, button_selected_border_color: table, right_click_y: number, hide_click_label: boolean, close_text_alpha: number, rightbutton_always_close: boolean, right_click_interact: boolean, y_offset: number, button_width: number, button_height: number, button_x: number, button_y: number, button_text_size: number, container_width_offset: number}|nil ----@param hookList table|nil +---@param optionsTable df_tabcontaineroptions? +---@param hookList table? ---@param languageInfo any ---@return df_tabcontainer function detailsFramework:CreateTabContainer(parent, title, frameName, tabList, optionsTable, hookList, languageInfo) @@ -257,6 +275,7 @@ function detailsFramework:CreateTabContainer(parent, title, frameName, tabList, ---@type df_tabcontainer local tabContainer = CreateFrame("frame", frameName, parent["widget"] or parent, "BackdropTemplate") tabContainer.hookList = hookList or {} + tabContainer:SetSize(optionsTable.width or 750, optionsTable.height or 450) detailsFramework:Mixin(tabContainer, detailsFramework.TabContainerMixin) @@ -296,6 +315,15 @@ function detailsFramework:CreateTabContainer(parent, title, frameName, tabList, tabFrame.tabIndex = tabIndex tabFrame:Hide() + if (tabInfo.createOnDemandFunc) then + tabFrame:SetScript("OnShow", function() + if (tabInfo.createOnDemandFunc) then + detailsFramework:Dispatch(tabInfo.createOnDemandFunc, tabFrame, parent) + tabInfo.createOnDemandFunc = nil + end + end) + end + --attempt to get the localized text from the language system using the addonId and the frameInfo.text local phraseId = tabInfo.text local bIsLanguagePrahseID = detailsFramework.Language.DoesPhraseIDExistsInDefaultLanguage(addonId, phraseId) diff --git a/boot.lua b/boot.lua index 40a0df406..4c00f45d2 100644 --- a/boot.lua +++ b/boot.lua @@ -410,29 +410,6 @@ do "/details auras: show a panel with your current auras, spell ids and spell payload.", "/details perf: show performance issues when you get a warning about freezes due to UpdateAddOnMemoryUsage().", "/details npcid: get the npc id of your target (a box is shown with the number ready to be copied).", - - {"v9.2.0.10001.146", "Aug 10th, 2022"}, - "New feature: Arena DPS Bar, can be enabled at the Broadcaster Tools section, shows a bar in 'kamehameha' style showing which team is doing more damage in the latest 3 seconds.", - "/keystone now has more space for the dungeon name.", - "Revamp on the options section for Broadcaster tools.", - "Added 'Icon Size Offset' under Options > Bars: General, this new option allow to adjust the size of the class/spec icon shown on each bar.", - "Added 'Show Faction Icon' under Options > Bars: General, with this new option, you can choose to not show the faction icon, this icon is usually shown during battlegrounds.", - "Added 'Faction Icon Size Offset' under Options > Bars: General, new option to adjust the size of the faction icon.", - "Added 'Show Arena Role Icon' under Options > Bars: General, new option to hide or show the role icon of players during an arena match.", - "Added 'Clear On Start PVP' overall data option (Flamanis).", - "Added 'Arena Role Icon Size Offset' under Options > Bars: General, new option which allow to control the size of the arena role icon.", - "Added 'Level' option to Wallpapers, the wallpaper can now be placed on different levels which solves issues where the wallpaper is too low of certain configuration.", - "Streamer! plugin got updates, now it is more clear to pick which mode to use.", - "WotLK classic compatibility (Flamanis, Daniel Henry).", - "Fixed Grimrail Depot cannon and granades damage be added to players (dios-david).", - "Fixed the title bar text not showing when using the Custom Title Bar feature.", - "Fixed an issue with Dynamic Overall Damage printing errors into the chat window (Flamanis).", - "Role detection in classic versions got improvements.", - "New API: Details:GetTop5Actors(attributeId), return the top 5 actors from the selected attribute.", - "New API: Details:GetActorByRank(attributeId, rankIndex), return an actor from the selected attribute and rankIndex.", - "Major cleanup and code improvements on dropdowns for library Details! Framework.", - "Cleanup on NickTag library.", - "Removed LibGroupInSpecT, LibItemUpgradeInfo and LibCompress. These libraries got replaced by OpenRaidLib and LibDeflate.", } local newsString = "|cFFF1F1F1" @@ -491,7 +468,7 @@ do --current instances of the exp (need to maintain) _detalhes.InstancesToStoreData = { --mapId - [2522] = true, --sepulcher of the first ones + [2549] = true, --amirdrassil } --store shield information for absorbs diff --git a/classes/class_utility.lua b/classes/class_utility.lua index b159618a9..55092ca9a 100644 --- a/classes/class_utility.lua +++ b/classes/class_utility.lua @@ -262,7 +262,7 @@ function Details.ShowDeathTooltip(instance, lineFrame, combatObject, deathTable) gameCooltip:AddStatusBar(healthPercent, 1, barTypeColors.heal, showSpark, statusBarBackgroundTable_ForDeathTooltip) end else - gameCooltip:AddLine("" .. format("%.1f", eventTime - timeOfDeath) .. "s " .. spellName .. " (|c" .. healingSourceColor .. source .. "|r)", (event[11] and ("x" .. amount .. " ") or ("")) .. "|c" .. healingAmountColor .. "+" .. Details:ToK(amount) .. " (" .. healthPercent .. "%)", 1, "white", "white") + gameCooltip:AddLine("" .. format("%.1f", eventTime - timeOfDeath) .. "s " .. spellName .. " (|c" .. healingSourceColor .. source .. "|r)", (event[11] and ("x" .. event[11] .. " ") or "") .. "|c" .. healingAmountColor .. "+" .. Details:ToK(amount) .. " (" .. healthPercent .. "%)", 1, "white", "white") gameCooltip:AddIcon(spellIcon, nil, nil, lineHeight, lineHeight, .1, .9, .1, .9) gameCooltip:AddStatusBar(healthPercent, 1, barTypeColors.heal, showSpark, statusBarBackgroundTable_ForDeathTooltip) end diff --git a/functions/spellcache.lua b/functions/spellcache.lua index 7707daeaa..53b030735 100644 --- a/functions/spellcache.lua +++ b/functions/spellcache.lua @@ -222,7 +222,9 @@ do [196917] = {name = lightOfTheMartyr_Name .. " (" .. Loc ["STRING_DAMAGE"] .. ")", icon = lightOfTheMartyr_Icon}, [77535] = {name = GetSpellInfo(77535), icon = "Interface\\Addons\\Details\\images\\icon_blood_shield"}, [395296] = {name = GetSpellInfo(395296) .. " (on your self)", icon = "Interface\\Addons\\Details\\images\\ebon_might"}, - --[424428] = {name = GetSpellInfo(424428) .. " (4P)", icon = "Interface\\Addons\\Details\\images\\spells\\eruption_tier4.jpg", defaultName = GetSpellInfo(424428), breakdownCanStack = true}, --evoker 4pc tier 10.2 + + [424428] = {name = (GetSpellInfo(424428) or "none") .. " (4P)", icon = "Interface\\Addons\\Details\\images\\spells\\eruption_tier4.jpg", defaultName = GetSpellInfo(424428), breakdownCanStack = true}, --augmentation 4pc tier 10.2 + [422779] = {name = (GetSpellInfo(422779) or "none") .. " (4P)", icon = "Interface\\Addons\\Details\\images\\spells\\burning_frenzy_tier4.jpg", defaultName = GetSpellInfo(422779)}, --feral 4pc tier 10.2 } customItemList[394453] = {itemId = 195480, isPassive = true} --ring: Seal of Diurna's Chosen diff --git a/images/spells/burning_frenzy_tier4.jpg b/images/spells/burning_frenzy_tier4.jpg new file mode 100644 index 000000000..bfafdbe0c Binary files /dev/null and b/images/spells/burning_frenzy_tier4.jpg differ