diff --git a/.gitignore b/.gitignore index 7348b6fa..2c40f28e 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ locales/zhTW.lua api.lua *.png media/options_visibility_context.afphoto~lock~ +luac.out diff --git a/Vignette Extra Icons.txt b/Vignette Extra Icons.txt new file mode 100644 index 00000000..4b5a8877 --- /dev/null +++ b/Vignette Extra Icons.txt @@ -0,0 +1,41 @@ + [zoneIDs.EMERALDDREAM] = { + { + dataType = "vignette", + id = 5971, + texture = "SeedPlanting-Full", + filterFunc = function() return true end, --this function is called before the icon is added to the map + tooltipFunc = function()end, --called on OnEnter + amountFunc = function()end, --called to se the number which goes bellow the icon + onAddFunc = function()end, --called when the icon is added to the map + onRemoveFunc = function()end, --called when the icon is removed from the map + } + }, + + +--[=[ +[1] = { + ["widgetSetID"] = 1005, + ["atlasName"] = "SeedPlanting-Full", + ["hasTooltip"] = true, + ["onMinimap"] = false, + ["rewardQuestID"] = 0, + ["type"] = 0, + ["isDead"] = false, + ["objectGUID"] = "Creature-0-3020-2548-66-209880-00005006E7", + ["addPaddingAboveWidgets"] = true, + ["onWorldMap"] = true, + ["name"] = "Emerald Bounty", + ["vignetteGUID"] = "Vignette-0-3020-2548-66-5971-00005006E7", + ["vignetteID"] = 5971, + ["inFogOfWar"] = false, + ["isUnique"] = true, + ["zoneInfiniteAOI"] = true, +}, +--]=] + + + + +/run LFGListFrame.ApplicationViewer.InfoBackground +/run LFGListFrame.SearchPanel:Show() +/run LFGListFrame.ApplicationViewer:Hide() diff --git a/WorldQuestTracker_IDs.lua b/WorldQuestTracker_IDs.lua index 72d21483..80c6a55c 100644 --- a/WorldQuestTracker_IDs.lua +++ b/WorldQuestTracker_IDs.lua @@ -584,6 +584,10 @@ WorldQuestTracker.mapTables = { }, } +WorldQuestTracker.extraIcons = { + +} + WorldQuestTracker.MapData.EquipmentIcons = { ["INVTYPE_HEAD"] = "Interface\\ICONS\\" .. "INV_Helmet_29", ["INVTYPE_NECK" ] = "Interface\\ICONS\\" .. "INV_Jewelry_Necklace_07", diff --git a/WorldQuestTracker_OptionsPanel.lua b/WorldQuestTracker_OptionsPanel.lua index 01f43e5c..b51c9705 100644 --- a/WorldQuestTracker_OptionsPanel.lua +++ b/WorldQuestTracker_OptionsPanel.lua @@ -505,18 +505,6 @@ function WorldQuestTrackerAddon.OpenOptionsPanel() name = "S_OPTIONS_MAPFRAME_ALIGN", desc = "S_OPTIONS_MAPFRAME_ALIGN", }, - { - type = "toggle", - get = function() - return DB.profile.show_faction_frame - end, - set = function(self, fixedparam, value) - WorldQuestTracker.SetSetting("show_faction_frame", not WorldQuestTracker.db.profile.show_faction_frame) - - end, - name = "S_OPTIONS_SHOWFACTIONS", - desc = "S_OPTIONS_SHOWFACTIONS", - }, { type = "toggle", get = function() @@ -707,6 +695,19 @@ function WorldQuestTrackerAddon.OpenOptionsPanel() get = function() return "S_VISIBILITY" end, text_template = DF:GetTemplate("font", "ORANGE_FONT_TEMPLATE") }, + + { + type = "toggle", + get = function() + return DB.profile.show_faction_frame + end, + set = function(self, fixedparam, value) + WorldQuestTracker.SetSetting("show_faction_frame", not WorldQuestTracker.db.profile.show_faction_frame) + + end, + name = "S_OPTIONS_SHOWFACTIONS", + desc = "|TInterface\\AddOns\\WorldQuestTracker\\media\\options_visibility_context:" .. 33 .. ":" .. 208 .. ":0:0:256:256:" .. (0) .. ":" .. (208) .. ":" .. (36+30) .. ":" .. (36+30+33) .. "|t\n\n" .. "S_OPTIONS_SHOWFACTIONS", + }, { type = "toggle", get = function() diff --git a/WorldQuestTracker_WorldMap.lua b/WorldQuestTracker_WorldMap.lua index 7ced0ca8..646e83df 100644 --- a/WorldQuestTracker_WorldMap.lua +++ b/WorldQuestTracker_WorldMap.lua @@ -1574,6 +1574,19 @@ local scheduledIconUpdate = function(questTable) WorldQuestTracker.SetupWorldQuestButton(button, worldQuestType, rarity, isElite, tradeskillLineIndex, nil, nil, isCriteria, nil, mapID) local newX, newY = HereBeDragons:TranslateZoneCoordinates(x, y, mapID, WorldMapFrame.mapID, false) + + if (mapID == WorldQuestTracker.MapData.ZoneIDs.ZARALEK) then + if (x and y) then --no zaralek mapID, but zaralek quests shown on worldmap + newX = 0.75 + x * 0.25 + newY = 0.75 + y * 0.25 + --button.blackGradient:Hide() + --button.flagText:Hide() + --self.bgFlag:Hide() + WorldQuestTracker.ClearZoneWidget(button) + button.circleBorder:Show() + end + end + pin:SetPosition(newX, newY) pin:SetSize(22, 22) pin.IsInUse = true diff --git a/WorldQuestTracker_ZoneMap.lua b/WorldQuestTracker_ZoneMap.lua index d694a06a..5327b7dc 100644 --- a/WorldQuestTracker_ZoneMap.lua +++ b/WorldQuestTracker_ZoneMap.lua @@ -30,6 +30,7 @@ local worldFramePOIs = WorldMapFrame.BorderFrame local UpdateDebug = false local ZoneWidgetPool = WorldQuestTracker.ZoneWidgetPool +local VignettePool = WorldQuestTracker.VignettePool local clear_widget = function(self) self.highlight:Hide() @@ -56,6 +57,12 @@ local clear_widget = function(self) self.flagCriteriaMatchGlow:Hide() self.TextureCustom:Hide() self.RareOverlay:Hide() + self.Shadow:Hide() + self.flagTextShadow:SetText("") +end + +WorldQuestTracker.ClearZoneWidget = function(widget) + clear_widget(widget) end local on_show_alpha_animation = function(self) @@ -503,17 +510,29 @@ function WorldQuestTracker.CreateZoneWidget(index, name, parent, pinTemplate) -- end --cria os widgets no mapa da zona -function WorldQuestTracker.GetOrCreateZoneWidget(index) - local taskPOI = ZoneWidgetPool [index] +function WorldQuestTracker.GetOrCreateZoneWidget(index, widgetType) + if (widgetType == "vignette") then + local icon = VignettePool[index] - if (not taskPOI) then - taskPOI = WorldQuestTracker.CreateZoneWidget(index, "WorldQuestTrackerZonePOIWidget", WorldQuestTracker.AnchoringFrame) - taskPOI.IsZoneQuestButton = true - ZoneWidgetPool [index] = taskPOI - end + if (not icon) then + icon = WorldQuestTracker.CreateZoneWidget(index, "WorldQuestTrackerZoneVignetteWidget", WorldQuestTracker.AnchoringFrame) + VignettePool[index] = icon + end + + icon.Texture:Show() + return icon + else + local taskPOI = ZoneWidgetPool[index] + + if (not taskPOI) then + taskPOI = WorldQuestTracker.CreateZoneWidget(index, "WorldQuestTrackerZonePOIWidget", WorldQuestTracker.AnchoringFrame) + taskPOI.IsZoneQuestButton = true + ZoneWidgetPool[index] = taskPOI + end - taskPOI.Texture:Show() - return taskPOI + taskPOI.Texture:Show() + return taskPOI + end end --esconde todos os widgets de zona @@ -524,14 +543,6 @@ function WorldQuestTracker.HideZoneWidgets() end end ---update anchors when zoomed -function WorldQuestTracker.UpdateZoneWidgetAnchors() - for i = 1, #WorldQuestTracker.Cache_ShownWidgetsOnZoneMap do - local widget = WorldQuestTracker.Cache_ShownWidgetsOnZoneMap [i] - WorldMapPOIFrame_AnchorPOI(widget, widget.PosX, widget.PosY, WORLD_MAP_POI_FRAME_LEVEL_OFFSETS.WORLD_QUEST) - end -end - local quest_bugged = {} local dazaralor_quests = { {0.441, 0.322}, @@ -545,7 +556,7 @@ local dazaralor_quests = { function WorldQuestTracker.AdjustThatThingInTheBottomLeftCorner() --looks like this dropdown is opened by default if (_G["DropDownList1MenuBackdrop"] and _G["DropDownList1MenuBackdrop"]:IsShown()) then - _G["DropDownList1MenuBackdrop"]:Hide() + --_G["DropDownList1MenuBackdrop"]:Hide() end local children = {WorldMapFrame:GetChildren()} @@ -594,6 +605,8 @@ function WorldQuestTracker.UpdateZoneWidgets(forceUpdate) --get the map shown in the map frame local mapID = WorldQuestTracker.GetCurrentMapAreaID() + WorldQuestTracker.UpdateZonePOIs(forceUpdate) + if (WorldQuestTracker.IsWorldQuestHub(mapID)) then return WorldQuestTracker.HideZoneWidgets() @@ -916,7 +929,8 @@ function WorldQuestTracker.UpdateZoneWidgets(forceUpdate) widget.AnchorFrame.questID = questID widget.AnchorFrame.numObjectives = widget.numObjectives - WorldQuestTrackerAddon.DataProvider:GetMap():SetPinPosition(widget.AnchorFrame, widget.PosX, widget.PosY) + local posX, posY = widget.PosX, widget.PosY + WorldQuestTrackerAddon.DataProvider:GetMap():SetPinPosition(widget.AnchorFrame, posX, posY) widget.AnchorFrame:Show() widget:SetFrameLevel(WorldQuestTracker.DefaultFrameLevel + floor(random(1, 30))) @@ -1097,6 +1111,56 @@ function WorldQuestTracker.UpdateZoneWidgets(forceUpdate) end +--check if the zone has extra data to show like quests, pois, etc +function WorldQuestTracker.UpdateZonePOIs(forceUpdate) + local mapID = WorldQuestTracker.GetCurrentMapAreaID() + local extraIcons = WorldQuestTracker.extraIcons[mapID] + + local index = 1 + + if (extraIcons) then + --extraIcons is an array with iconData + for i = 1, #extraIcons do + local iconData = extraIcons[i] + if (iconData.dataType == "vignette") then + local id = iconData.id + local allVignetteSerials = C_VignetteInfo.GetVignettes() + + for o = 1, #allVignetteSerials do + local vignetteSerial = allVignetteSerials[o] + local vignetteInfo = C_VignetteInfo.GetVignetteInfo(vignetteSerial) + + if (vignetteInfo) then + if (vignetteInfo.vignetteID == id) then + local vec2Pos = C_VignetteInfo.GetVignettePosition(vignetteSerial, mapID) + if (vec2Pos) then + local widget = WorldQuestTracker.GetOrCreateZoneWidget(index, "vignette") + index = index + 1 + + widget.questID = 0 + widget.PosX = vec2Pos.x + widget.PosY = vec2Pos.y + + --the zone widget need to be updated here + WorldQuestTracker.ResetWorldQuestZoneButton(widget) + widget.Texture:SetAtlas(vignetteInfo.atlasName) + + widget.Texture:SetSize(16, 16) + widget:SetSize(16, 16) + widget:SetAlpha(0.8) + WorldQuestTrackerAddon.DataProvider:GetMap():SetPinPosition(widget.AnchorFrame, widget.PosX, widget.PosY) + widget:Show() + end + end + end + end + + --elseif (iconData.dataType == "icon") then + end + end + end +end + --reset the button function WorldQuestTracker.ResetWorldQuestZoneButton(self) self.isArtifact = nil @@ -1194,8 +1258,7 @@ function WorldQuestTracker.SetupWorldQuestButton(self, worldQuestType, rarity, i end --default alpha - --self:SetAlpha(WQT_ZONEWIDGET_ALPHA - 0.05) - self:SetAlpha(ALPHA_BLEND_AMOUNT) + self:SetAlpha(WorldQuestTracker.db.profile.worldmap_widget_alpha) self.FactionID = factionID if (self.isCriteria) then @@ -1459,6 +1522,11 @@ end --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --> zone summary ~summaryframe +function WorldQuestTracker.RefreshZoneSummaryAlpha() + local alpha = WorldQuestTracker.db.profile.world_summary_alpha + WorldQuestTrackerZoneSummaryFrame:SetAlpha(alpha) +end + local ZoneSumaryFrame = CreateFrame("frame", "WorldQuestTrackerZoneSummaryFrame", worldFramePOIs, "BackdropTemplate") ZoneSumaryFrame:SetPoint("topleft", worldFramePOIs, "topleft", 2, -380) ZoneSumaryFrame:SetSize(200, 400) @@ -1506,7 +1574,7 @@ local GetOrCreateZoneSummaryWidget = function(index) end local button = CreateFrame("button", "WorldQuestTrackerZoneSummaryFrame_Widget" .. index, ZoneSumaryFrame, "BackdropTemplate") - button:SetAlpha(WQT_ZONEWIDGET_ALPHA) + button:SetAlpha(WorldQuestTracker.db.profile.world_summary_alpha) --button:SetPoint("bottomleft", ZoneSumaryFrame, "bottomleft", 0,((index-1)*(ZoneSumaryFrame.WidgetHeight + 1)) -2) --grow bottom to top button:SetPoint("topleft", ZoneSumaryFrame, "topleft", 0,(((index-1) *(ZoneSumaryFrame.WidgetHeight + 1)) -2) * -1) --grow top to bottom @@ -1663,7 +1731,7 @@ function WorldQuestTracker.SetupZoneSummaryButton(summaryWidget, zoneWidget) --update the quest icon local okay, gold, resource, apower = WorldQuestTracker.UpdateWorldWidget(widget, questID, numObjectives, mapID, isCriteria, isNew, isUsingTracker, timeLeft, artifactPowerIcon) widget.texture:SetTexCoord(.1, .9, .1, .9) - widget:SetAlpha(WQT_ZONEWIDGET_ALPHA) + widget:SetAlpha(WorldQuestTracker.db.profile.world_summary_alpha) widget.background:Hide() widget.factionBorder:Hide() @@ -1689,7 +1757,7 @@ function WorldQuestTracker.SetupZoneSummaryButton(summaryWidget, zoneWidget) --set the time left local timePriority = WorldQuestTracker.db.profile.sort_time_priority - local alphaAmount = WQT_WORLDWIDGET_BLENDED + 0.06 + local alphaAmount = 0.923 if (timePriority and timePriority > 0) then if (timePriority < 4) then @@ -1726,7 +1794,7 @@ function WorldQuestTracker.SetupZoneSummaryButton(summaryWidget, zoneWidget) summaryWidget:SetAlpha(1) end - summaryWidget.timeLeftText:SetText(timeLeft > 1440 and floor(timeLeft/1440) .. "d" or timeLeft > 60 and floor(timeLeft/60) .. "h" or timeLeft .. "m") + summaryWidget.timeLeftText:SetText((timeLeft > 1440 and floor(timeLeft/1440) .. "d") or (timeLeft > 60 and floor(timeLeft/60) .. "h") or (timeLeft .. "m")) summaryWidget.timeLeftText:SetJustifyH("center") summaryWidget.timeLeftText:Show() @@ -1848,6 +1916,7 @@ function WorldQuestTracker.UpdateZoneSummaryFrame() end WorldQuestTracker.QuestSummaryShown = true + WorldQuestTracker.RefreshZoneSummaryAlpha() end diff --git a/libs/DF/auras.lua b/libs/DF/auras.lua index 9a694489..494a281a 100644 --- a/libs/DF/auras.lua +++ b/libs/DF/auras.lua @@ -205,11 +205,7 @@ local aura_panel_defaultoptions = { } function DF:CreateAuraConfigPanel(parent, name, db, changeCallback, options, texts) - local options_text_template = DF:GetTemplate("font", "OPTIONS_FONT_TEMPLATE") local options_dropdown_template = DF:GetTemplate("dropdown", "OPTIONS_DROPDOWN_TEMPLATE") - local options_switch_template = DF:GetTemplate("switch", "OPTIONS_CHECKBOX_TEMPLATE") - local options_slider_template = DF:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE") - local options_button_template = DF:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE") local newAuraPanel = CreateFrame("frame", name, parent, "BackdropTemplate") newAuraPanel.db = db @@ -629,202 +625,6 @@ function DF:CreateAuraConfigPanel(parent, name, db, changeCallback, options, tex local scrollWidth = 208 -do --deprecated, using a scrollbox tempate from scrollbox.lua - local scrollHeight = 343 - local lineAmount = 18 - local lineHeight = 18 - local backdropColor = {.8, .8, .8, 0.2} - local backdropColor_OnEnter = {.8, .8, .8, 0.4} - - --aura scroll box default settings - local auraScrollDefaultSettings = { - show_spell_tooltip = false, - line_height = 18, - line_amount = 18, - } - - local autoTrackList_LineOnEnter = function(self, capsule, value) - local flag = self.Flag - value = value or self.SpellID - - if not flag then - GameCooltip2:Preset(2) - GameCooltip2:SetOwner(self, "left", "right", 2, 0) - GameCooltip2:SetOption("TextSize", 10) - - local spellName, _, spellIcon = GetSpellInfo(value) - if (spellName) then - GameCooltip2:AddLine(spellName .. "(" .. value .. ")") - GameCooltip2:AddIcon(spellIcon, 1, 1, 14, 14, .1, .9, .1, .9) - end - GameCooltip2:Show() - - else - local spellName, _, spellIcon = GetSpellInfo(value) - if (spellName and spellsWithSameName) then - local spellNameLower = spellName:lower() - local sameNameSpells = spellsWithSameName[spellNameLower] - - if (sameNameSpells) then - GameCooltip2:Preset(2) - GameCooltip2:SetOwner(self, "left", "right", 2, 0) - GameCooltip2:SetOption("TextSize", 10) - - for i, spellId in ipairs(sameNameSpells) do - GameCooltip2:AddLine(spellName .. " (" .. spellId .. ")") - GameCooltip2:AddIcon(spellIcon, 1, 1, 14, 14, .1, .9, .1, .9) - end - - GameCooltip2:Show() - end - end - end - end - - local autoTrackList_LineOnLeave = function() - GameCooltip2:Hide() - end - - - local createAuraScrollBox = function(scrollBoxParent, scrollBoxName, scrollBoxParentKey, scrollBoxTitle, databaseTable, removeAuraFunc, options) - local scrollOptions = {} - detailsFramework.OptionsFunctions.BuildOptionsTable(scrollOptions, auraScrollDefaultSettings, options) - - local updateFunc = 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) - line.icon:SetTexCoord(.1, .9, .1, .9) - end - end - end - - local auraLineOnEnter = function(line) - if (scrollOptions.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(backdropColor_OnEnter)) - end - - local auraLineOnLeave = function(self) - self:SetBackdropColor(unpack(backdropColor)) - GameTooltip:Hide() - end - - local onAuraRemoveButtonClick = function(self) - local spellId = self:GetParent().SpellID - databaseTable[spellId] = nil - databaseTable["" .. (spellId or "")] = nil -- cleanup... - scrollBoxParent[scrollBoxParentKey]:Refresh() - if (removeAuraFunc) then --upvalue - detailsFramework:QuickDispatch(removeAuraFunc) - end - end - - local createLineFunc = function(self, index) - local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate") - local lineHeight = scrollOptions.options.line_height - - line:SetPoint("topleft", self, "topleft", 1, -((index - 1) * (lineHeight + 1)) - 1) - line:SetSize(scrollWidth - 2, lineHeight) - line:SetScript("OnEnter", autoTrackList_LineOnEnter) - line:HookScript("OnEnter", auraLineOnEnter) - line:SetScript("OnLeave", autoTrackList_LineOnLeave) - line:HookScript("OnLeave", auraLineOnLeave) - - line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) - line:SetBackdropColor(unpack(backdropColor)) - - local icon = line:CreateTexture("$parentIcon", "overlay") - icon:SetSize(lineHeight - 2, lineHeight - 2) - - local name = line:CreateFontString("$parentName", "overlay", "GameFontNormal") - DF:SetFontSize(name, 10) - - local removeButton = CreateFrame("button", "$parentRemoveButton", line, "UIPanelCloseButton") - removeButton:SetSize(16, 16) - removeButton:SetScript("OnClick", onAuraRemoveButtonClick) - removeButton:SetPoint("topright", line, "topright") - removeButton:GetNormalTexture():SetDesaturated(true) - - icon:SetPoint("left", line, "left", 2, 0) - name:SetPoint("left", icon, "right", 3, 0) - - line.icon = icon - line.name = name - line.removebutton = removeButton - - return line - end - - local auraScrollBox = DF:CreateScrollBox(scrollBoxParent, scrollBoxName, updateFunc, databaseTable, scrollWidth, scrollHeight, scrollOptions.options.line_amount, scrollOptions.options.line_height) - DF:ReskinSlider(auraScrollBox) - scrollBoxParent[scrollBoxParentKey] = auraScrollBox - auraScrollBox.OriginalData = databaseTable - - function auraScrollBox:Refresh() - local t = {} - local added = {} - for spellID, flag in pairs(auraScrollBox.OriginalData) do - local spellName, _, spellIcon = GetSpellInfo(spellID) - if (spellName and not added[tonumber(spellID) or 0]) then - local lowerSpellName = spellName:lower() - tinsert(t, {spellID, spellName, spellIcon, lowerSpellName, flag}) - added[tonumber(spellID) or 0] = true - end - end - - table.sort(t, function(t1, t2) return t1[4] < t2[4] end) - - self:SetData(t) - self:Refresh() - end - - function auraScrollBox:DoSetData(newDB) - self:SetData(newDB) - self.OriginalData = newDB - if (self.Refresh) then - self:Refresh() - else - self:Refresh() - end - end - - local titleLabel = DF:CreateLabel(scrollBoxParent, scrollBoxTitle) - titleLabel.textcolor = "silver" - titleLabel.textsize = 10 - titleLabel:SetPoint("bottomleft", auraScrollBox, "topleft", 0, 2) - - for i = 1, lineAmount do - auraScrollBox:CreateLine(createLineFunc) - end - - auraScrollBox:Refresh() - return auraScrollBox - end -end - local onAuraRemoveCallback = function() if (changeCallback) then DF:QuickDispatch(changeCallback) @@ -855,6 +655,11 @@ end debuffTrackedAuraScrollBox:SetPoint("topleft", auraPanel_Auto, "topleft", 16 +(scrollWidth * 2) + xLocation, y) buffTrackedAuraScrollBox:SetPoint("topleft", auraPanel_Auto, "topleft", 24 +(scrollWidth * 3) + xLocation, y) + buffTrackedAuraScrollBox:GetTitleFontString():SetText(newAuraPanel.LocTexts.BUFFS_TRACKED) + debuffTrackedAuraScrollBox:GetTitleFontString():SetText(newAuraPanel.LocTexts.DEBUFFS_TRACKED) + buffIgnoredAuraScrollBox:GetTitleFontString():SetText(newAuraPanel.LocTexts.BUFFS_IGNORED) + debuffIgnoredAuraScrollBox:GetTitleFontString():SetText(newAuraPanel.LocTexts.DEBUFFS_IGNORED) + newAuraPanel.buff_ignored = buffIgnoredAuraScrollBox newAuraPanel.debuff_ignored = debuffIgnoredAuraScrollBox newAuraPanel.buff_tracked = buffTrackedAuraScrollBox diff --git a/libs/DF/buildmenu.lua b/libs/DF/buildmenu.lua index 6c76a4d7..e162ed36 100644 --- a/libs/DF/buildmenu.lua +++ b/libs/DF/buildmenu.lua @@ -93,6 +93,16 @@ local _ ---@field nocombat boolean can't edit when in combat ---@field spacement boolean gives a little of more space from the next widget +detailsFramework.OptionsFrameMixin = { + +} + +local setWidgetId = function(parent, widgetTable, widgetObject) + if (widgetTable.id) then + parent.widgetids[widgetTable.id] = widgetObject + end +end + local onEnterHighlight = function(self) self.highlightTexture:Show() if (self.parent:GetScript("OnEnter")) then @@ -139,7 +149,450 @@ local createOptionHighlightTexture = function(frame, label, widgetWidth) return highlightTexture end -local refresh_options = function(self) +local setLabelProperties = function(parent, widget, widgetTable, currentXOffset, currentYOffset, template) + widget._get = widgetTable.get + widget.widget_type = "label" + widget:SetPoint(currentXOffset, currentYOffset) + + if (widgetTable.text_template or template) then + widget:SetTemplate(widgetTable.text_template or template) + else + widget.fontsize = widgetTable.size or 10 + end + + if (widgetTable.font) then + widget.fontface = widgetTable.font + end + + setWidgetId(parent, widgetTable, widget) +end + +local setDropdownProperties = function(parent, widget, widgetTable, currentXOffset, currentYOffset, template, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth) + widget._get = widgetTable.get + widget.widget_type = "select" + + widget:Refresh() + widget:Select(widgetTable.get()) + widget:SetTemplate(template) + + if (widgetWidth) then + widget:SetWidth(widgetWidth) + end + if (widgetHeight) then + widget:SetHeight(widgetHeight) + end + + setWidgetId(parent, widgetTable, widget) + + local label = widget.hasLabel.widget + + widget:ClearAllPoints() + label:ClearAllPoints() + + if (bAlignAsPairs) then --regular + PixelUtil.SetPoint(label, "topleft", widget:GetParent(), "topleft", currentXOffset, currentYOffset) + PixelUtil.SetPoint(widget.widget, "left", label, "left", nAlignAsPairsLength, 0) + + if (not widget.highlightFrame) then + local highlightFrame = createOptionHighlightTexture(widget, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) + widget.highlightFrame = highlightFrame + end + else + widget:SetPoint("left", label, "right", 2, 0) + label:SetPoint("topleft", parent, "topleft", currentXOffset, currentYOffset) + end + + --global callback + if (valueChangeHook) then + widget:SetHook("OnOptionSelected", valueChangeHook) + end + + --hook list + if (widgetTable.hooks) then + for hookName, hookFunc in pairs(widgetTable.hooks) do + widget:SetHook(hookName, hookFunc) + end + end + + local widgetTotalSize = label:GetStringWidth() + 144 + if (widgetTotalSize > maxColumnWidth) then + maxColumnWidth = widgetTotalSize + end + + if (widget:GetWidth() > maxWidgetWidth) then + maxWidgetWidth = widget:GetWidth() + end + + return maxColumnWidth, maxWidgetWidth +end + +local setToggleProperties = function(parent, widget, widgetTable, currentXOffset, currentYOffset, template, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, switchIsCheckbox, bUseBoxFirstOnAllWidgets, menuOptions, index, maxWidgetWidth) + widget._get = widgetTable.get + widget.widget_type = "toggle" + widget.OnSwitch = widgetTable.set + + if (switchIsCheckbox) then + widget:SetAsCheckBox() + end + + widget:SetValue(widgetTable.get()) + + if (widgetWidth) then + PixelUtil.SetWidth(widget.widget, widgetWidth) + end + if (widgetHeight) then + PixelUtil.SetHeight(widget.widget, widgetHeight) + end + + widget:SetTemplate(template) + + setWidgetId(parent, widgetTable, widget) + + local label = widget.hasLabel.widget + + widget:ClearAllPoints() + label:ClearAllPoints() + + local extraPaddingY = 0 + + if (bAlignAsPairs) then + PixelUtil.SetPoint(label, "topleft", widget:GetParent(), "topleft", currentXOffset, currentYOffset) + PixelUtil.SetPoint(widget.widget, "left", label, "left", nAlignAsPairsLength, 0) + + if (not widget.highlightFrame) then + local highlightFrame = createOptionHighlightTexture(widget, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) + widget.highlightFrame = highlightFrame + end + else + if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then + label:SetPoint("left", widget.widget or widget, "right", 2, 0) + widget:SetPoint("topleft", parent, "topleft", currentXOffset, currentYOffset) + + local nextWidgetTable = menuOptions[index+1] + if (nextWidgetTable) then + if (nextWidgetTable.type ~= "blank" and nextWidgetTable.type ~= "breakline" and nextWidgetTable.type ~= "toggle" and nextWidgetTable.type ~= "color") then + extraPaddingY = 4 + end + end + else + widget:SetPoint("left", label, "right", 2, 0) + label:SetPoint("topleft", parent, "topleft", currentXOffset, currentYOffset) + end + end + + --global callback + if (valueChangeHook) then + widget:SetHook("OnSwitch", valueChangeHook) + end + + --hook list + if (widgetTable.hooks) then + for hookName, hookFunc in pairs(widgetTable.hooks) do + widget:SetHook(hookName, hookFunc) + end + end + + local widgetTotalSize = label:GetStringWidth() + 32 + if (widgetTotalSize > maxColumnWidth) then + maxColumnWidth = widgetTotalSize + end + + if (widget:GetWidth() > maxWidgetWidth) then + maxWidgetWidth = widget:GetWidth() + end + + return maxColumnWidth, maxWidgetWidth, extraPaddingY +end + +local setRangeProperties = function(parent, widget, widgetTable, currentXOffset, currentYOffset, template, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, bIsDecimals, bAttachSliderButtonsToLeft) + widget._get = widgetTable.get + widget.widget_type = "range" + widget:SetTemplate(template) + + widget.bAttachButtonsToLeft = bAttachSliderButtonsToLeft + + if (bIsDecimals) then + widget.slider:SetValueStep(0.01) + else + widget.slider:SetValueStep(widgetTable.step or 1) + end + widget.useDecimals = bIsDecimals + + widget.slider:SetMinMaxValues(widgetTable.min, widgetTable.max) + widget.slider:SetValue(widgetTable.get() or 0) + widget.ivalue = widget.slider:GetValue() + + if (widgetWidth) then + widget:SetWidth(widgetWidth) + end + if (widgetHeight) then + widget:SetHeight(widgetHeight) + end + + widget:SetHook("OnValueChange", widgetTable.set) + + if (valueChangeHook) then + widget:SetHook("OnValueChange", valueChangeHook) + end + + if (widgetTable.thumbscale) then + widget:SetThumbSize(widget.thumb.originalWidth * widgetTable.thumbscale, nil) + else + widget:SetThumbSize(widget.thumb.originalWidth * 1.3, nil) + end + + --hook list + if (widgetTable.hooks) then + for hookName, hookFunc in pairs(widgetTable.hooks) do + widget:SetHook(hookName, hookFunc) + end + end + + setWidgetId(parent, widgetTable, widget) + + local label = widget.hasLabel.widget + + widget:ClearAllPoints() + label:ClearAllPoints() + + if (bAlignAsPairs) then + PixelUtil.SetPoint(label, "topleft", widget:GetParent(), "topleft", currentXOffset, currentYOffset) + PixelUtil.SetPoint(widget.widget, "left", label, "left", nAlignAsPairsLength, 0) + + if (not widget.highlightFrame) then + local highlightFrame = createOptionHighlightTexture(widget, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) + widget.highlightFrame = highlightFrame + end + else + widget:SetPoint("left", label, "right", 2, 0) + label:SetPoint("topleft", parent, "topleft", currentXOffset, currentYOffset) + end + + local widgetTotalSize = label:GetStringWidth() + 146 + if (widgetTotalSize > maxColumnWidth) then + maxColumnWidth = widgetTotalSize + end + + if (widget:GetWidth() > maxWidgetWidth) then + maxWidgetWidth = widget:GetWidth() + end + + return maxColumnWidth, maxWidgetWidth +end + +local setColorProperties = function(parent, widget, widgetTable, currentXOffset, currentYOffset, template, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, bUseBoxFirstOnAllWidgets, extraPaddingY) + widget._get = widgetTable.get + widget.widget_type = "color" + + local r, g, b, a = detailsFramework:ParseColors(widgetTable.get()) + widget:SetColor(r, g, b, a) + + widget.color_callback = widgetTable.set --callback + + --[=[ + if (widgetWidth) then + widget:SetWidth(widgetWidth) + else + widget:SetWidth(18) + end + + if (widgetHeight) then + widget:SetHeight(widgetHeight) + else + widget:SetHeight(18) + end + --]=] + + widget:SetTemplate(template) + widget:SetWidth(18) + widget:SetHeight(18) + + widget:SetHook("OnColorChanged", widgetTable.set) + + if (valueChangeHook) then + widget:SetHook("OnColorChanged", valueChangeHook) + end + + --hook list + if (widgetTable.hooks) then + for hookName, hookFunc in pairs(widgetTable.hooks) do + widget:SetHook(hookName, hookFunc) + end + end + + setWidgetId(parent, widgetTable, widget) + + local label = widget.hasLabel.widget + + widget:ClearAllPoints() + label:ClearAllPoints() + + if (bAlignAsPairs) then + PixelUtil.SetPoint(label, "topleft", widget:GetParent(), "topleft", currentXOffset, currentYOffset) + PixelUtil.SetPoint(widget.widget, "left", label, "left", nAlignAsPairsLength, 0) + + if (not widget.highlightFrame) then + local highlightFrame = createOptionHighlightTexture(widget, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) + widget.highlightFrame = highlightFrame + end + else + if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then + label:SetPoint("left", widget.widget, "right", 2, 0) + widget:SetPoint(currentXOffset, currentYOffset) + extraPaddingY = 1 + else + widget:SetPoint("left", label, "right", 2, 0) + label:SetPoint("topleft", parent, "topleft", currentXOffset, currentYOffset) + end + end + + local widgetTotalSize = label:GetStringWidth() + 32 + if (widgetTotalSize > maxColumnWidth) then + maxColumnWidth = widgetTotalSize + end + + if (widget:GetWidth() > maxWidgetWidth) then + maxWidgetWidth = widget:GetWidth() + end + + return maxColumnWidth, maxWidgetWidth, extraPaddingY +end + +local setExecuteProperties = function(parent, widget, widgetTable, currentXOffset, currentYOffset, template, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, textTemplate, latestInlineWidget) + widget._get = widgetTable.get + widget.widget_type = "execute" + widget:SetTemplate(template) + widget:SetWidth(widgetWidth or widgetTable.width or 120, widgetHeight or widgetTable.height or 18) + + widget:SetClickFunction(widgetTable.func, widgetTable.param1, widgetTable.param2) + + --button icon + if (widgetTable.icontexture) then + widget:SetIcon(widgetTable.icontexture, nil, nil, nil, widgetTable.icontexcoords, nil, nil, 2) + end + + textTemplate = widgetTable.text_template or textTemplate or detailsFramework.font_templates["ORANGE_FONT_TEMPLATE"] + widget.textcolor = textTemplate.color + widget.textfont = textTemplate.font + widget.textsize = textTemplate.size + + --hook list + if (widgetTable.hooks) then + for hookName, hookFunc in pairs(widgetTable.hooks) do + widget:SetHook(hookName, hookFunc) + end + end + + setWidgetId(parent, widgetTable, widget) + + local label = widget.hasLabel.widget + + widget:ClearAllPoints() + label:ClearAllPoints() + + if (bAlignAsPairs) then + PixelUtil.SetPoint(label, "topleft", widget:GetParent(), "topleft", currentXOffset, currentYOffset) + PixelUtil.SetPoint(widget.widget, "left", label, "left", nAlignAsPairsLength, 0) + + if (not widget.highlightFrame) then + local highlightFrame = createOptionHighlightTexture(widget, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) + widget.highlightFrame = highlightFrame + end + else + if (widgetTable.inline) then + if (latestInlineWidget) then + widget:SetPoint("left", latestInlineWidget, "right", 2, 0) + latestInlineWidget = widget + else + widget:SetPoint(currentXOffset, currentYOffset) + latestInlineWidget = widget + end + else + widget:SetPoint(currentXOffset, currentYOffset) + end + end + + local widgetTotalSize = widget:GetWidth() + 4 + if (widgetTotalSize > maxColumnWidth) then + maxColumnWidth = widgetTotalSize + end + + if (widget:GetWidth() > maxWidgetWidth) then + maxWidgetWidth = widget:GetWidth() + end + + return maxColumnWidth, maxWidgetWidth, latestInlineWidget +end + +local setTextEntryProperties = function(parent, widget, widgetTable, currentXOffset, currentYOffset, template, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, textTemplate, latestInlineWidget) + widget._get = widgetTable.get + widget.text = widgetTable.get() + widget.widget_type = "textentry" + widget:SetTemplate(widgetTable.template or widgetTable.button_template or template) + widget:SetWidth(widgetWidth or widgetTable.width or 120, widgetHeight or widgetTable.height or 18) + widget:SetCommitFunction(widgetTable.func or widgetTable.set) + + widget:SetHook("OnEnterPressed", function(...) + local upFunc = widgetTable.func or widgetTable.set + upFunc(...) + if (valueChangeHook) then + valueChangeHook() + end + end) + + widget:SetHook("OnEditFocusLost", function(...) + local upFunc = widgetTable.func or widgetTable.set + upFunc(...) + if (valueChangeHook) then + valueChangeHook() + end + end) + + textTemplate = widgetTable.text_template or textTemplate or detailsFramework.font_templates["ORANGE_FONT_TEMPLATE"] + widget.textcolor = textTemplate.color + widget.textfont = textTemplate.font + widget.textsize = textTemplate.size + + --hook list + if (widgetTable.hooks) then + for hookName, hookFunc in pairs(widgetTable.hooks) do + widget:SetHook(hookName, hookFunc) + end + end + + setWidgetId(parent, widgetTable, widget) + + local label = widget.hasLabel.widget + + widget:ClearAllPoints() + label:ClearAllPoints() + + if (bAlignAsPairs) then + PixelUtil.SetPoint(label, "topleft", widget:GetParent(), "topleft", currentXOffset, currentYOffset) + PixelUtil.SetPoint(widget.widget, "left", label, "left", nAlignAsPairsLength, 0) + + if (not widget.highlightFrame) then + local highlightFrame = createOptionHighlightTexture(widget, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) + widget.highlightFrame = highlightFrame + end + else + widget:SetPoint("left", label, "right", 2, 0) + label:SetPoint("topleft", parent, "topleft", currentXOffset, currentYOffset) + end + + local widgetTotalSize = label:GetStringWidth() + 64 --need review, might not be correct + if (widgetTotalSize > maxColumnWidth) then + maxColumnWidth = widgetTotalSize + end + + if (widget:GetWidth() > maxWidgetWidth) then + maxWidgetWidth = widget:GetWidth() + end + + return maxColumnWidth, maxWidgetWidth +end + +local refreshOptions = function(self) for _, widget in ipairs(self.widget_list) do if (widget._get) then if (widget.widget_type == "label") then @@ -169,7 +622,77 @@ local refresh_options = function(self) end end -detailsFramework.internalFunctions.RefreshOptionsPanel = refresh_options +detailsFramework.internalFunctions.RefreshOptionsPanel = refreshOptions + +local parseOptionsTypes = function(menuOptions) + --normalize format types + for index, widgetTable in ipairs(menuOptions) do + if (widgetTable.type == "space") then + widgetTable.type = "blank" + + elseif (widgetTable.type == "fontdropdown") then + widgetTable.type = "selectfont" + elseif (widgetTable.type == "colordropdown") then + widgetTable.type = "selectcolor" + elseif (widgetTable.type == "outlinedropdown") then + widgetTable.type = "selectoutline" + elseif (widgetTable.type == "anchordropdown") then + widgetTable.type = "selectanchor" + elseif (widgetTable.type == "dropdown") then + widgetTable.type = "select" + + elseif (widgetTable.type == "switch") then + widgetTable.type = "toggle" + + elseif (widgetTable.type == "slider") then + widgetTable.type = "range" + + elseif (widgetTable.type == "button") then + widgetTable.type = "execute" + end + end +end + +local parseOptionsTable = function(menuOptions) + local bUseBoxFirstOnAllWidgets = menuOptions.always_boxfirst + local widgetWidth = menuOptions.widget_width --a width to be used on all widgets + local widgetHeight = menuOptions.widget_height --a height to be used on all widgets + local bAlignAsPairs = menuOptions.align_as_pairs + local nAlignAsPairsLength = menuOptions.align_as_pairs_string_space or 160 + local nAlignAsPairsSpacing = menuOptions.align_as_pairs_spacing or 20 + local bAttachSliderButtonsToLeft = menuOptions.slider_buttons_to_left + + --if a scrollbox is passed, the height can be ignored + --the scrollBox child will be used as the parent, and the height of the child will be resized to fit the widgets + local bUseScrollFrame = menuOptions.use_scrollframe + local languageAddonId = menuOptions.language_addonId + return bUseBoxFirstOnAllWidgets, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, nAlignAsPairsSpacing, bUseScrollFrame, languageAddonId, bAttachSliderButtonsToLeft +end + +local parseParent = function(bUseScrollFrame, parent, height, yOffset) + if (bUseScrollFrame) then + local width, height = parent:GetSize() + parent = parent:GetScrollChild() + parent:SetSize(width, height) + else + if (height and type(height) == "number") then + height = math.abs((height or parent:GetHeight()) - math.abs(yOffset) + 20) + height = height * -1 + else + height = parent:GetHeight() + end + end + + return parent, height +end + +local parseLanguageTable = function(languageAddonId) + local languageTable + if (languageAddonId) then + languageTable = DetailsFramework.Language.GetLanguageTable(languageAddonId) + end + return languageTable +end local getFrameById = function(self, id) return self.widgetids[id] @@ -186,13 +709,14 @@ function detailsFramework:ClearOptionsPanel(frame) end function detailsFramework:SetAsOptionsPanel(frame) - frame.RefreshOptions = refresh_options + --print("refresh_options", refresh_options) + frame.RefreshOptions = refreshOptions frame.widget_list = {} frame.widget_list_by_type = { ["dropdown"] = {}, -- "select" ["switch"] = {}, -- "toggle" ["slider"] = {}, -- "range" - ["color"] = {}, -- + ["color"] = {}, -- ["button"] = {}, -- "execute" ["textentry"] = {}, -- ["label"] = {}, --"text" @@ -374,12 +898,15 @@ function detailsFramework:BuildMenuVolatile(parent, menuOptions, xOffset, yOffse end detailsFramework:ClearOptionsPanel(parent) + local amountLineWidgetAdded = 0 + local biggestColumnHeight = 0 --used to resize the scrollbox child when a scrollbox is passed + local latestInlineWidget local currentXOffset = xOffset or 0 local currentYOffset = yOffset or 0 - local maxColumnWidth = 0 - - local latestInlineWidget + local maxColumnWidth = 0 --biggest width of widget + text size on the current column loop pass + local maxWidgetWidth = 0 --biggest widget width on the current column loop pass + --which is the next widget to get from the pool local widgetIndexes = { label = 1, dropdown = 1, @@ -390,62 +917,20 @@ function detailsFramework:BuildMenuVolatile(parent, menuOptions, xOffset, yOffse textentry = 1, } - if (height and type(height) == "number") then - height = math.abs((height or parent:GetHeight()) - math.abs(yOffset) + 20) - height = height * -1 - else - height = parent:GetHeight() - end + parseOptionsTypes(menuOptions) + local bUseBoxFirstOnAllWidgets, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, nAlignAsPairsSpacing, bUseScrollFrame, languageAddonId, bAttachSliderButtonsToLeft = parseOptionsTable(menuOptions) + parent, height = parseParent(bUseScrollFrame, parent, height, yOffset) + local languageTable = parseLanguageTable(languageAddonId) - --normalize format types for index, widgetTable in ipairs(menuOptions) do - if (widgetTable.type == "space") then - widgetTable.type = "blank" - - elseif (widgetTable.type == "fontdropdown") then - widgetTable.type = "selectfont" - elseif (widgetTable.type == "colordropdown") then - widgetTable.type = "selectcolor" - elseif (widgetTable.type == "outlinedropdown") then - widgetTable.type = "selectoutline" - elseif (widgetTable.type == "anchordropdown") then - widgetTable.type = "selectanchor" - elseif (widgetTable.type == "dropdown") then - widgetTable.type = "select" - - elseif (widgetTable.type == "switch") then - widgetTable.type = "toggle" - - elseif (widgetTable.type == "slider") then - widgetTable.type = "range" - - elseif (widgetTable.type == "button") then - widgetTable.type = "execute" - end - end - - --catch some options added in the hash part of the menu table - local bUseBoxFirstOnAllWidgets = menuOptions.always_boxfirst - local bAlignAsPairs = menuOptions.align_as_pairs - local nAlignAsPairsLength = menuOptions.align_as_pairs_string_space or 160 - local languageAddonId = menuOptions.language_addonId - local widgetWidth = menuOptions.widget_width - local widgetHeight = menuOptions.widget_height - local languageTable - - if (languageAddonId) then - languageTable = DetailsFramework.Language.GetLanguageTable(languageAddonId) - end - - for index, widgetTable in ipairs(menuOptions) do - if (not widgetTable.hidden) then - local widgetCreated - if (latestInlineWidget) then - if (not widgetTable.inline) then - latestInlineWidget = nil - currentYOffset = currentYOffset - 20 - end - end + if (not widgetTable.hidden) then + local widgetCreated + if (latestInlineWidget) then + if (not widgetTable.inline) then + latestInlineWidget = nil + currentYOffset = currentYOffset - 20 + end + end local extraPaddingY = 0 @@ -456,439 +941,131 @@ function detailsFramework:BuildMenuVolatile(parent, menuOptions, xOffset, yOffse elseif (widgetTable.type == "label" or widgetTable.type == "text") then local label = getMenuWidgetVolative(parent, "label", widgetIndexes) + label:ClearAllPoints() widgetCreated = label + setLabelProperties(parent, label, widgetTable, currentXOffset, currentYOffset, textTemplate) + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable) local namePhrase = (languageTable and (languageTable[namePhraseId] or languageTable[widgetTable.namePhraseId] or languageTable[widgetTable.name])) or (widgetTable.get and widgetTable.get()) or widgetTable.text or (widgetTable.namePhraseId) or "" label.text = namePhrase label.color = widgetTable.color - if (widgetTable.font) then - label.fontface = widgetTable.font - end - - if (widgetTable.text_template or textTemplate) then - label:SetTemplate(widgetTable.text_template or textTemplate) - else - label.fontsize = widgetTable.size or 10 - end - - label._get = widgetTable.get - label.widget_type = "label" - label:ClearAllPoints() - label:SetPoint(currentXOffset, currentYOffset) - - if (widgetTable.id) then - parent.widgetids [widgetTable.id] = label - end + amountLineWidgetAdded = amountLineWidgetAdded + 1 --dropdowns elseif (widgetTable.type:find("select")) then assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get() not found in the widget table for 'select'") local dropdown = getMenuWidgetVolative(parent, "dropdown", widgetIndexes) widgetCreated = dropdown + local defaultHeight = 18 - if (widgetTable.type == "selectfont") then - local func = detailsFramework:CreateFontListGenerator(widgetTable.set) - dropdown:SetFunction(func) - - elseif (widgetTable.type == "selectcolor") then - local func = detailsFramework:CreateColorListGenerator(widgetTable.set) - dropdown:SetFunction(func) - - elseif (widgetTable.type == "selectanchor") then - local func = detailsFramework:CreateAnchorPointListGenerator(widgetTable.set) - dropdown:SetFunction(func) + do + if (widgetTable.type == "selectfont") then + local func = detailsFramework:CreateFontListGenerator(widgetTable.set) + dropdown:SetFunction(func) - elseif (widgetTable.type == "selectoutline") then - local func = detailsFramework:CreateOutlineListGenerator(widgetTable.set) - dropdown:SetFunction(func) - else - dropdown:SetFunction(widgetTable.values) - end + elseif (widgetTable.type == "selectcolor") then + local func = detailsFramework:CreateColorListGenerator(widgetTable.set) + dropdown:SetFunction(func) - dropdown:Refresh() - dropdown:Select(widgetTable.get()) - dropdown:SetTemplate(dropdownTemplate) + elseif (widgetTable.type == "selectanchor") then + local func = detailsFramework:CreateAnchorPointListGenerator(widgetTable.set) + dropdown:SetFunction(func) - if (widgetWidth) then - dropdown:SetWidth(widgetWidth) - end - if (widgetHeight) then - dropdown:SetHeight(widgetHeight) + elseif (widgetTable.type == "selectoutline") then + local func = detailsFramework:CreateOutlineListGenerator(widgetTable.set) + dropdown:SetFunction(func) + else + dropdown:SetFunction(widgetTable.values) + end end local descPhrase = getDescPhraseText(languageTable, widgetTable) dropdown:SetTooltip(descPhrase) - dropdown._get = widgetTable.get - dropdown.widget_type = "select" local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId) dropdown.hasLabel.text = namePhrase - dropdown.hasLabel:SetTemplate(widgetTable.text_template or textTemplate) - --as these are reused widgets, clean the previous point - dropdown:ClearAllPoints() - dropdown.hasLabel:ClearAllPoints() - - if (bAlignAsPairs) then - dropdown.hasLabel:SetPoint(currentXOffset, currentYOffset) - dropdown:SetPoint("left", dropdown.hasLabel, "left", nAlignAsPairsLength, 0) - else - dropdown:SetPoint("left", dropdown.hasLabel, "right", 2, 0) - dropdown.hasLabel:SetPoint(currentXOffset, currentYOffset) - end - - --global callback - if (valueChangeHook) then - dropdown:SetHook("OnOptionSelected", valueChangeHook) - end - - --hook list (hook list is wiped when getting the widget) - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - dropdown:SetHook(hookName, hookFunc) - end - end - - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = dropdown - end - - local widgetTotalSize = dropdown.hasLabel.widget:GetStringWidth() + 140 + 4 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + maxColumnWidth, maxWidgetWidth = setDropdownProperties(parent, dropdown, widgetTable, currentXOffset, currentYOffset, textTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth) + amountLineWidgetAdded = amountLineWidgetAdded + 1 --switchs elseif (widgetTable.type == "toggle" or widgetTable.type == "switch") then local switch = getMenuWidgetVolative(parent, "switch", widgetIndexes) widgetCreated = switch - switch:SetValue(widgetTable.get()) - switch:SetTemplate(switchTemplate) - switch:SetAsCheckBox() --it's always a checkbox on volatile menu - local descPhrase = getDescPhraseText(languageTable, widgetTable) switch:SetTooltip(descPhrase) - switch._get = widgetTable.get - switch.widget_type = "toggle" - switch.OnSwitch = widgetTable.set - - if (valueChangeHook) then - switch:SetHook("OnSwitch", valueChangeHook) - end - - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - switch:SetHook(hookName, hookFunc) - end - end - - if (widgetTable.width) then - switch:SetWidth(widgetTable.width) - end - if (widgetTable.height) then - switch:SetHeight(widgetTable.height) - end local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId) switch.hasLabel.text = namePhrase switch.hasLabel:SetTemplate(widgetTable.text_template or textTemplate) - switch:ClearAllPoints() - switch.hasLabel:ClearAllPoints() - - if (bAlignAsPairs) then - switch.hasLabel:SetPoint(currentXOffset, currentYOffset) - switch:SetPoint("left", switch.hasLabel, "left", nAlignAsPairsLength, 0) - else - if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then - switch:SetPoint(currentXOffset, currentYOffset) - switch.hasLabel:SetPoint("left", switch, "right", 2) - - local nextWidgetTable = menuOptions[index+1] - if (nextWidgetTable) then - if (nextWidgetTable.type ~= "blank" and nextWidgetTable.type ~= "breakline" and nextWidgetTable.type ~= "toggle" and nextWidgetTable.type ~= "color") then - extraPaddingY = 4 - end - end - else - switch.hasLabel:SetPoint(currentXOffset, currentYOffset) - switch:SetPoint("left", switch.hasLabel, "right", 2) - end - end - - if (widgetTable.id) then - parent.widgetids [widgetTable.id] = switch - end - - local widgetTotalSize = switch.hasLabel:GetStringWidth() + 32 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + maxColumnWidth, maxWidgetWidth, extraPaddingY = setToggleProperties(parent, switch, widgetTable, currentXOffset, currentYOffset, switchTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, true, bUseBoxFirstOnAllWidgets, menuOptions, index, maxWidgetWidth) + amountLineWidgetAdded = amountLineWidgetAdded + 1 --slider - elseif (widgetTable.type == "range" or widgetTable.type == "slider") then + elseif (widgetTable.type == "range") then local slider = getMenuWidgetVolative(parent, "slider", widgetIndexes) widgetCreated = slider - if (widgetTable.usedecimals) then - slider.slider:SetValueStep(0.01) - else - slider.slider:SetValueStep(widgetTable.step or 1) - end - slider.useDecimals = widgetTable.usedecimals - - slider.slider:SetMinMaxValues(widgetTable.min, widgetTable.max) - slider.slider:SetValue(widgetTable.get()) - slider.ivalue = slider.slider:GetValue() - - slider:SetTemplate(sliderTemplate) - - if (widgetWidth) then - slider:SetWidth(widgetWidth) - end - if (widgetHeight) then - slider:SetHeight(widgetHeight) - end - local descPhrase = getDescPhraseText(languageTable, widgetTable) slider:SetTooltip(descPhrase) - slider._get = widgetTable.get - slider.widget_type = "range" - slider:SetHook("OnValueChange", widgetTable.set) - - if (valueChangeHook) then - slider:SetHook("OnValueChange", valueChangeHook) - end - - if (widgetTable.thumbscale) then - slider:SetThumbSize (slider.thumb.originalWidth * widgetTable.thumbscale, nil) - else - slider:SetThumbSize (slider.thumb.originalWidth * 1.3, nil) - end - - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - slider:SetHook(hookName, hookFunc) - end - end local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId) slider.hasLabel.text = namePhrase slider.hasLabel:SetTemplate(widgetTable.text_template or textTemplate) - slider:ClearAllPoints() - slider.hasLabel:ClearAllPoints() - - if (bAlignAsPairs) then - slider.hasLabel:SetPoint(currentXOffset, currentYOffset) - slider:SetPoint("left", slider.hasLabel, "left", nAlignAsPairsLength, 0) - else - slider:SetPoint("left", slider.hasLabel, "right", 2) - slider.hasLabel:SetPoint(currentXOffset, currentYOffset) - end - - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = slider - end - - local widgetTotalSize = slider.hasLabel:GetStringWidth() + 146 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + maxColumnWidth, maxWidgetWidth = setRangeProperties(parent, slider, widgetTable, currentXOffset, currentYOffset, sliderTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, widgetTable.usedecimals, bAttachSliderButtonsToLeft) + amountLineWidgetAdded = amountLineWidgetAdded + 1 --color - elseif (widgetTable.type == "color" or widgetTable.type == "color") then + elseif (widgetTable.type == "color") then local colorpick = getMenuWidgetVolative(parent, "color", widgetIndexes) widgetCreated = colorpick - colorpick.color_callback = widgetTable.set --callback - colorpick:SetTemplate(buttonTemplate) - colorpick:SetSize(18, 18) - local descPhrase = getDescPhraseText(languageTable, widgetTable) colorpick:SetTooltip(descPhrase) - colorpick._get = widgetTable.get - colorpick.widget_type = "color" - - local default_value, g, b, a = widgetTable.get() - if (type(default_value) == "table") then - colorpick:SetColor(unpack(default_value)) - else - colorpick:SetColor(default_value, g, b, a) - end - - if (valueChangeHook) then - colorpick:SetHook("OnColorChanged", valueChangeHook) - end - - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - colorpick:SetHook(hookName, hookFunc) - end - end local label = colorpick.hasLabel - local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId) label.text = namePhrase label:SetTemplate(widgetTable.text_template or textTemplate) - label:ClearAllPoints() - colorpick:ClearAllPoints() - - if (bAlignAsPairs) then - label:SetPoint(currentXOffset, currentYOffset) - colorpick:SetPoint("left", label, "left", nAlignAsPairsLength, 0) - else - if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then - label:SetPoint("left", colorpick, "right", 2, 0) - colorpick:SetPoint(currentXOffset, currentYOffset) - extraPaddingY = 1 - else - colorpick:SetPoint("left", label, "right", 2, 0) - label:SetPoint(currentXOffset, currentYOffset) - end - end - - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = colorpick - end - - local widgetTotalSize = label:GetStringWidth() + 32 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + maxColumnWidth, maxWidgetWidth, extraPaddingY = setColorProperties(parent, colorpick, widgetTable, currentXOffset, currentYOffset, switchTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, bUseBoxFirstOnAllWidgets, extraPaddingY) + amountLineWidgetAdded = amountLineWidgetAdded + 1 --button elseif (widgetTable.type == "execute" or widgetTable.type == "button") then local button = getMenuWidgetVolative(parent, "button", widgetIndexes) + button.widget_type = "execute" widgetCreated = button - button:SetTemplate(buttonTemplate) - button:SetSize(widgetWidth or widgetTable.width or 120, widgetHeight or widgetTable.height or 18) - button:SetClickFunction(widgetTable.func, widgetTable.param1, widgetTable.param2) - - local textTemplate = widgetTable.text_template or textTemplate or detailsFramework.font_templates["ORANGE_FONT_TEMPLATE"] - button.textcolor = textTemplate.color - button.textfont = textTemplate.font - button.textsize = textTemplate.size + maxColumnWidth, maxWidgetWidth, latestInlineWidget = setExecuteProperties(parent, button, widgetTable, currentXOffset, currentYOffset, buttonTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, textTemplate, latestInlineWidget) local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId) button.text = namePhrase - button:ClearAllPoints() - - if (bAlignAsPairs) then - button:SetPoint(currentXOffset, currentYOffset) - else - if (widgetTable.inline) then - if (latestInlineWidget) then - button:SetPoint("left", latestInlineWidget, "right", 2, 0) - latestInlineWidget = button - else - button:SetPoint(currentXOffset, currentYOffset) - latestInlineWidget = button - end - else - button:SetPoint(currentXOffset, currentYOffset) - end - end - local descPhrase = getDescPhraseText(languageTable, widgetTable) button:SetTooltip(descPhrase) - button.widget_type = "execute" - - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - button:SetHook(hookName, hookFunc) - end - end - - if (widgetTable.width) then - button:SetWidth(widgetTable.width) - end - if (widgetTable.height) then - button:SetHeight(widgetTable.height) - end - - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = button - end - - local widgetTotalSize = button:GetWidth() + 4 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + amountLineWidgetAdded = amountLineWidgetAdded + 1 --textentry elseif (widgetTable.type == "textentry") then local textentry = getMenuWidgetVolative(parent, "textentry", widgetIndexes) widgetCreated = textentry - textentry:SetCommitFunction(widgetTable.func or widgetTable.set) - textentry:SetTemplate(widgetTable.template or widgetTable.button_template or buttonTemplate) - textentry:SetSize(widgetWidth or widgetTable.width or 120, widgetHeight or widgetTable.height or 18) - local descPhrase = getDescPhraseText(languageTable, widgetTable) textentry:SetTooltip(descPhrase) - textentry.text = widgetTable.get() - textentry._get = widgetTable.get - textentry.widget_type = "textentry" - - textentry:SetHook("OnEnterPressed", function(...) - local upFunc = widgetTable.func or widgetTable.set - upFunc(...) - if (valueChangeHook) then - valueChangeHook() - end - end) - textentry:SetHook("OnEditFocusLost", function(...) - local upFunc = widgetTable.func or widgetTable.set - upFunc(...) - if (valueChangeHook) then - valueChangeHook() - end - end) local namePhrase = getNamePhraseText(languageTable, widgetTable, useColon, languageAddonId) textentry.hasLabel.text = namePhrase textentry.hasLabel:SetTemplate(widgetTable.text_template or textTemplate) - textentry.hasLabel:ClearAllPoints() - textentry:ClearAllPoints() - - if (bAlignAsPairs) then - textentry.hasLabel:SetPoint(currentXOffset, currentYOffset) - textentry:SetPoint("left", textentry.hasLabel, "left", nAlignAsPairsLength, 0) - else - textentry:SetPoint("left", textentry.hasLabel, "right", 2) - textentry.hasLabel:SetPoint(currentXOffset, currentYOffset) - end - - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - textentry:SetHook(hookName, hookFunc) - end - end - - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = textentry - end - - local widgetTotalSize = textentry.hasLabel:GetStringWidth() + 64 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end - + maxColumnWidth, maxWidgetWidth = setTextEntryProperties(parent, textentry, widgetTable, currentXOffset, currentYOffset, buttonTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, textTemplate) + amountLineWidgetAdded = amountLineWidgetAdded + 1 end --end loop if (widgetTable.nocombat) then @@ -907,10 +1084,28 @@ function detailsFramework:BuildMenuVolatile(parent, menuOptions, xOffset, yOffse currentYOffset = currentYOffset - extraPaddingY end - if (widgetTable.type == "breakline" or currentYOffset < height) then - currentYOffset = yOffset - currentXOffset = currentXOffset + maxColumnWidth + 20 - maxColumnWidth = 0 + if (bUseScrollFrame) then + if (widgetTable.type == "breakline") then + biggestColumnHeight = math.min(currentYOffset, biggestColumnHeight) + currentYOffset = yOffset + + if (bAlignAsPairs) then + currentXOffset = currentXOffset + nAlignAsPairsLength + (widgetWidth or maxWidgetWidth) + nAlignAsPairsSpacing + else + currentXOffset = currentXOffset + maxColumnWidth + 20 + end + + amountLineWidgetAdded = 0 + maxColumnWidth = 0 + maxWidgetWidth = 0 + end + else + if (widgetTable.type == "breakline" or currentYOffset < height) then + currentYOffset = yOffset + currentXOffset = currentXOffset + maxColumnWidth + 20 + amountLineWidgetAdded = 0 + maxColumnWidth = 0 + end end if widgetCreated then @@ -940,668 +1135,347 @@ local getDescripttionPhraseID = function(widgetTable, languageAddonId, languageT return widgetTable.desc end - ---classes used by the menu builder on the menuOptions table on both functions BuildMenu and BuildMenuVolatile - ---the menuOptions consists of a table with several tables inside in array, each table is a widget to be created - ---class df_menu_label is used when the sub table of menuOptions has a key named "type" with the value "label" or "text" - function detailsFramework:BuildMenu(parent, menuOptions, xOffset, yOffset, height, useColon, textTemplate, dropdownTemplate, switchTemplate, switchIsCheckbox, sliderTemplate, buttonTemplate, valueChangeHook) - --how many widgets has been created on this line loop pass - local amountLineWidgetCreated = 0 - local latestInlineWidget - - --normalize format types - for index, widgetTable in ipairs(menuOptions) do - if (widgetTable.type == "space") then - widgetTable.type = "blank" - - elseif (widgetTable.type == "fontdropdown") then - widgetTable.type = "selectfont" - elseif (widgetTable.type == "colordropdown") then - widgetTable.type = "selectcolor" - elseif (widgetTable.type == "outlinedropdown") then - widgetTable.type = "selectoutline" - elseif (widgetTable.type == "anchordropdown") then - widgetTable.type = "selectanchor" - elseif (widgetTable.type == "dropdown") then - widgetTable.type = "select" - - elseif (widgetTable.type == "switch") then - widgetTable.type = "toggle" - - elseif (widgetTable.type == "slider") then - widgetTable.type = "range" - - elseif (widgetTable.type == "button") then - widgetTable.type = "execute" - end - end - - --catch some options added in the hash part of the menu table - local bUseBoxFirstOnAllWidgets = menuOptions.always_boxfirst - local widgetWidth = menuOptions.widget_width --a width to be used on all widgets - local widgetHeight = menuOptions.widget_height --a height to be used on all widgets - local bAlignAsPairs = menuOptions.align_as_pairs - local nAlignAsPairsLength = menuOptions.align_as_pairs_string_space or 160 - local nAlignAsPairsSpacing = menuOptions.align_as_pairs_spacing or 20 - - --if a scrollbox is passed, the height can be ignored - --the scrollBox child will be used as the parent, and the height of the child will be resized to fit the widgets - local bUseScrollFrame = menuOptions.use_scrollframe - local biggestColumnHeight = 0 --used to resize the scrollbox child when a scrollbox is passed - - if (not bUseScrollFrame) then - if (height and type(height) == "number") then - height = math.abs((height or parent:GetHeight()) - math.abs(yOffset) + 20) - height = height * -1 - else - height = parent:GetHeight() - end - else - local width, height = parent:GetSize() - parent = parent:GetScrollChild() - parent:SetSize(width, height) - end - - local languageAddonId = menuOptions.language_addonId - local languageTable - - if (languageAddonId) then - languageTable = DetailsFramework.Language.GetLanguageTable(languageAddonId) - end - - if (not parent.widget_list) then - detailsFramework:SetAsOptionsPanel(parent) - end - - local currentXOffset = xOffset or 0 - local currentYOffset = yOffset or 0 - local maxColumnWidth = 0 --biggest width of widget + text size on the current column loop pass - local maxWidgetWidth = 0 --biggest widget width on the current column loop pass - local maxWidth = parent:GetWidth() --total width the buildmenu can use - not in use - - for index, widgetTable in ipairs(menuOptions) do - if (not widgetTable.hidden) then - local widgetCreated - if (latestInlineWidget) then - if (not widgetTable.inline) then - latestInlineWidget = nil - currentYOffset = currentYOffset - 28 - end - end +---classes used by the menu builder on the menuOptions table on both functions BuildMenu and BuildMenuVolatile +---the menuOptions consists of a table with several tables inside in array, each table is a widget to be created +---class df_menu_label is used when the sub table of menuOptions has a key named "type" with the value "label" or "text" +function detailsFramework:BuildMenu(parent, menuOptions, xOffset, yOffset, height, useColon, textTemplate, dropdownTemplate, switchTemplate, switchIsCheckbox, sliderTemplate, buttonTemplate, valueChangeHook) + --how many widgets has been created on this line loop pass + local amountLineWidgetAdded = 0 + local biggestColumnHeight = 0 --used to resize the scrollbox child when a scrollbox is passed + local latestInlineWidget + local currentXOffset = xOffset or 0 + local currentYOffset = yOffset or 0 + local maxColumnWidth = 0 --biggest width of widget + text size on the current column loop pass + local maxWidgetWidth = 0 --biggest widget width on the current column loop pass - local extraPaddingY = 0 + --parse settings and the options table + parseOptionsTypes(menuOptions) + local bUseBoxFirstOnAllWidgets, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, nAlignAsPairsSpacing, bUseScrollFrame, languageAddonId, bAttachSliderButtonsToLeft = parseOptionsTable(menuOptions) + parent, height = parseParent(bUseScrollFrame, parent, height, yOffset) + local languageTable = parseLanguageTable(languageAddonId) - if (widgetTable.type == "blank") then - --do nothing + if (not parent.widget_list) then + detailsFramework:SetAsOptionsPanel(parent) + end - elseif (widgetTable.type == "label" or widgetTable.type == "text") then - ---@cast widgetTable df_menu_label + for index, widgetTable in ipairs(menuOptions) do + if (not widgetTable.hidden) then + local widgetCreated + if (latestInlineWidget) then + if (not widgetTable.inline) then + latestInlineWidget = nil + currentYOffset = currentYOffset - 28 + end + end - local label = detailsFramework:CreateLabel(parent, "", widgetTable.text_template or textTemplate or widgetTable.size, widgetTable.color, widgetTable.font, nil, "$parentWidget" .. index, "overlay") - label._get = widgetTable.get - label.widget_type = "label" - label:SetPoint(currentXOffset, currentYOffset) + local extraPaddingY = 0 - local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable) - if (namePhraseId) then - DetailsFramework.Language.RegisterObject(languageAddonId, label.widget, namePhraseId) - label.languageAddonId = languageAddonId - else - local textToSet = (widgetTable.get and widgetTable.get()) or widgetTable.text or "" - label:SetText(textToSet) - end + if (widgetTable.type == "blank") then + --do nothing - --store the widget created into the overall table and the widget by type - table.insert(parent.widget_list, label) - table.insert(parent.widget_list_by_type.label, label) + elseif (widgetTable.type == "label" or widgetTable.type == "text") then + ---@cast widgetTable df_menu_label - amountLineWidgetCreated = amountLineWidgetCreated + 1 + local label = detailsFramework:CreateLabel(parent, "", widgetTable.text_template or textTemplate or widgetTable.size, widgetTable.color, widgetTable.font, nil, "$parentWidget" .. index, "overlay") + setLabelProperties(parent, label, widgetTable, currentXOffset, currentYOffset) - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = label - end + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable) + if (namePhraseId) then + DetailsFramework.Language.RegisterObject(languageAddonId, label.widget, namePhraseId) + label.languageAddonId = languageAddonId + else + local textToSet = (widgetTable.get and widgetTable.get()) or widgetTable.text or "" + label:SetText(textToSet) + end - elseif (widgetTable.type:find("select")) then - ---@cast widgetTable df_menu_dropdown + --store the widget created into the overall table and the widget by type + table.insert(parent.widget_list, label) + table.insert(parent.widget_list_by_type.label, label) - assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'select'") + amountLineWidgetAdded = amountLineWidgetAdded + 1 - local defaultHeight = 18 + elseif (widgetTable.type:find("select")) then + ---@cast widgetTable df_menu_dropdown + assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'select'") + local defaultHeight = 18 - local dropdown - if (widgetTable.type == "selectfont") then - dropdown = detailsFramework:CreateFontDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate) + local dropdown + do + if (widgetTable.type == "selectfont") then + dropdown = detailsFramework:CreateFontDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate) - elseif (widgetTable.type == "selectcolor") then + elseif (widgetTable.type == "selectcolor") then dropdown = detailsFramework:CreateColorDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate) - elseif (widgetTable.type == "selectanchor") then - dropdown = detailsFramework:CreateAnchorPointDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate) - - elseif (widgetTable.type == "selectoutline") then - dropdown = detailsFramework:CreateOutlineDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate) - else - dropdown = detailsFramework:NewDropDown(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 140, widgetHeight or defaultHeight, widgetTable.values, widgetTable.get(), dropdownTemplate) - end - - local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) - DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, dropdown, "have_tooltip", descPhraseId, widgetTable.desc) - - dropdown._get = widgetTable.get - dropdown.widget_type = "select" - - local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) - local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) - DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) - - dropdown.addonId = languageAddonId - if (languageAddonId) then - detailsFramework.Language.RegisterCallback(languageAddonId, function(addonId, languageId, ...) dropdown:Select(dropdown:GetValue()) end) - C_Timer.After(0.1, function() dropdown:Select(dropdown:GetValue()) end) - end + elseif (widgetTable.type == "selectanchor") then + dropdown = detailsFramework:CreateAnchorPointDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate) - if (bAlignAsPairs) then - PixelUtil.SetPoint(label.widget, "topleft", dropdown:GetParent(), "topleft", currentXOffset, currentYOffset) - PixelUtil.SetPoint(dropdown.widget, "left", label.widget, "left", nAlignAsPairsLength, 0) - createOptionHighlightTexture(dropdown, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) + elseif (widgetTable.type == "selectoutline") then + dropdown = detailsFramework:CreateOutlineDropDown(parent, widgetTable.set, widgetTable.get(), widgetWidth or 140, widgetHeight or defaultHeight, nil, "$parentWidget" .. index, dropdownTemplate) else - dropdown:SetPoint("left", label, "right", 2, 0) - label:SetPoint(currentXOffset, currentYOffset) + dropdown = detailsFramework:NewDropDown(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 140, widgetHeight or defaultHeight, widgetTable.values, widgetTable.get(), dropdownTemplate) end + end - dropdown.hasLabel = label + local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) + DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, dropdown, "have_tooltip", descPhraseId, widgetTable.desc) + local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) + dropdown.hasLabel = label - --global callback - if (valueChangeHook) then - dropdown:SetHook("OnOptionSelected", valueChangeHook) - end + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) + DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) + dropdown.addonId = languageAddonId - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - dropdown:SetHook(hookName, hookFunc) - end - end + if (languageAddonId) then + detailsFramework.Language.RegisterCallback(languageAddonId, function(addonId, languageId, ...) dropdown:Select(dropdown:GetValue()) end) + C_Timer.After(0.1, function() dropdown:Select(dropdown:GetValue()) end) + end - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = dropdown - end + maxColumnWidth, maxWidgetWidth = setDropdownProperties(parent, dropdown, widgetTable, currentXOffset, currentYOffset, textTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth) - local widgetTotalSize = label.widget:GetStringWidth() + 144 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + --store the widget created into the overall table and the widget by type + table.insert(parent.widget_list, dropdown) + table.insert(parent.widget_list_by_type.dropdown, dropdown) - if (dropdown:GetWidth() > maxWidgetWidth) then - maxWidgetWidth = dropdown:GetWidth() - end + widgetCreated = dropdown + amountLineWidgetAdded = amountLineWidgetAdded + 1 - --store the widget created into the overall table and the widget by type - table.insert(parent.widget_list, dropdown) - table.insert(parent.widget_list_by_type.dropdown, dropdown) + elseif (widgetTable.type == "toggle") then + ---@cast widgetTable df_menu_toggle - widgetCreated = dropdown - amountLineWidgetCreated = amountLineWidgetCreated + 1 + local switch = detailsFramework:NewSwitch(parent, nil, "$parentWidget" .. index, nil, 60, 20, nil, nil, widgetTable.get(), nil, nil, nil, nil, switchTemplate) - elseif (widgetTable.type == "toggle") then - ---@cast widgetTable df_menu_toggle + local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) + DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, switch, "have_tooltip", descPhraseId, widgetTable.desc) - local switch = detailsFramework:NewSwitch(parent, nil, "$parentWidget" .. index, nil, 60, 20, nil, nil, widgetTable.get(), nil, nil, nil, nil, switchTemplate) + local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) + switch.hasLabel = label - local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) - DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, switch, "have_tooltip", descPhraseId, widgetTable.desc) + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) + DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) - switch._get = widgetTable.get - switch.widget_type = "toggle" - switch.OnSwitch = widgetTable.set + maxColumnWidth, maxWidgetWidth, extraPaddingY = setToggleProperties(parent, switch, widgetTable, currentXOffset, currentYOffset, switchTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, switchIsCheckbox, bUseBoxFirstOnAllWidgets, menuOptions, index, maxWidgetWidth) - if (switchIsCheckbox) then - switch:SetAsCheckBox() - end + --store the widget created into the overall table and the widget by type + table.insert(parent.widget_list, switch) + table.insert(parent.widget_list_by_type.switch, switch) - if (valueChangeHook) then - switch:SetHook("OnSwitch", valueChangeHook) - end + widgetCreated = switch + amountLineWidgetAdded = amountLineWidgetAdded + 1 - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - switch:SetHook(hookName, hookFunc) - end - end + elseif (widgetTable.type == "range") then + ---@cast widgetTable df_menu_range - if (widgetTable.width) then - PixelUtil.SetWidth(switch.widget, widgetTable.width) - end - if (widgetTable.height) then - PixelUtil.SetHeight(switch.widget, widgetTable.height) - end + assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'range'") + local bIsDecimals = widgetTable.usedecimals + local slider = detailsFramework:NewSlider(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 140, widgetHeight or 18, widgetTable.min, widgetTable.max, widgetTable.step, widgetTable.get(), bIsDecimals, nil, nil, sliderTemplate) - local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) + local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) + DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, slider, "have_tooltip", descPhraseId, widgetTable.desc) - local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) - DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) + local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) + slider.hasLabel = label - if (bAlignAsPairs) then - PixelUtil.SetPoint(label.widget, "topleft", switch:GetParent(), "topleft", currentXOffset, currentYOffset) - PixelUtil.SetPoint(switch.widget, "left", label.widget, "left", nAlignAsPairsLength, 0) - createOptionHighlightTexture(switch, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) - else - if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then - switch:SetPoint(currentXOffset, currentYOffset) - label:SetPoint("left", switch, "right", 2) - - local nextWidgetTable = menuOptions[index+1] - if (nextWidgetTable) then - if (nextWidgetTable.type ~= "blank" and nextWidgetTable.type ~= "breakline" and nextWidgetTable.type ~= "toggle" and nextWidgetTable.type ~= "color") then - extraPaddingY = 4 - end - end - else - label:SetPoint(currentXOffset, currentYOffset) - switch:SetPoint("left", label, "right", 2, 0) - end - end - switch.hasLabel = label + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) + DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = switch - end + maxColumnWidth, maxWidgetWidth = setRangeProperties(parent, slider, widgetTable, currentXOffset, currentYOffset, sliderTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, bIsDecimals, bAttachSliderButtonsToLeft) + --store the widget created into the overall table and the widget by type + table.insert(parent.widget_list, slider) + table.insert(parent.widget_list_by_type.slider, slider) - local widgetTotalSize = label.widget:GetStringWidth() + 32 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + widgetCreated = slider + amountLineWidgetAdded = amountLineWidgetAdded + 1 - if (switch:GetWidth() > maxWidgetWidth) then - maxWidgetWidth = switch:GetWidth() - end + elseif (widgetTable.type == "color") then + ---@cast widgetTable df_menu_color + assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'color'") + local colorpick = detailsFramework:NewColorPickButton(parent, "$parentWidget" .. index, nil, widgetTable.set, nil, buttonTemplate) - --store the widget created into the overall table and the widget by type - table.insert(parent.widget_list, switch) - table.insert(parent.widget_list_by_type.switch, switch) + local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) + DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, colorpick, "have_tooltip", descPhraseId, widgetTable.desc) - widgetCreated = switch - amountLineWidgetCreated = amountLineWidgetCreated + 1 + local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) + colorpick.hasLabel = label - elseif (widgetTable.type == "range") then - ---@cast widgetTable df_menu_range + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) + DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) - assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'range'") - local bIsDecimals = widgetTable.usedecimals - local slider = detailsFramework:NewSlider(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 140, widgetHeight or 18, widgetTable.min, widgetTable.max, widgetTable.step, widgetTable.get(), bIsDecimals, nil, nil, sliderTemplate) + maxColumnWidth, maxWidgetWidth, extraPaddingY = setColorProperties(parent, colorpick, widgetTable, currentXOffset, currentYOffset, buttonTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, bUseBoxFirstOnAllWidgets, extraPaddingY) - local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) - DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, slider, "have_tooltip", descPhraseId, widgetTable.desc) + --store the widget created into the overall table and the widget by type + table.insert(parent.widget_list, colorpick) + table.insert(parent.widget_list_by_type.color, colorpick) - slider._get = widgetTable.get - slider.widget_type = "range" - slider:SetHook("OnValueChange", widgetTable.set) + widgetCreated = colorpick + amountLineWidgetAdded = amountLineWidgetAdded + 1 - if (widgetTable.thumbscale) then - slider:SetThumbSize(slider.thumb:GetWidth() * widgetTable.thumbscale, nil) - else - slider:SetThumbSize(slider.thumb:GetWidth() * 1.3, nil) - end + elseif (widgetTable.type == "execute") then + ---@cast widgetTable df_menu_button + local button = detailsFramework:NewButton(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 120, widgetHeight or 18, widgetTable.func, widgetTable.param1, widgetTable.param2, nil, "", nil, buttonTemplate, textTemplate) + button.widget_type = "execute" - if (valueChangeHook) then - slider:SetHook("OnValueChange", valueChangeHook) - end + local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) + button.hasLabel = label - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - slider:SetHook(hookName, hookFunc) - end - end + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) + DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, button.widget, namePhraseId, widgetTable.name) - local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) - local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) - DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) + local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) + DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, button, "have_tooltip", descPhraseId, widgetTable.desc) - if (bAlignAsPairs) then - PixelUtil.SetPoint(label.widget, "topleft", slider:GetParent(), "topleft", currentXOffset, currentYOffset) - PixelUtil.SetPoint(slider.widget, "left", label.widget, "left", nAlignAsPairsLength, 0) - createOptionHighlightTexture(slider, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) - else - slider:SetPoint("left", label, "right", 2) - label:SetPoint(currentXOffset, currentYOffset) - end - slider.hasLabel = label + maxColumnWidth, maxWidgetWidth, latestInlineWidget = setExecuteProperties(parent, button, widgetTable, currentXOffset, currentYOffset, buttonTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, textTemplate, latestInlineWidget) - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = slider - end + --store the widget created into the overall table and the widget by type + table.insert(parent.widget_list, button) + table.insert(parent.widget_list_by_type.button, button) - local widgetTotalSize = label.widget:GetStringWidth() + 146 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end + widgetCreated = button + amountLineWidgetAdded = amountLineWidgetAdded + 1 - if (slider:GetWidth() > maxWidgetWidth) then - maxWidgetWidth = slider:GetWidth() - end + elseif (widgetTable.type == "textentry") then + ---@cast widgetTable df_menu_textentry + local textentry = detailsFramework:CreateTextEntry(parent, widgetTable.func or widgetTable.set, widgetWidth or 120, widgetHeight or 18, nil, "$parentWidget" .. index, nil, buttonTemplate) + local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) + textentry.hasLabel = label + textentry.align = widgetTable.align or "left" - --store the widget created into the overall table and the widget by type - table.insert(parent.widget_list, slider) - table.insert(parent.widget_list_by_type.slider, slider) + local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) + DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, textentry, "have_tooltip", descPhraseId, widgetTable.desc) - widgetCreated = slider - amountLineWidgetCreated = amountLineWidgetCreated + 1 + local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) + DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) - elseif (widgetTable.type == "color") then - ---@cast widgetTable df_menu_color - assert(widgetTable.get, "DetailsFramework:BuildMenu(): .get not found in the widget table for 'color'") - local colorpick = detailsFramework:NewColorPickButton(parent, "$parentWidget" .. index, nil, widgetTable.set, nil, buttonTemplate) + maxColumnWidth, maxWidgetWidth = setTextEntryProperties(parent, textentry, widgetTable, currentXOffset, currentYOffset, buttonTemplate, widgetWidth, widgetHeight, bAlignAsPairs, nAlignAsPairsLength, valueChangeHook, maxColumnWidth, maxWidgetWidth, textTemplate) - local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) - DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, colorpick, "have_tooltip", descPhraseId, widgetTable.desc) + --store the widget created into the overall table and the widget by type + table.insert(parent.widget_list, textentry) + table.insert(parent.widget_list_by_type.textentry, textentry) - colorpick._get = widgetTable.get - colorpick.widget_type = "color" - colorpick:SetSize(18, 18) + widgetCreated = textentry + amountLineWidgetAdded = amountLineWidgetAdded + 1 + end - local r, g, b, a = detailsFramework:ParseColors(widgetTable.get()) - colorpick:SetColor(r, g, b, a) + if (widgetTable.nocombat) then + table.insert(widgetsToDisableOnCombat, widgetCreated) + end - if (valueChangeHook) then - colorpick:SetHook("OnColorChanged", valueChangeHook) - end + if (not widgetTable.inline) then + if (widgetTable.spacement) then + currentYOffset = currentYOffset - 30 + else + currentYOffset = currentYOffset - 20 + end + end - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - colorpick:SetHook(hookName, hookFunc) - end - end + if (extraPaddingY > 0) then + currentYOffset = currentYOffset - extraPaddingY + end - local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) - local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) - DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) + if (bUseScrollFrame) then + if (widgetTable.type == "breakline") then + biggestColumnHeight = math.min(currentYOffset, biggestColumnHeight) + currentYOffset = yOffset if (bAlignAsPairs) then - label:SetPoint(currentXOffset, currentYOffset) - colorpick:SetPoint("left", label, "left", nAlignAsPairsLength, 0) - createOptionHighlightTexture(colorpick, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) - else - if (widgetTable.boxfirst or bUseBoxFirstOnAllWidgets) then - label:SetPoint("left", colorpick, "right", 2) - colorpick:SetPoint(currentXOffset, currentYOffset) - extraPaddingY = 1 - else - colorpick:SetPoint("left", label, "right", 2) - label:SetPoint(currentXOffset, currentYOffset) - end - end - - colorpick.hasLabel = label - - if (widgetTable.id) then - parent.widgetids[widgetTable.id] = colorpick - end - - local widgetTotalSize = label.widget:GetStringWidth() + 32 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end - - if (colorpick:GetWidth() > maxWidgetWidth) then - maxWidgetWidth = colorpick:GetWidth() - end - - --store the widget created into the overall table and the widget by type - table.insert(parent.widget_list, colorpick) - table.insert(parent.widget_list_by_type.color, colorpick) - - widgetCreated = colorpick - amountLineWidgetCreated = amountLineWidgetCreated + 1 - - elseif (widgetTable.type == "execute") then - ---@cast widgetTable df_menu_button - - local button = detailsFramework:NewButton(parent, nil, "$parentWidget" .. index, nil, widgetWidth or 120, widgetHeight or 18, widgetTable.func, widgetTable.param1, widgetTable.param2, nil, "", nil, buttonTemplate, textTemplate) - - local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) - DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, button.widget, namePhraseId, widgetTable.name) - - if (not buttonTemplate) then - button:InstallCustomTexture() - end - - if (widgetTable.inline) then - if (latestInlineWidget) then - button:SetPoint("left", latestInlineWidget, "right", 2, 0) - latestInlineWidget = button - else - button:SetPoint(currentXOffset, currentYOffset) - latestInlineWidget = button - end + currentXOffset = currentXOffset + nAlignAsPairsLength + (widgetWidth or maxWidgetWidth) + nAlignAsPairsSpacing else - button:SetPoint(currentXOffset, currentYOffset) - end - - local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) - DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, button, "have_tooltip", descPhraseId, widgetTable.desc) - - button.widget_type = "execute" - - --button icon - if (widgetTable.icontexture) then - button:SetIcon(widgetTable.icontexture, nil, nil, nil, widgetTable.icontexcoords, nil, nil, 2) - end - - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - button:SetHook(hookName, hookFunc) - end - end - - if (widgetTable.id) then - parent.widgetids [widgetTable.id] = button - end - - if (widgetTable.width and not widgetWidth) then - button:SetWidth(widgetTable.width) - end - if (widgetTable.height and not widgetHeight) then - button:SetHeight(widgetTable.height) - end - - local widgetTotalSize = button:GetWidth() + 4 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end - - if (button:GetWidth() > maxWidgetWidth) then - maxWidgetWidth = button:GetWidth() + currentXOffset = currentXOffset + maxColumnWidth + 20 end - --store the widget created into the overall table and the widget by type - table.insert(parent.widget_list, button) - table.insert(parent.widget_list_by_type.button, button) - - widgetCreated = button - amountLineWidgetCreated = amountLineWidgetCreated + 1 - - elseif (widgetTable.type == "textentry") then - ---@cast widgetTable df_menu_textentry - - local textentry = detailsFramework:CreateTextEntry(parent, widgetTable.func or widgetTable.set, widgetWidth or 120, widgetHeight or 18, nil, "$parentWidget" .. index, nil, buttonTemplate) - textentry.align = widgetTable.align or "left" - - local descPhraseId = getDescripttionPhraseID(widgetTable, languageAddonId, languageTable) - DetailsFramework.Language.RegisterTableKeyWithDefault(languageAddonId, textentry, "have_tooltip", descPhraseId, widgetTable.desc) - - textentry.text = widgetTable.get() - textentry._get = widgetTable.get - textentry.widget_type = "textentry" - textentry:SetHook("OnEnterPressed", widgetTable.func or widgetTable.set) - textentry:SetHook("OnEditFocusLost", widgetTable.func or widgetTable.set) - - local label = detailsFramework:NewLabel(parent, nil, "$parentLabel" .. index, nil, "", "GameFontNormal", widgetTable.text_template or textTemplate or 12) - - local namePhraseId = getNamePhraseID(widgetTable, languageAddonId, languageTable, true) - DetailsFramework.Language.RegisterObjectWithDefault(languageAddonId, label.widget, namePhraseId, formatOptionNameWithColon(widgetTable.name, useColon)) + amountLineWidgetAdded = 0 + maxColumnWidth = 0 + maxWidgetWidth = 0 + end + else + if (widgetTable.type == "breakline" or currentYOffset < height) then + currentYOffset = yOffset + currentXOffset = currentXOffset + maxColumnWidth + 20 + amountLineWidgetAdded = 0 + maxColumnWidth = 0 + end + end + end --no widget.hidden + end --end loop - if (bAlignAsPairs) then - label:SetPoint(currentXOffset, currentYOffset) - textentry:SetPoint("left", label, "left", nAlignAsPairsLength, 0) - createOptionHighlightTexture(textentry, label, (widgetWidth or 140) + nAlignAsPairsLength + 5) - else - textentry:SetPoint("left", label, "right", 2) - label:SetPoint(currentXOffset, currentYOffset) - end + if (bUseScrollFrame) then + parent:SetHeight(biggestColumnHeight * -1) + end - textentry.hasLabel = label + detailsFramework.RefreshUnsafeOptionsWidgets() +end - --hook list - if (widgetTable.hooks) then - for hookName, hookFunc in pairs(widgetTable.hooks) do - textentry:SetHook(hookName, hookFunc) - end - end - if (widgetTable.id) then - parent.widgetids [widgetTable.id] = textentry - end +local lockNotSafeWidgetsForCombat = function() + for _, widget in ipairs(widgetsToDisableOnCombat) do + widget:Disable() + end +end - local widgetTotalSize = label.widget:GetStringWidth() + 64 - if (widgetTotalSize > maxColumnWidth) then - maxColumnWidth = widgetTotalSize - end +local unlockNotSafeWidgetsForCombat = function() + for _, widget in ipairs(widgetsToDisableOnCombat) do + widget:Enable() + end +end - if (textentry:GetWidth() > maxWidgetWidth) then - maxWidgetWidth = textentry:GetWidth() - end +function detailsFramework.RefreshUnsafeOptionsWidgets() + if (detailsFramework.PlayerHasCombatFlag) then + lockNotSafeWidgetsForCombat() + else + unlockNotSafeWidgetsForCombat() + end +end - --store the widget created into the overall table and the widget by type - table.insert(parent.widget_list, textentry) - table.insert(parent.widget_list_by_type.textentry, textentry) +detailsFramework.PlayerHasCombatFlag = false +local ProtectCombatFrame = CreateFrame("frame") +ProtectCombatFrame:RegisterEvent("PLAYER_REGEN_ENABLED") +ProtectCombatFrame:RegisterEvent("PLAYER_REGEN_DISABLED") +ProtectCombatFrame:RegisterEvent("PLAYER_ENTERING_WORLD") +ProtectCombatFrame:SetScript("OnEvent", function(self, event) + if (event == "PLAYER_ENTERING_WORLD") then + if (InCombatLockdown()) then + detailsFramework.PlayerHasCombatFlag = true + else + detailsFramework.PlayerHasCombatFlag = false + end + detailsFramework.RefreshUnsafeOptionsWidgets() - widgetCreated = textentry - amountLineWidgetCreated = amountLineWidgetCreated + 1 - end + elseif (event == "PLAYER_REGEN_ENABLED") then + detailsFramework.PlayerHasCombatFlag = false + detailsFramework.RefreshUnsafeOptionsWidgets() - if (widgetTable.nocombat) then - table.insert(widgetsToDisableOnCombat, widgetCreated) - end + elseif (event == "PLAYER_REGEN_DISABLED") then + detailsFramework.PlayerHasCombatFlag = true + detailsFramework.RefreshUnsafeOptionsWidgets() + end +end) - if (not widgetTable.inline) then - if (widgetTable.spacement) then - currentYOffset = currentYOffset - 30 - else - currentYOffset = currentYOffset - 20 - end - end +function detailsFramework:CreateInCombatTexture(frame) + if (detailsFramework.debug and not frame) then + error("Details! Framework: CreateInCombatTexture invalid frame on parameter 1.") + end - if (extraPaddingY > 0) then - currentYOffset = currentYOffset - extraPaddingY - end + local inCombatBackgroundTexture = detailsFramework:CreateImage(frame) + inCombatBackgroundTexture:SetColorTexture(.6, 0, 0, .1) + inCombatBackgroundTexture:Hide() - if (bUseScrollFrame) then - if (widgetTable.type == "breakline") then - biggestColumnHeight = math.min(currentYOffset, biggestColumnHeight) - currentYOffset = yOffset + local inCombatLabel = detailsFramework:CreateLabel(frame, "you are in combat", 24, "silver") + inCombatLabel:SetPoint("right", inCombatBackgroundTexture, "right", -10, 0) + inCombatLabel:Hide() - if (bAlignAsPairs) then - currentXOffset = currentXOffset + nAlignAsPairsLength + (widgetWidth or maxWidgetWidth) + nAlignAsPairsSpacing - else - currentXOffset = currentXOffset + maxColumnWidth + 20 - end + frame:RegisterEvent("PLAYER_REGEN_DISABLED") + frame:RegisterEvent("PLAYER_REGEN_ENABLED") - amountLineWidgetCreated = 0 - maxColumnWidth = 0 - maxWidgetWidth = 0 - end - else - if (widgetTable.type == "breakline" or currentYOffset < height) then - currentYOffset = yOffset - currentXOffset = currentXOffset + maxColumnWidth + 20 - amountLineWidgetCreated = 0 - maxColumnWidth = 0 - end - end - end - end + frame:SetScript("OnEvent", function(self, event) + if (event == "PLAYER_REGEN_DISABLED") then + inCombatBackgroundTexture:Show() + inCombatLabel:Show() - if (bUseScrollFrame) then - parent:SetHeight(biggestColumnHeight * -1) + elseif (event == "PLAYER_REGEN_ENABLED") then + inCombatBackgroundTexture:Hide() + inCombatLabel:Hide() end + end) - detailsFramework.RefreshUnsafeOptionsWidgets() - end - - - local lockNotSafeWidgetsForCombat = function() - for _, widget in ipairs(widgetsToDisableOnCombat) do - widget:Disable() - end - end - - local unlockNotSafeWidgetsForCombat = function() - for _, widget in ipairs(widgetsToDisableOnCombat) do - widget:Enable() - end - end - - function detailsFramework.RefreshUnsafeOptionsWidgets() - if (detailsFramework.PlayerHasCombatFlag) then - lockNotSafeWidgetsForCombat() - else - unlockNotSafeWidgetsForCombat() - end - end - - detailsFramework.PlayerHasCombatFlag = false - local ProtectCombatFrame = CreateFrame("frame") - ProtectCombatFrame:RegisterEvent("PLAYER_REGEN_ENABLED") - ProtectCombatFrame:RegisterEvent("PLAYER_REGEN_DISABLED") - ProtectCombatFrame:RegisterEvent("PLAYER_ENTERING_WORLD") - ProtectCombatFrame:SetScript("OnEvent", function(self, event) - if (event == "PLAYER_ENTERING_WORLD") then - if (InCombatLockdown()) then - detailsFramework.PlayerHasCombatFlag = true - else - detailsFramework.PlayerHasCombatFlag = false - end - detailsFramework.RefreshUnsafeOptionsWidgets() - - elseif (event == "PLAYER_REGEN_ENABLED") then - detailsFramework.PlayerHasCombatFlag = false - detailsFramework.RefreshUnsafeOptionsWidgets() - - elseif (event == "PLAYER_REGEN_DISABLED") then - detailsFramework.PlayerHasCombatFlag = true - detailsFramework.RefreshUnsafeOptionsWidgets() - end - end) - - function detailsFramework:CreateInCombatTexture(frame) - if (detailsFramework.debug and not frame) then - error("Details! Framework: CreateInCombatTexture invalid frame on parameter 1.") - end - - local inCombatBackgroundTexture = detailsFramework:CreateImage(frame) - inCombatBackgroundTexture:SetColorTexture(.6, 0, 0, .1) - inCombatBackgroundTexture:Hide() - - local inCombatLabel = detailsFramework:CreateLabel(frame, "you are in combat", 24, "silver") - inCombatLabel:SetPoint("right", inCombatBackgroundTexture, "right", -10, 0) - inCombatLabel:Hide() - - frame:RegisterEvent("PLAYER_REGEN_DISABLED") - frame:RegisterEvent("PLAYER_REGEN_ENABLED") - - frame:SetScript("OnEvent", function(self, event) - if (event == "PLAYER_REGEN_DISABLED") then - inCombatBackgroundTexture:Show() - inCombatLabel:Show() - - elseif (event == "PLAYER_REGEN_ENABLED") then - inCombatBackgroundTexture:Hide() - inCombatLabel:Hide() - end - end) - - return inCombatBackgroundTexture - end \ No newline at end of file + return inCombatBackgroundTexture +end \ No newline at end of file diff --git a/libs/DF/definitions.lua b/libs/DF/definitions.lua index 40ef74df..ad17ec79 100644 --- a/libs/DF/definitions.lua +++ b/libs/DF/definitions.lua @@ -9,7 +9,7 @@ ---@field deploy fun(tblReceiving:table, tblGiving:table) : table copy keys/values that does exist on tblGiving but not in tblReceiving ---@field copytocompress fun(tblReceiving:table, tblGiving:table) : table copy the values from table2 to table1 overwriting existing values, ignores __index, functions and tables with a 'GetObjectType' key ---@field removeduplicate fun(tbl1:table, tbl2:table) remove the keys from table1 which also exists in table2 with the same value ----@field getfrompath fun(tbl:table, path:string) : any get a value from a table using a path, e.g. getfrompath(tbl, "a.b.c") is the same as tbl.a.b.c +---@field getfrompath fun(tbl:table, path:string, subOffset:number?) : any get a value from a table using a path, e.g. getfrompath(tbl, "a.b.c") is the same as tbl.a.b.c; if subOffset is passed, return the subOffset'th value of the path ---@field setfrompath fun(tbl:table, path:string, value:any) : boolean set the value of a table using a path, e.g. setfrompath(tbl, "a.b.c", 10) is the same as tbl.a.b.c = 10 ---@field dump fun(tbl:table) : string dump a table to a string @@ -57,7 +57,7 @@ ---@field EditorMixin df_editormixin ---@field ClassCache {ID:number, Name:string, FileString:string, Texture:string, TexCoord:number[]}[] only available after calling GetClassList() ---@field Math df_math ----@field FontOutlineFlags {key1:outline, key2:string}[] +---@field FontOutlineFlags table ---@field table df_table_functions ---@field AnchorPoints string[] ---@field ClassFileNameToIndex table engClass -> classIndex @@ -103,7 +103,7 @@ ---@field CommaValue fun(self:table, value:number) : string convert a number to a string with commas, e.g. 1000000 -> 1,000,000 ---@field SplitTextInLines fun(self:table, text:string) : string[] split a text into lines ---@field UnitGroupRolesAssigned fun(unitId: unit, bUseSupport:boolean, specId: specializationid) : string there's no self here ----@field SetAnchor fun(self:table, widget:uiobject, anchorTable:df_anchor, anchorTo:uiobject) only adjust the anchors of a widget, does not save values +---@field SetAnchor fun(self:table, widget:uiobject, anchorTable:df_anchor, anchorTo:uiobject?) only adjust the anchors of a widget, does not save values ---@field AddTextureToText fun(text:string, textureInfo:table, bAddSpace:boolean?, bAddAfterText:boolean) : string textureInfo is a table with .texture .width .height .coords{left, right, top, bottom} ---@field CreateTextureInfo fun(texture:atlasname|texturepath|textureid, width:number?, height:number?, left:number?, right:number?, top:number?, bottom:number?, imageWidthnumber?, imageHeightnumber?) : table ---@field ApplyStandardBackdrop fun(self:table, frame:frame, bUseSolidColor:boolean?, alphaScale:number?) diff --git a/libs/DF/dropdown.lua b/libs/DF/dropdown.lua index 69928474..cff92a67 100644 --- a/libs/DF/dropdown.lua +++ b/libs/DF/dropdown.lua @@ -986,16 +986,13 @@ function DetailsFrameworkDropDownOnHide(self) object:Close() end +local iconSizeTable = {16, 16} function DF:BuildDropDownFontList(onClick, icon, iconTexcoord, iconSize) local fontTable = {} - if (type(iconSize) ~= "table") then - iconSize = {iconSize or 16, iconSize or 16} - end - local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0") for name, fontPath in pairs(SharedMedia:HashTable("font")) do - fontTable[#fontTable+1] = {value = name, label = name, onclick = onClick, icon = icon, iconsize = iconSize, texcoord = iconTexcoord, font = fontPath, descfont = "abcdefg ABCDEFG"} + fontTable[#fontTable+1] = {value = name, label = name, onclick = onClick, icon = icon, iconsize = iconSizeTable, texcoord = iconTexcoord, font = fontPath, descfont = "abcdefg ABCDEFG"} end table.sort(fontTable, function(t1, t2) return t1.label < t2.label end) @@ -1141,11 +1138,12 @@ function DF:CreateOutlineListGenerator(callback) local newGenerator = function() local dropdownOptions = {} - for i, outlineInfo in ipairs(DF.FontOutlineFlags) do - local outlineName, outlineLoc = unpack(outlineInfo) + for index, outlineInfo in pairs(DF.FontOutlineFlags) do + local outlineValue = outlineInfo[1] + local outlineName = outlineInfo[2] table.insert(dropdownOptions, { - label = outlineLoc, - value = outlineName, + label = outlineName, + value = outlineValue, onclick = callback }) end diff --git a/libs/DF/editor.lua b/libs/DF/editor.lua index d1e2f072..e8bf7265 100644 --- a/libs/DF/editor.lua +++ b/libs/DF/editor.lua @@ -22,10 +22,10 @@ local _ --the mapTable is a table with the attribute name as a key, and the value is the profile key. For example, {["size"] = "text_size"} means profileTable["text_size"] = 10. ---@class df_editor_attribute ----@field name string ----@field label string +---@field name string? +---@field label string? ---@field widget string ----@field default any +---@field default any? ---@field minvalue number? ---@field maxvalue number? ---@field step number? @@ -72,6 +72,7 @@ local attributes = { widget = "range", setter = function(widget, value) widget:SetAlpha(value) end }, + {widget = "blank"}, { name = "shadow", label = "Draw Shadow", @@ -106,6 +107,7 @@ local attributes = { widget = "outlinedropdown", setter = function(widget, value) widget:SetFont(widget:GetFont(), select(2, widget:GetFont()), value) end }, + {widget = "blank"}, { name = "anchor", label = "Anchor", @@ -137,10 +139,20 @@ local attributes = { maxvalue = math.pi*2, setter = function(widget, value) widget:SetRotation(value) end }, + { + name = "scale", + label = "Scale", + widget = "range", + usedecimals = true, + minvalue = 0.65, + maxvalue = 2.5, + setter = function(widget, value) widget:SetScale(value) end + }, } } ---@class df_editormixin : table +---@field GetAllRegisteredObjects fun(self:df_editor):df_editor_objectinfo[] ---@field GetEditingObject fun(self:df_editor):uiobject ---@field GetEditingOptions fun(self:df_editor):df_editobjectoptions ---@field GetExtraOptions fun(self:df_editor):table @@ -148,6 +160,7 @@ local attributes = { ---@field GetOnEditCallback fun(self:df_editor):function ---@field GetOptionsFrame fun(self:df_editor):frame ---@field GetCanvasScrollBox fun(self:df_editor):df_canvasscrollbox +---@field GetObjectSelector fun(self:df_editor):df_scrollbox ---@field EditObject fun(self:df_editor, object:uiobject, profileTable:table, profileKeyMap:table, extraOptions:table?, callback:function?, options:df_editobjectoptions?) ---@field PrepareObjectForEditing fun(self:df_editor) ---@field CreateMoverGuideLines fun(self:df_editor) @@ -226,18 +239,27 @@ detailsFramework.EditorMixin = { return self.canvasScrollBox end, - ---@param self df_editor - ---@param object uiobject - ---@param profileTable table - ---@param profileKeyMap table - ---@param extraOptions table? a way to add more options other than the default attributes for the object. - ---@param callback function? calls when an attribute is changed with the payload: editingObject, optionName, newValue, profileTable, profileKey - ---@param options df_editobjectoptions? - EditObject = function(self, object, profileTable, profileKeyMap, extraOptions, callback, options) - assert(type(object) == "table", "EditObject(object) expects an UIObject on first parameter.") - assert(type(profileTable) == "table", "EditObject(object) expects a table on second parameter.") - assert(object.GetObjectType, "EditObject(object) expects an UIObject on first parameter.") + GetObjectSelector = function(self) + return self.objectSelector + end, + + EditObjectById = function(self, id) + ---@type df_editor_objectinfo + local objectRegistered = self:GetObjectById(id) + assert(type(objectRegistered) == "table", "EditObjectById() object not found.") + self:EditObject(objectRegistered) + end, + EditObjectByIndex = function(self, index) + ---@type df_editor_objectinfo + local objectRegistered = self:GetObjectByIndex(index) + assert(type(objectRegistered) == "table", "EditObjectById() object not found.") + self:EditObject(objectRegistered) + end, + + ---@param self df_editor + ---@param registeredObject df_editor_objectinfo + EditObject = function(self, registeredObject) --clear previous values self.editingObject = nil self.editingProfileMap = nil @@ -246,21 +268,22 @@ detailsFramework.EditorMixin = { self.editingExtraOptions = nil self.onEditCallback = nil - --deploy the options table - options = type(options) == "table" and options or {} - detailsFramework.table.deploy(options, editObjectDefaultOptions) + local object = registeredObject.object + local profileTable = registeredObject.profiletable + local profileKeyMap = registeredObject.profilekeymap + local extraOptions = registeredObject.extraoptions + local callback = registeredObject.callback + local options = registeredObject.options --as there's no other place which this members are set, there is no need to create setter functions self.editingObject = object self.editingProfileMap = profileKeyMap self.editingProfileTable = profileTable self.editingOptions = options - self.editingExtraOptions = extraOptions or {} + self.editingExtraOptions = extraOptions if (type(callback) == "function") then self.onEditCallback = callback - elseif (callback) then - error("EditObject(object) callback must be a function or nil.") end self:PrepareObjectForEditing() @@ -340,13 +363,15 @@ detailsFramework.EditorMixin = { end --if there's extra options, add the attributeList to a new table and right after the extra options - if (extraOptions) then + if (extraOptions and #extraOptions > 0) then local attributeListWithExtraOptions = {} for i = 1, #attributeList do attributeListWithExtraOptions[#attributeListWithExtraOptions+1] = attributeList[i] end + attributeListWithExtraOptions[#attributeListWithExtraOptions+1] = {widget = "blank", default = true} + for i = 1, #extraOptions do attributeListWithExtraOptions[#attributeListWithExtraOptions+1] = extraOptions[i] end @@ -356,94 +381,107 @@ detailsFramework.EditorMixin = { local anchorSettings - --table to use on DF:BuildMenu() + --table to use on DF:BuildMenuVolatile() local menuOptions = {} for i = 1, #attributeList do local option = attributeList[i] - --get the key to be used on profile table - local profileKey = profileMap[option.name] - local value - - --if the key contains a dot or a bracket, it means it's a table path, example: "text_settings[1].width" - if (profileKey and (profileKey:match("%.") or profileKey:match("%["))) then - value = detailsFramework.table.getfrompath(profileTable, profileKey) + if (option.widget == "blank") then + menuOptions[#menuOptions+1] = {type = "blank"} else - value = profileTable[profileKey] - end + --get the key to be used on profile table + local profileKey = profileMap[option.name] + local value - --if no value is found, attempt to get a default - value = value or option.default + --if the key contains a dot or a bracket, it means it's a table path, example: "text_settings[1].width" + if (profileKey and (profileKey:match("%.") or profileKey:match("%["))) then + value = detailsFramework.table.getfrompath(profileTable, profileKey) + else + value = profileTable[profileKey] + end - local minValue = option.minvalue - local maxValue = option.maxvalue + --if no value is found, attempt to get a default + if (type(value) == "nil") then + value = option.default + end - if (option.name == "anchoroffsetx") then - minValue = -object:GetParent():GetWidth()/2 - maxValue = object:GetParent():GetWidth()/2 - elseif (option.name == "anchoroffsety") then - minValue = -object:GetParent():GetHeight()/2 - maxValue = object:GetParent():GetHeight()/2 - end + local bHasValue = type(value) ~= "nil" - if (value) then - local parentTable = getParentTable(profileTable, profileKey) + local minValue = option.minvalue + local maxValue = option.maxvalue - if (option.name == "anchor" or option.name == "anchoroffsetx" or option.name == "anchoroffsety") then - anchorSettings = parentTable + if (option.name == "anchoroffsetx") then + minValue = -object:GetParent():GetWidth()/2 + maxValue = object:GetParent():GetWidth()/2 + elseif (option.name == "anchoroffsety") then + minValue = -object:GetParent():GetHeight()/2 + maxValue = object:GetParent():GetHeight()/2 end - menuOptions[#menuOptions+1] = { - type = option.widget, - name = option.label, - get = function() return value end, - set = function(widget, fixedValue, newValue, ...) - --color is a table with 4 indexes for each color plus alpha - if (option.name:find("color")) then - --calor callback sends the red color in the fixedParameter slot - local r, g, b, alpha = fixedValue, newValue, ... - --need to use the same table from the profile table - parentTable[1] = r - parentTable[2] = g - parentTable[3] = b - parentTable[4] = alpha - - newValue = parentTable - else - detailsFramework.table.setfrompath(profileTable, profileKey, newValue) - end - - if (self:GetOnEditCallback()) then - self:GetOnEditCallback()(object, option.name, newValue, profileTable, profileKey) - end - - --update the widget visual - --anchoring uses SetAnchor() which require the anchorTable to be passed - if (option.name == "anchor" or option.name == "anchoroffsetx" or option.name == "anchoroffsety") then - anchorSettings = parentTable - - if (option.name == "anchor") then - anchorSettings.x = 0 - anchorSettings.y = 0 + if (bHasValue) then + local parentTable = getParentTable(profileTable, profileKey) + + if (option.name == "anchor" or option.name == "anchoroffsetx" or option.name == "anchoroffsety") then + anchorSettings = parentTable + end + + menuOptions[#menuOptions+1] = { + type = option.widget, + name = option.label, + get = function() return value end, + set = function(widget, fixedValue, newValue, ...) + --color is a table with 4 indexes for each color plus alpha + if (option.widget == "range" or option.widget == "slider") then + if (not option.usedecimals) then + newValue = math.floor(newValue) + end + + elseif (option.widget == "color") then + --calor callback sends the red color in the fixedParameter slot + local r, g, b, alpha = fixedValue, newValue, ... + --need to use the same table from the profile table + parentTable[1] = r + parentTable[2] = g + parentTable[3] = b + parentTable[4] = alpha + + newValue = parentTable + else + detailsFramework.table.setfrompath(profileTable, profileKey, newValue) end - self:StopObjectMovement() + if (self:GetOnEditCallback()) then + self:GetOnEditCallback()(object, option.name, newValue, profileTable, profileKey) + end - option.setter(object, parentTable) + --update the widget visual + --anchoring uses SetAnchor() which require the anchorTable to be passed + if (option.name == "anchor" or option.name == "anchoroffsetx" or option.name == "anchoroffsety") then + anchorSettings = parentTable - if (editingOptions.can_move) then - self:StartObjectMovement(anchorSettings) + if (option.name == "anchor") then + anchorSettings.x = 0 + anchorSettings.y = 0 + end + + self:StopObjectMovement() + + option.setter(object, parentTable) + + if (editingOptions.can_move) then + self:StartObjectMovement(anchorSettings) + end + else + option.setter(object, newValue) end - else - option.setter(object, newValue) - end - end, - min = minValue, - max = maxValue, - step = option.step, - usedecimals = option.usedecimals, - id = option.name, - } + end, + min = minValue, + max = maxValue, + step = option.step, + usedecimals = option.usedecimals, + id = option.name, + } + end end end @@ -451,6 +489,7 @@ detailsFramework.EditorMixin = { menuOptions.align_as_pairs = true menuOptions.align_as_pairs_length = 150 menuOptions.widget_width = 180 + menuOptions.slider_buttons_to_left = true local optionsFrame = self:GetOptionsFrame() local canvasScrollBox = self:GetCanvasScrollBox() @@ -471,7 +510,7 @@ detailsFramework.EditorMixin = { local options_slider_template = detailsFramework:GetTemplate("slider", "OPTIONS_SLIDER_TEMPLATE") local options_button_template = detailsFramework:GetTemplate("button", "OPTIONS_BUTTON_TEMPLATE") - detailsFramework:BuildMenu(optionsFrame, menuOptions, 0, -2, maxHeight, bUseColon, options_text_template, options_dropdown_template, options_switch_template, bSwitchIsCheckbox, options_slider_template, options_button_template) + detailsFramework:BuildMenuVolatile(optionsFrame, menuOptions, 0, -2, maxHeight, bUseColon, options_text_template, options_dropdown_template, options_switch_template, bSwitchIsCheckbox, options_slider_template, options_button_template) if (editingOptions.can_move) then self:StartObjectMovement(anchorSettings) @@ -482,84 +521,94 @@ detailsFramework.EditorMixin = { ---@param anchorSettings df_anchor StartObjectMovement = function(self, anchorSettings) local object = self:GetEditingObject() - local moverFrame = self:GetMoverFrame() + local moverFrame = self:GetMoverFrame() moverFrame:EnableMouse(true) moverFrame:SetMovable(true) moverFrame:ClearAllPoints() - moverFrame:SetPoint("topleft", object, "topleft", -4, 4) - moverFrame:SetPoint("bottomright", object, "bottomright", 4, -4) moverFrame:Show() - self:UpdateGuideLinesAnchors() - - --update the mover frame size to match the object size - if (object:GetObjectType() == "FontString") then - ---@cast object fontstring - local width = object:GetStringWidth() - local height = object:GetStringHeight() - moverFrame:SetSize(width, height) - else - local width, height = object:GetSize() - moverFrame:SetSize(width, height) + --update guidelines + if (self:GetEditingOptions().use_guide_lines) then + --self:UpdateGuideLinesAnchors() + --show all four guidelines + for side, texture in pairs(self.moverGuideLines) do + texture:Show() + end end + local optionsFrame = self:GetOptionsFrame() + + local objectWidth, objectHeight = object:GetSize() + moverFrame:SetSize(objectWidth, objectHeight) + detailsFramework:SetAnchor(moverFrame, anchorSettings, object:GetParent()) + local currentPosX, currentPosY + moverFrame:SetScript("OnMouseDown", function() - moverFrame:StartMoving() + object:ClearAllPoints() + object:SetPoint("topleft", moverFrame, "topleft", 0, 0) + + currentPosX, currentPosY = moverFrame:GetCenter() moverFrame.bIsMoving = true + moverFrame:StartMoving() end) moverFrame:SetScript("OnMouseUp", function() moverFrame:StopMovingOrSizing() moverFrame.bIsMoving = false - end) - --update guidelines - if (self:GetEditingOptions().use_guide_lines) then - --show all four guidelines - for side, texture in pairs(self.moverGuideLines) do - texture:Show() - end - end + local originX = anchorSettings.x + local originY = anchorSettings.y - local optionsFrame = self:GetOptionsFrame() + local newPosX, newPosY = moverFrame:GetCenter() + + local xOffset = newPosX - currentPosX + local yOffset = newPosY - currentPosY + + anchorSettings.x = originX + xOffset + anchorSettings.y = originY + yOffset - --record the current position of the moverFrame to check later if the frame has moved - --if the moverFrame has moved, need to update the anchor settings x and y values - local currentPosX, currentPosY = moverFrame:GetCenter() + local anchorXSlider = optionsFrame:GetWidgetById("anchoroffsetx") + anchorXSlider:SetValueNoCallback(anchorSettings.x) + + local anchorYSlider = optionsFrame:GetWidgetById("anchoroffsety") + anchorYSlider:SetValueNoCallback(anchorSettings.y) + + object:ClearAllPoints() + detailsFramework:SetAnchor(object, anchorSettings, object:GetParent()) + end) + + --detailsFramework:SetAnchor(moverFrame, anchorSettings) + --detailsFramework:SetAnchor(object, anchorSettings, moverFrame) moverFrame:SetScript("OnUpdate", function() --if the object isn't moving, make the mover follow the object position - if (moverFrame.bIsMoving) then + if (false and moverFrame.bIsMoving) then + --object:ClearAllPoints() + --object:SetPoint("topleft", moverFrame, "topleft", 0, 0) + --if the object is moving, check if the moverFrame has moved local newPosX, newPosY = moverFrame:GetCenter() --did the frame moved? - if (newPosX ~= currentPosX or newPosY ~= currentPosY) then - --if the moverFrame has moved, update the anchor settings + if (newPosX ~= currentPosX) then local xOffset = newPosX - currentPosX - local yOffset = newPosY - currentPosY anchorSettings.x = anchorSettings.x + xOffset - anchorSettings.y = anchorSettings.y + yOffset - - --update the anchor x and y slider's shown value without calling the callback local anchorXSlider = optionsFrame:GetWidgetById("anchoroffsetx") anchorXSlider:SetValueNoCallback(anchorSettings.x) + end + + if (newPosY ~= currentPosY) then + local yOffset = newPosY - currentPosY + anchorSettings.y = anchorSettings.y + yOffset local anchorYSlider = optionsFrame:GetWidgetById("anchoroffsety") anchorYSlider:SetValueNoCallback(anchorSettings.y) - - --update the object anchor - detailsFramework:SetAnchor(object, anchorSettings, object:GetParent()) - - --update the current position - currentPosX, currentPosY = newPosX, newPosY end - else - moverFrame:ClearAllPoints() - moverFrame:SetPoint("topleft", object, "topleft", -4, 4) - moverFrame:SetPoint("bottomright", object, "bottomright", 4, -4) + + currentPosX, currentPosY = newPosX, newPosY end + --[=[ --update the mover frame size to match the object size if (object:GetObjectType() == "FontString") then ---@cast object fontstring @@ -570,6 +619,7 @@ detailsFramework.EditorMixin = { local width, height = object:GetSize() moverFrame:SetSize(width, height) end + --]=] end) end, @@ -587,27 +637,241 @@ detailsFramework.EditorMixin = { moverFrame:Hide() end, + + RegisterObject = function(self, object, localizedLabel, id, profileTable, profileKeyMap, extraOptions, callback, options) + assert(type(object) == "table", "RegisterObjectToEdit() expects an UIObject on #1 parameter.") + assert(object.GetObjectType, "RegisterObjectToEdit() expects an UIObject on #1 parameter.") + assert(type(profileTable) == "table", "RegisterObjectToEdit() expects a table on #4 parameter.") + assert(type(id) ~= "nil" and type(id) ~= "boolean", "RegisterObjectToEdit() expects an ID on parameter #3.") + assert(type(callback) == "function" or callback == nil, "RegisterObjectToEdit() expects a function or nil as the #7 parameter.") + + local registeredObjects = self:GetAllRegisteredObjects() + + --is object already registered? + for i = 1, #registeredObjects do + local objectRegistered = registeredObjects[i] + if (objectRegistered.object == object) then + error("RegisterObjectToEdit() object already registered.") + end + end + + --deploy the options table + options = type(options) == "table" and options or {} + detailsFramework.table.deploy(options, editObjectDefaultOptions) + + localizedLabel = type(localizedLabel) == "string" and localizedLabel or "invalid label" + + --a button to select the widget + local selectButton = CreateFrame("button", "$parentSelectButton" .. id, object:GetParent()) + selectButton:SetAllPoints(object) + + ---@type df_editor_objectinfo + local objectRegistered = { + object = object, + label = localizedLabel, + id = id, + profiletable = profileTable, + profilekeymap = profileKeyMap, + extraoptions = extraOptions or {}, + callback = callback, + options = options, + selectButton = selectButton, + } + + selectButton:SetScript("OnClick", function() + self:EditObject(objectRegistered) + end) + + registeredObjects[#registeredObjects+1] = objectRegistered + self.registeredObjectsByID[id] = objectRegistered + + local objectSelector = self:GetObjectSelector() + objectSelector:RefreshMe() + + --what to do after an object is registered? + return objectRegistered + end, + + UnregisterObject = function(self, object) + local registeredObjects = self:GetAllRegisteredObjects() + + for i = 1, #registeredObjects do + local objectRegistered = registeredObjects[i] + if (objectRegistered.object == object) then + self.registeredObjectsByID[objectRegistered.id] = nil + table.remove(registeredObjects, i) + break + end + end + + local objectSelector = self:GetObjectSelector() + objectSelector:RefreshMe() + + --stop editing the object + end, + + ---@param self df_editor + ---@return df_editor_objectinfo[] + GetAllRegisteredObjects = function(self) + return self.registeredObjects + end, + + ---@param self df_editor + ---@return df_editor_objectinfo? + GetObjectByRef = function(self, object) + local registeredObjects = self:GetAllRegisteredObjects() + for i = 1, #registeredObjects do + local objectRegistered = registeredObjects[i] + if (objectRegistered.object == object) then + return objectRegistered + end + end + end, + + GetObjectByIndex = function(self, index) + local registeredObjects = self:GetAllRegisteredObjects() + return registeredObjects[index] + end, + + GetObjectById = function(self, id) + return self.registeredObjectsByID[id] + end, + + CreateObjectSelectionList = function(self, scroll_width, scroll_height, scroll_lines, scroll_line_height) + local editorFrame = self + + local refreshFunc = function(self, data, offset, totalLines) --~refresh + for i = 1, totalLines do + local index = i + offset + ---@type df_editor_objectinfo + local objectRegistered = data[index] + + if (objectRegistered) then + local line = self:GetLine(i) + line.index = index + if (objectRegistered.object:GetObjectType() == "Texture") then + line.Icon:SetTexture([[Interface\AnimCreate\AnimCreateIcons]]) + line.Icon:SetTexCoord(1/4, 2/4, 1/4, 2/4) + + elseif (objectRegistered.object:GetObjectType() == "Texture") then + line.Icon:SetTexture([[Interface\AnimCreate\AnimCreateIcons]]) + line.Icon:SetTexCoord(2/4, 3/4, 0, 1/4) + end + + line.Label:SetText(objectRegistered.label) + end + end + end + + local createLineFunc = function(self, index) -- ~createline --~line + local line = CreateFrame("button", "$parentLine" .. index, self, "BackdropTemplate") + line:SetPoint("topleft", self, "topleft", 1, -((index-1)*(scroll_line_height+1)) - 1) + line:SetSize(scroll_width - 2, scroll_line_height) + + line:SetBackdrop({bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], tileSize = 64, tile = true}) + if (index % 2 == 0) then + line:SetBackdropColor(.1, .1, .1, .1) + else + line:SetBackdropColor(.1, .1, .1, .4) + end + + detailsFramework:Mixin(line, detailsFramework.HeaderFunctions) + + --line:SetScript("OnEnter", lineOnEnter) + --line:SetScript("OnLeave", lineOnLeave) + + line:SetScript("OnClick", function(self) + local objectRegistered = editorFrame:GetObjectByIndex(self.index) + editorFrame:EditObject(objectRegistered) + end) + + --icon + local objectIcon = line:CreateTexture("$parentIcon", "overlay") + objectIcon:SetSize(scroll_line_height - 2, scroll_line_height - 2) + + --object label + local objectLabel = line:CreateFontString("$parentLabel", "overlay", "GameFontNormal") + + objectIcon:SetPoint("left", line, "left", 2, 0) + objectLabel:SetPoint("left", objectIcon, "right", 2, 0) + + line.Icon = objectIcon + line.Label = objectLabel + + return line + end + + local selectObjectScrollBox = detailsFramework:CreateScrollBox(self:GetParent(), "$parentSelectObjectScrollBox", refreshFunc, editorFrame:GetAllRegisteredObjects(), scroll_width, scroll_height, scroll_lines, scroll_line_height) + detailsFramework:ReskinSlider(selectObjectScrollBox) + + function selectObjectScrollBox:RefreshMe() + selectObjectScrollBox:SetData(editorFrame:GetAllRegisteredObjects()) + selectObjectScrollBox:Refresh() + end + + --create lines + for i = 1, scroll_lines do + selectObjectScrollBox:CreateLine(createLineFunc) + end + + return selectObjectScrollBox + end, + + OnHide = function(self) + self:StopObjectMovement() + end, } +---@class df_editor_defaultoptions : table +---@field width number +---@field height number +---@field options_width number +---@field create_object_list boolean +---@field object_list_width number +---@field object_list_height number +---@field object_list_lines number +---@field object_list_line_height number + +---@class df_editor_defaultoptions local editorDefaultOptions = { width = 400, - height = 600, + height = 548, + options_width = 340, + create_object_list = true, + object_list_width = 200, + object_list_height = 420, + object_list_lines = 20, + object_list_line_height = 20, } ---@class df_editor : frame, df_optionsmixin, df_editormixin ---@field options table +---@field registeredObjects df_editor_objectinfo[] +---@field registeredObjectsByID table ---@field editingObject uiobject ---@field editingProfileTable table ---@field editingProfileMap table ---@field editingOptions df_editobjectoptions ---@field editingExtraOptions table +---@field moverGuideLines table ---@field onEditCallback function ---@field optionsFrame frame ---@field overTheTopFrame frame +---@field objectSelector df_scrollbox ---@field moverFrame frame ----@field moverGuideLines table ---@field canvasScrollBox df_canvasscrollbox +---@class df_editor_objectinfo : table +---@field object uiobject +---@field label string +---@field id any +---@field profiletable table +---@field profilekeymap table +---@field extraoptions table +---@field callback function +---@field options df_editobjectoptions +---@field selectButton button + function detailsFramework:CreateEditor(parent, name, options) name = name or ("DetailsFrameworkEditor" .. math.random(100000, 10000000)) local editorFrame = CreateFrame("frame", name, parent, "BackdropTemplate") @@ -615,16 +879,45 @@ function detailsFramework:CreateEditor(parent, name, options) detailsFramework:Mixin(editorFrame, detailsFramework.EditorMixin) detailsFramework:Mixin(editorFrame, detailsFramework.OptionsFunctions) + editorFrame:SetScript("OnHide", editorFrame.OnHide) + + editorFrame.registeredObjects = {} + editorFrame.registeredObjectsByID = {} + editorFrame:BuildOptionsTable(editorDefaultOptions, options) editorFrame:SetSize(editorFrame.options.width, editorFrame.options.height) - --options frame is the frame that holds the options for the editing object, it is used as the parent frame for BuildMenuVolatile() + --The options frame holds the options for the object being edited. It is used as the parent frame for the BuildMenuVolatile() function. local optionsFrame = CreateFrame("frame", name .. "OptionsFrame", editorFrame, "BackdropTemplate") - optionsFrame:SetSize(editorFrame.options.width, 5000) + optionsFrame:SetSize(editorFrame.options.options_width, 5000) - local canvasFrame = detailsFramework:CreateCanvasScrollBox(editorFrame, optionsFrame, name .. "CanvasScrollBox") - canvasFrame:SetAllPoints() + local canvasScrollBoxOptions = { + width = editorFrame.options.options_width, + height = 400, + reskin_slider = true, + } + local canvasFrame = detailsFramework:CreateCanvasScrollBox(editorFrame, optionsFrame, name .. "CanvasScrollBox", canvasScrollBoxOptions) + + if (editorFrame.options.create_object_list) then + local scrollWidth = editorFrame.options.object_list_width + local scrollHeight = editorFrame.options.object_list_height + local scrollLinesAmount = editorFrame.options.object_list_lines + local scrollLineHeight = editorFrame.options.object_list_line_height + + local objectSelector = editorFrame:CreateObjectSelectionList(scrollWidth, scrollHeight, scrollLinesAmount, scrollLineHeight) + objectSelector:SetPoint("topleft", editorFrame, "topleft", 0, -2) + objectSelector:SetBackdropBorderColor(0, 0, 0, 0) + editorFrame.objectSelector = objectSelector + objectSelector:RefreshMe() + + local nScrollBarWidth = 30 + canvasFrame:SetPoint("topleft", objectSelector, "topright", nScrollBarWidth, 0) + canvasFrame:SetPoint("bottomleft", objectSelector, "bottomright", -nScrollBarWidth, 0) + else + canvasFrame:SetPoint("topleft", editorFrame, "topleft", 2, -2) + canvasFrame:SetPoint("bottomleft", editorFrame, "bottomleft", 2, 0) + end --over the top frame is a frame that is always on top of everything else local OTTFrame = CreateFrame("frame", "$parentOTTFrame", UIParent) @@ -634,10 +927,9 @@ function detailsFramework:CreateEditor(parent, name, options) --frame that is used to move the object local moverFrame = CreateFrame("frame", "$parentMoverFrame", OTTFrame, "BackdropTemplate") moverFrame:SetClampedToScreen(true) - moverFrame:SetBackdrop({ - edgeFile = "Interface\\Buttons\\WHITE8x8", - edgeSize = 1, - }) + detailsFramework:ApplyStandardBackdrop(moverFrame) + moverFrame:SetBackdropColor(.10, .10, .10, 0) + moverFrame.__background:SetAlpha(0.1) editorFrame.moverFrame = moverFrame editorFrame:CreateMoverGuideLines() diff --git a/libs/DF/externals.lua b/libs/DF/externals.lua index 4d419f35..7df43012 100644 --- a/libs/DF/externals.lua +++ b/libs/DF/externals.lua @@ -94,7 +94,7 @@ function detailsFramework:LoadLCC(LibCC) end end -if IS_WOW_PROJECT_CLASSIC_ERA then +if IS_WOW_PROJECT_CLASSIC_ERA and false then --disable this for now, as it appears to be working now through API changes... local LibCC = LibStub("LibClassicCasterino", true) if (LibCC and not _G.DetailsFrameworkLCCLoaded) then detailsFramework:LoadLCC(LibCC) diff --git a/libs/DF/fw.lua b/libs/DF/fw.lua index 80a6302e..41aa51e7 100644 --- a/libs/DF/fw.lua +++ b/libs/DF/fw.lua @@ -1,6 +1,6 @@ -local dversion = 482 +local dversion = 494 local major, minor = "DetailsFramework-1.0", dversion local DF, oldminor = LibStub:NewLibrary(major, minor) @@ -313,23 +313,51 @@ function DF.GetSpecializationRole(...) return nil end +--[=[ dump of C_EncounterJournal + ["GetEncountersOnMap"] = function, + ["SetPreviewMythicPlusLevel"] = function, + ["GetLootInfoByIndex"] = function, + ["GetSlotFilter"] = function, + ["IsEncounterComplete"] = function, + ["SetTab"] = function, + ["ResetSlotFilter"] = function, + ["OnOpen"] = function, + ["InstanceHasLoot"] = function, + ["GetSectionIconFlags"] = function, + ["SetPreviewPvpTier"] = function, + ["GetEncounterJournalLink"] = function, + ["GetInstanceForGameMap"] = function, + ["GetSectionInfo"] = function, + ["GetLootInfo"] = function, + ["GetDungeonEntrancesForMap"] = function, + ["OnClose"] = function, + ["SetSlotFilter"] = function, +--]=] + --build dummy encounter journal functions if they doesn't exists --this is done for compatibility with classic and if in the future EJ_ functions are moved to C_ +---@class EncounterJournal : table +---@field EJ_GetInstanceForMap fun(mapId: number) +---@field EJ_GetInstanceInfo fun(journalInstanceID: number) +---@field EJ_SelectInstance fun(journalInstanceID: number) +---@field EJ_GetEncounterInfoByIndex fun(index: number, journalInstanceID: number?) +---@field EJ_GetEncounterInfo fun(journalEncounterID: number) +---@field EJ_SelectEncounter fun(journalEncounterID: number) +---@field EJ_GetSectionInfo fun(sectionID: number) +---@field EJ_GetCreatureInfo fun(index: number, journalEncounterID: number?) +---@field EJ_SetDifficulty fun(difficultyID: number) +---@field EJ_GetNumLoot fun(): number DF.EncounterJournal = { - EJ_GetCurrentInstance = EJ_GetCurrentInstance or function() return nil end, EJ_GetInstanceForMap = EJ_GetInstanceForMap or function() return nil end, EJ_GetInstanceInfo = EJ_GetInstanceInfo or function() return nil end, EJ_SelectInstance = EJ_SelectInstance or function() return nil end, - EJ_GetEncounterInfoByIndex = EJ_GetEncounterInfoByIndex or function() return nil end, EJ_GetEncounterInfo = EJ_GetEncounterInfo or function() return nil end, EJ_SelectEncounter = EJ_SelectEncounter or function() return nil end, - EJ_GetSectionInfo = EJ_GetSectionInfo or function() return nil end, EJ_GetCreatureInfo = EJ_GetCreatureInfo or function() return nil end, EJ_SetDifficulty = EJ_SetDifficulty or function() return nil end, EJ_GetNumLoot = EJ_GetNumLoot or function() return 0 end, - EJ_GetLootInfoByIndex = EJ_GetLootInfoByIndex or function() return nil end, } --will always give a very random name for our widgets @@ -498,10 +526,12 @@ end ---get a value from a table using a path, e.g. getfrompath(tbl, "a.b.c") is the same as tbl.a.b.c ---@param t table ---@param path string +---@param subOffset number? ---@return any -function DF.table.getfrompath(t, path) +function DF.table.getfrompath(t, path, subOffset) if (path:match("%.") or path:match("%[")) then local value + local offset = 0 for key in path:gmatch("[%w_]+") do value = t[key] or t[tonumber(key)] @@ -513,6 +543,11 @@ function DF.table.getfrompath(t, path) --update t for the next iteration t = value + offset = offset + 1 + + if (subOffset == offset) then + return value + end end return value @@ -1329,7 +1364,7 @@ function DF:SetFontOutline(fontString, outline) outline = "OUTLINE" elseif (type(outline) == "boolean" and not outline) then - outline = "NONE" + outline = "" --"NONE" elseif (outline == 1) then outline = "OUTLINE" @@ -1338,6 +1373,7 @@ function DF:SetFontOutline(fontString, outline) outline = "THICKOUTLINE" end end + outline = (not outline or outline == "NONE") and "" or outline fontString:SetFont(font, fontSize, outline) end @@ -1897,7 +1933,7 @@ local anchoringFunctions = { ---set the anchor point using a df_anchor table ---@param widget uiobject ---@param anchorTable df_anchor ----@param anchorTo uiobject +---@param anchorTo uiobject? function DF:SetAnchor(widget, anchorTable, anchorTo) anchorTo = anchorTo or widget:GetParent() anchoringFunctions[anchorTable.side](widget, anchorTo, anchorTable.x, anchorTable.y) @@ -2651,6 +2687,7 @@ function DF:CreateAnimation(animation, animationType, order, duration, arg1, arg elseif (animationType == "ROTATION") then anim:SetDegrees(arg1) --degree + --print("SetOrigin", arg2, arg3, arg4) anim:SetOrigin(arg2 or "center", arg3 or 0, arg4 or 0) --point, x, y elseif (animationType == "TRANSLATION") then diff --git a/libs/DF/loadconditions.lua b/libs/DF/loadconditions.lua index bea2e91b..a4bbd50d 100644 --- a/libs/DF/loadconditions.lua +++ b/libs/DF/loadconditions.lua @@ -100,20 +100,19 @@ local default_load_conditions_frame_options = { 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("TRAIT_CONFIG_LIST_UPDATED") + filterFrame:RegisterEvent("CHALLENGE_MODE_START") + else + filterFrame:RegisterEvent("PLAYER_ENTERING_WORLD") 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") diff --git a/libs/DF/panel.lua b/libs/DF/panel.lua index 16dbd814..b3eecced 100644 --- a/libs/DF/panel.lua +++ b/libs/DF/panel.lua @@ -2074,10 +2074,11 @@ function detailsFramework:CreateSimplePanel(parent, width, height, title, frameN --set the backdrop if (panelOptions.RoundedCorners) then local tRoundedCornerPreset = { - roundness = 6, + roundness = 3, color = {.1, .1, .1, 0.98}, border_color = {.05, .05, .05, 0.834}, use_titlebar = true, + titlebar_height = 26, } detailsFramework:AddRoundedCornersToFrame(simplePanel, tRoundedCornerPreset) else diff --git a/libs/DF/rounded_panel.lua b/libs/DF/rounded_panel.lua index 3167c9a9..f782630f 100644 --- a/libs/DF/rounded_panel.lua +++ b/libs/DF/rounded_panel.lua @@ -53,11 +53,13 @@ local cornerNames = {"TopLeft", "TopRight", "BottomLeft", "BottomRight"} ---@field border_color any ---@field corner_texture any ---@field horizontal_border_size_offset number? +---@field titlebar_height number? ---@class df_roundedpanel_preset : table, df_roundedpanel_options ---@field border_color any ---@field color any ---@field roundness number? +---@field titlebar_height number? ---@class df_roundedcornermixin : table ---@field RoundedCornerConstructor fun(self:df_roundedpanel) --called from CreateRoundedPanel @@ -239,9 +241,9 @@ detailsFramework.RoundedCornerPanelMixin = { ---create a frame placed at the top side of the rounded panel, this frame has a member called 'Text' which is a fontstring for the title ---@param self df_roundedpanel ---@return df_roundedpanel - CreateTitleBar = function(self) + CreateTitleBar = function(self, optionsTable) ---@type df_roundedpanel - local titleBar = detailsFramework:CreateRoundedPanel(self, "$parentTitleBar", {width = self.options.width - 6, height = 16}) + local titleBar = detailsFramework:CreateRoundedPanel(self, "$parentTitleBar", {width = self.options.width - 6, height = self.options.titlebar_height}) titleBar:SetPoint("top", self, "top", 0, -4) titleBar:SetRoundness(5) titleBar:SetFrameLevel(9500) @@ -512,19 +514,20 @@ local defaultOptions = { color = {.1, .1, .1, 1}, border_color = {.2, .2, .2, .5}, corner_texture = [[Interface\CHARACTERFRAME\TempPortraitAlphaMaskSmall]], + titlebar_height = 26, } local defaultPreset = { color = {.1, .1, .1, 1}, border_color = {.2, .2, .2, .5}, roundness = 3, + titlebar_height = 16, } ---create a regular panel with rounded corner ---@param parent frame ---@param name string|nil ---@param optionsTable table|nil ----@return df_roundedpanel function detailsFramework:CreateRoundedPanel(parent, name, optionsTable) ---@type df_roundedpanel local newRoundedPanel = CreateFrame("frame", name, parent, "BackdropTemplate") @@ -540,7 +543,10 @@ function detailsFramework:CreateRoundedPanel(parent, name, optionsTable) if (newRoundedPanel.options.use_titlebar) then ---@type df_roundedpanel - local titleBar = detailsFramework:CreateRoundedPanel(newRoundedPanel, "$parentTitleBar", {height = 26}) + local titleBar = newRoundedPanel:CreateTitleBar(newRoundedPanel.options) + + --[=[ + local titleBar = detailsFramework:CreateRoundedPanel(newRoundedPanel, "$parentTitleBar", {height = newRoundedPanel.options.titlebar_height, title = newRoundedPanel.options.title}) titleBar:SetColor(unpack(titleBarColor)) titleBar:SetPoint("top", newRoundedPanel, "top", 0, -7) @@ -549,6 +555,7 @@ function detailsFramework:CreateRoundedPanel(parent, name, optionsTable) newRoundedPanel.TitleBar = titleBar titleBar:SetRoundness(5) newRoundedPanel.bHasTitleBar = true + --]=] end if (newRoundedPanel.options.use_scalebar) then @@ -579,7 +586,8 @@ local applyPreset = function(frame, preset) end if (preset.use_titlebar) then - frame:CreateTitleBar() + frame:CreateTitleBar(preset) + frame.TitleBar.Text:SetText(preset.title) end end @@ -623,6 +631,7 @@ 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 + frame.options.titlebar_height = preset.titlebar_height applyPreset(frame, preset) else applyPreset(frame, defaultPreset) diff --git a/libs/DF/scrollbox.lua b/libs/DF/scrollbox.lua index fa4a4979..f315daa2 100644 --- a/libs/DF/scrollbox.lua +++ b/libs/DF/scrollbox.lua @@ -686,7 +686,23 @@ end detailsFramework.CanvasScrollBoxMixin = { + SetScrollSpeed = function(self, speed) + assert(type(speed) == "number", "CanvasScrollBox:SetScrollSpeed(speed): speed must be a number.") + self.scrollStep = speed + end, + + GetScrollSpeed = function(self) + return self.scrollStep + end, + OnVerticalScroll = function(self, delta) + local scrollStep = self:GetScrollSpeed() + if (delta > 0) then + self:SetVerticalScroll(math.max(self:GetVerticalScroll() - scrollStep, 0)) + else + self:SetVerticalScroll(math.min(self:GetVerticalScroll() + scrollStep, self:GetVerticalScrollRange())) + end + end, } local canvasScrollBoxDefaultOptions = { @@ -706,6 +722,10 @@ local canvasScrollBoxDefaultOptions = { function detailsFramework:CreateCanvasScrollBox(parent, child, name, options) ---@type df_canvasscrollbox local canvasScrollBox = CreateFrame("scrollframe", name or ("DetailsFrameworkCanvasScroll" .. math.random(50000, 10000000)), parent, "BackdropTemplate, UIPanelScrollFrameTemplate") + canvasScrollBox.scrollStep = 20 + canvasScrollBox.minValue = 0 + + canvasScrollBox:SetScript("OnMouseWheel", detailsFramework.CanvasScrollBoxMixin.OnVerticalScroll) detailsFramework:Mixin(canvasScrollBox, detailsFramework.CanvasScrollBoxMixin) detailsFramework:Mixin(canvasScrollBox, detailsFramework.OptionsFunctions) diff --git a/libs/DF/slider.lua b/libs/DF/slider.lua index 932a36e5..6cc9656b 100644 --- a/libs/DF/slider.lua +++ b/libs/DF/slider.lua @@ -319,7 +319,7 @@ DF:Mixin(DFSliderMetaFunctions, DF.ScriptHookMixin) return end - DetailsFrameworkSliderButtons1:ShowMe(slider) + DetailsFrameworkSliderButtons1:ShowMe(slider, object.bAttachButtonsToLeft) local kill = object:RunHooksForWidget("OnEnter", slider, object) if (kill) then @@ -363,6 +363,14 @@ DF:Mixin(DFSliderMetaFunctions, DF.ScriptHookMixin) local sliderButtonsParentFrame = DetailsFrameworkSliderButtons1 or CreateFrame("frame", "DetailsFrameworkSliderButtons1", UIParent, "BackdropTemplate") sliderButtonsParentFrame:Hide() sliderButtonsParentFrame:SetHeight(18) --width is set by setpoint + + C_Timer.After(0, function() + if (not sliderButtonsParentFrame.__background) then + DetailsFramework:ApplyStandardBackdrop(sliderButtonsParentFrame) --ApplyStandardBackdrop loads after this file + end + sliderButtonsParentFrame:SetBackdropBorderColor(0, 0, 0, 0) + sliderButtonsParentFrame:SetBackdropColor(.05, .05, .05, .9) + end) sliderButtonsParentFrame.isGoingToHide = false local timeToHide = 0 @@ -375,11 +383,27 @@ DF:Mixin(DFSliderMetaFunctions, DF.ScriptHookMixin) end end - function sliderButtonsParentFrame:ShowMe(sliderFrame) + function sliderButtonsParentFrame:ShowMe(sliderFrame, bAnchorToLeft) + sliderButtonsParentFrame.bAnchorToLeft = bAnchorToLeft sliderButtonsParentFrame:SetParent(sliderFrame) sliderButtonsParentFrame:ClearAllPoints() - sliderButtonsParentFrame:SetPoint("bottomleft", sliderFrame, "topleft", -5, -5) - sliderButtonsParentFrame:SetPoint("bottomright", sliderFrame, "topright", 5, -5) + + sliderButtonsParentFrame.buttonMinor:ClearAllPoints() + sliderButtonsParentFrame.buttonPlus:ClearAllPoints() + + sliderButtonsParentFrame:SetWidth(35) + + if (sliderButtonsParentFrame.bAnchorToLeft) then + sliderButtonsParentFrame:SetPoint("topright", sliderFrame, "topleft", 0, 0) + sliderButtonsParentFrame:SetPoint("bottomright", sliderFrame, "bottomleft", 0, 0) + sliderButtonsParentFrame.buttonPlus:SetPoint("right", sliderButtonsParentFrame, "right", -2, 0) + sliderButtonsParentFrame.buttonMinor:SetPoint("right", sliderButtonsParentFrame.buttonPlus, "left", 0, 0) + else + sliderButtonsParentFrame:SetPoint("topleft", sliderFrame, "topright", 2, 0) + sliderButtonsParentFrame:SetPoint("bottomleft", sliderFrame, "bottomright", 2, 0) + sliderButtonsParentFrame.buttonMinor:SetPoint("left", sliderButtonsParentFrame, "left", 2, 0) + sliderButtonsParentFrame.buttonPlus:SetPoint("left", sliderButtonsParentFrame.buttonMinor, "right", 0, 0) + end sliderButtonsParentFrame:SetFrameStrata("FULLSCREEN") sliderButtonsParentFrame:SetFrameLevel(sliderFrame:GetFrameLevel() + 1000) @@ -399,10 +423,12 @@ DF:Mixin(DFSliderMetaFunctions, DF.ScriptHookMixin) sliderButtonsParentFrame:SetScript("OnUpdate", onUpdateTimeToHide) end - local buttonPlus = CreateFrame("button", "DetailsFrameworkSliderButtonsPlusButton", sliderButtonsParentFrame, "BackdropTemplate") - local buttonMinor = CreateFrame("button", "DetailsFrameworkSliderButtonsMinorButton", sliderButtonsParentFrame, "BackdropTemplate") + local buttonPlus = DetailsFrameworkSliderButtonsPlusButton or CreateFrame("button", "DetailsFrameworkSliderButtonsPlusButton", sliderButtonsParentFrame, "BackdropTemplate") + local buttonMinor = DetailsFrameworkSliderButtonsMinorButton or CreateFrame("button", "DetailsFrameworkSliderButtonsMinorButton", sliderButtonsParentFrame, "BackdropTemplate") buttonPlus:SetFrameStrata(sliderButtonsParentFrame:GetFrameStrata()) buttonMinor:SetFrameStrata(sliderButtonsParentFrame:GetFrameStrata()) + sliderButtonsParentFrame.buttonPlus = buttonPlus + sliderButtonsParentFrame.buttonMinor = buttonMinor buttonPlus:SetScript("OnEnter", function(self) if (sliderButtonsParentFrame.isGoingToHide) then diff --git a/libs/DF/unitframe.lua b/libs/DF/unitframe.lua index 04347c44..23594fe8 100644 --- a/libs/DF/unitframe.lua +++ b/libs/DF/unitframe.lua @@ -1937,6 +1937,7 @@ function detailsFramework:CreateCastBar(parent, name, settingsOverride) detailsFramework:Mixin(castBar, detailsFramework.CastFrameFunctions) detailsFramework:Mixin(castBar, detailsFramework.StatusBarFunctions) + castBar:CreateTextureMask() castBar:AddMaskTexture(castBar.flashTexture) castBar:AddMaskTexture(castBar.background) diff --git a/media/options_visibility_context.tga b/media/options_visibility_context.tga index 5a063f66..39d7d3b8 100644 Binary files a/media/options_visibility_context.tga and b/media/options_visibility_context.tga differ