-- ------------------------------------------------------------------------------ -- -- TradeSkillMaster -- -- https://tradeskillmaster.com -- -- All Rights Reserved - Detailed license information included with addon. -- -- ------------------------------------------------------------------------------ -- local _, TSM = ... local Tooltip = TSM:NewPackage("Tooltip") local ItemString = TSM.Include("Util.ItemString") local ObjectPool = TSM.Include("Util.ObjectPool") local ItemTooltip = TSM.Include("Service.ItemTooltip") local Settings = TSM.Include("Service.Settings") local LibTSMClass = TSM.Include("LibTSMClass") local TooltipInfo = LibTSMClass.DefineClass("TooltipInfo") local TooltipEntry = LibTSMClass.DefineClass("TooltipEntry") local private = { entryObjPool = ObjectPool.New("TOOLTIP_ENTRY", TooltipEntry), settings = nil, registeredInfo = {}, settingsBuilder = nil, } local ITER_INDEX_PART_MULTIPLE = 1000 -- ============================================================================ -- Module Functions -- ============================================================================ function Tooltip.OnInitialize() private.settings = Settings.NewView() :AddKey("global", "tooltipOptions", "moduleTooltips") :AddKey("global", "tooltipOptions", "customPriceTooltips") :AddKey("global", "tooltipOptions", "vendorBuyTooltip") :AddKey("global", "tooltipOptions", "vendorSellTooltip") :AddKey("global", "tooltipOptions", "groupNameTooltip") :AddKey("global", "tooltipOptions", "detailedDestroyTooltip") :AddKey("global", "tooltipOptions", "millTooltip") :AddKey("global", "tooltipOptions", "prospectTooltip") :AddKey("global", "tooltipOptions", "deTooltip") :AddKey("global", "tooltipOptions", "transformTooltip") :AddKey("global", "tooltipOptions", "operationTooltips") :AddKey("global", "tooltipOptions", "inventoryTooltipFormat") ItemTooltip.SetWrapperPopulateFunction(private.PopulateTooltip) private.settingsBuilder = ItemTooltip.CreateBuilder() end function Tooltip.CreateInfo() return TooltipInfo() end function Tooltip.Register(info) info:_CheckDefaults() tinsert(private.registeredInfo, info) end function Tooltip.SettingsLineIterator() assert(not private.settingsBuilder:_Prepare(ItemString.GetPlaceholder(), 1)) return private.SettingsLineIteratorHelper, nil, 0 end -- ============================================================================ -- TooltipInfo Class -- ============================================================================ function TooltipInfo.__init(self) self._headingLeft = nil self._headingRight = nil self._settingsModule = nil self._entries = {} end function TooltipInfo.SetHeadings(self, left, right) self._headingLeft = left self._headingRight = right return self end function TooltipInfo.SetSettingsModule(self, settingsModule) self._settingsModule = settingsModule return self end function TooltipInfo.AddSettingEntry(self, key, defaultValue, populateFunc, populateArg) if defaultValue == nil then defaultValue = private.settings:GetDefaultReadOnly(key) end assert(type(defaultValue) == "boolean") local entry = private.entryObjPool:Get() entry:_Acquire(self, key, true, false, defaultValue, populateFunc, populateArg) tinsert(self._entries, entry) return self end function TooltipInfo.AddSettingValueEntry(self, key, setValue, clearValue, populateFunc, populateArg) local entry = private.entryObjPool:Get() entry:_Acquire(self, key, setValue, clearValue, nil, populateFunc, populateArg) tinsert(self._entries, entry) return self end function TooltipInfo.DeleteSettingsByKeyMatch(self, matchStr) for i = #self._entries, 1, -1 do local entry = self._entries[i] if entry:KeyMatches(matchStr) then tremove(self._entries, i) entry:_Release() private.entryObjPool:Recycle(entry) end end end function TooltipInfo._CheckDefaults(self) if self._settingsModule and not private.settings.moduleTooltips[self._settingsModule] then -- populate all the default values private.settings.moduleTooltips[self._settingsModule] = {} for _, entry in ipairs(self._entries) do entry:_ResetSetting() end end end function TooltipInfo._GetSettingsTable(self) if self._settingsModule then return private.settings.moduleTooltips[self._settingsModule] else return private.settings end end function TooltipInfo._Populate(self, tooltip, itemString) local headingRightText = self._headingRight and self._headingRight(tooltip, itemString) or nil tooltip:StartSection(self._headingLeft, headingRightText) for _, entry in ipairs(self._entries) do if entry:IsEnabled() then entry:_Populate(tooltip, itemString) end end tooltip:EndSection() end function TooltipInfo._GetEntry(self, index) return self._entries[index] end -- ============================================================================ -- TooltipEntry Class -- ============================================================================ function TooltipEntry.__init(self) self._info = nil self._settingKey = nil self._settingSetValue = nil self._settingClearValue = nil self._settingDefaultValue = nil self._populateFunc = nil self._populateArg = nil end function TooltipEntry._Acquire(self, info, key, setValue, clearValue, defaultValue, populateFunc, populateArg) assert(setValue == nil or setValue, "'setValue' must be truthy") assert(info and key and populateFunc) assert(clearValue ~= nil or defaultValue ~= nil) self._info = info self._settingKey = key self._settingSetValue = setValue or true self._settingClearValue = clearValue or false self._settingDefaultValue = defaultValue self._populateFunc = populateFunc self._populateArg = populateArg end function TooltipEntry._Release(self) self._info = nil self._settingKey = nil self._settingSetValue = nil self._settingClearValue = nil self._settingDefaultValue = nil self._populateFunc = nil self._populateArg = nil end function TooltipEntry.GetSettingInfo(self) local tbl = self._info:_GetSettingsTable() local key, key2, extra = strsplit(".", self._settingKey) assert(key and not extra) if key2 then tbl = tbl[key] key = key2 end assert(type(tbl) == "table") return tbl, key end function TooltipEntry.IsEnabled(self) local settingTbl, settingKey = self:GetSettingInfo() local settingValue = settingTbl[settingKey] if settingValue == nil then assert(self._settingDefaultValue ~= nil) settingTbl[settingKey] = self._settingDefaultValue settingValue = settingTbl[settingKey] end return settingValue == self._settingSetValue end function TooltipEntry.KeyMatches(self, matchStr) return strmatch(self._settingKey, matchStr) and true or false end function TooltipEntry._ResetSetting(self, value) local tbl = self._info:_GetSettingsTable() if self._settingDefaultValue ~= nil then tbl[self._settingKey] = self._settingDefaultValue elseif self._settingClearValue ~= nil then tbl[self._settingKey] = self._settingClearValue else error("Invalid setting info") end end function TooltipEntry._Populate(self, tooltip, itemString) self._populateFunc(tooltip, itemString, self._populateArg) end -- ============================================================================ -- Private Helper Functions -- ============================================================================ function private.PopulateTooltip(tooltip, itemString) for _, info in ipairs(private.registeredInfo) do info:_Populate(tooltip, itemString) end end function private.SettingsLineIteratorHelper(_, index) local infoIndex = floor(index / (ITER_INDEX_PART_MULTIPLE ^ 2)) local entryIndex = floor(index / ITER_INDEX_PART_MULTIPLE) % ITER_INDEX_PART_MULTIPLE local lineIndex = index % ITER_INDEX_PART_MULTIPLE local info, entry = nil, nil while lineIndex >= private.settingsBuilder:GetNumLines() do -- move to the next entry info = private.registeredInfo[infoIndex] entryIndex = entryIndex + 1 entry = info and info:_GetEntry(entryIndex) if entry then private.settingsBuilder:SetDisabled(not entry:IsEnabled()) entry:_Populate(private.settingsBuilder, ItemString.GetPlaceholder()) private.settingsBuilder:SetDisabled(false) else -- move to the next info if infoIndex > 0 then private.settingsBuilder:EndSection() end infoIndex = infoIndex + 1 info = private.registeredInfo[infoIndex] if info then private.settingsBuilder:StartSection(info._headingLeft) entryIndex = 0 else return end end end lineIndex = lineIndex + 1 index = infoIndex * ITER_INDEX_PART_MULTIPLE ^ 2 + entryIndex * ITER_INDEX_PART_MULTIPLE + lineIndex local leftText, rightText, lineColor = private.settingsBuilder:GetLine(lineIndex) assert(infoIndex < ITER_INDEX_PART_MULTIPLE and entryIndex < ITER_INDEX_PART_MULTIPLE and lineIndex < ITER_INDEX_PART_MULTIPLE) return index, leftText, rightText, lineColor end