local MAJOR, MINOR = "LibSort-1.0", 1 local LibSort, oldminor = LibStub:NewLibrary(MAJOR, MINOR) if not LibSort then return end --the same or newer version of this lib is already loaded into memory LIBSORT = LibSort -- Lookup Tables --- local wm = WINDOW_MANAGER local defaultType = {["isNumeric"] = 0, ["isBoolean"] = false, ["isString"] = ""} local inventoryTypes = {[INVENTORY_BACKPACK] = ZO_PlayerInventoryBackpack, [INVENTORY_BANK] = ZO_PlayerBankBackpack, [INVENTORY_GUILD_BANK] = ZO_GuildBankBackpack} --- Utility functions --- local function removeSpaces(name) return name:gsub(" ","") end local function makePrefix(name) return removeSpaces(name) .. "_" end function LibSort:Debug(msg) if LibSort.isDebugging then d("[LibSort]: "..msg) end end --- Storage variables --- LibSort.RegisteredCallbacks = {} LibSort.AddonOrder = {} LibSort.DefaultOrdersLow = {} LibSort.DefaultOrdersHigh = {} --- Arrow generation --- function LibSort:SetupArrows() LibSort.ItemSortBank = wm:CreateControlFromVirtual("ItemSortBank", ZO_PlayerBankSortBy, "ZO_SortHeaderIcon") LibSort.ItemSortBank:SetDimensions(16, 32) LibSort.ItemSortBank:SetAnchor(RIGHT, ZO_PlayerBankSortByName, LEFT, -15) ZO_SortHeader_SetMouseCallback(ItemSortBank, function(header, eventType) if(eventType == "OnMouseEnter") then InitializeTooltip(InformationTooltip, ItemSortBank, BOTTOMRIGHT, 0, 32) SetTooltipText(InformationTooltip, "Sort") else ClearTooltip(InformationTooltip) end end) ZO_PlayerInventory_InitSortHeaderIcon(LibSort.ItemSortBank, "EsoUI/Art/Miscellaneous/list_sortHeader_icon_neutral.dds", "EsoUI/Art/Miscellaneous/list_sortHeader_icon_sortUp.dds", "EsoUI/Art/Miscellaneous/list_sortHeader_icon_sortDown.dds", "EsoUI/Art/Miscellaneous/list_sortHeader_icon_over.dds", "age") PLAYER_INVENTORY.inventories[INVENTORY_BANK].sortHeaders:AddHeader(ItemSortBank) LibSort.ItemSortGuild = wm:CreateControlFromVirtual("ItemSortGuild", ZO_GuildBankSortBy, "ZO_SortHeaderIcon") LibSort.ItemSortGuild:SetDimensions(16, 32) LibSort.ItemSortGuild:SetAnchor(RIGHT, ZO_GuildBankSortByName, LEFT, -15) ZO_SortHeader_SetMouseCallback(ItemSortGuild, function(header, eventType) if(eventType == "OnMouseEnter") then InitializeTooltip(InformationTooltip, ItemSortGuild, BOTTOMRIGHT, 0, 32) SetTooltipText(InformationTooltip, "Sort") else ClearTooltip(InformationTooltip) end end) ZO_PlayerInventory_InitSortHeaderIcon(LibSort.ItemSortGuild, "EsoUI/Art/Miscellaneous/list_sortHeader_icon_neutral.dds", "EsoUI/Art/Miscellaneous/list_sortHeader_icon_sortUp.dds", "EsoUI/Art/Miscellaneous/list_sortHeader_icon_sortDown.dds", "EsoUI/Art/Miscellaneous/list_sortHeader_icon_over.dds", "age") PLAYER_INVENTORY.inventories[INVENTORY_GUILD_BANK].sortHeaders:AddHeader(ItemSortGuild) end --- Main functions --- LibSort.sortKeys = ZO_Inventory_GetDefaultHeaderSortKeys() function LibSort:InjectKeys() for addon, callbacks in pairs(self.RegisteredCallbacks) do for name, data in pairs(callbacks) do if not self.sortKeys[data.key] then self.sortKeys[data.key] = {} self.sortKeys[data.key][data.dataType] = true end end end self:ReOrderKeys() end function LibSort:ReOrderKeys() local first local previous for i, addonName in ipairs(self.AddonOrder) do if self.DefaultOrdersLow[addonName] then for _, name in ipairs(self.DefaultOrdersLow[addonName]) do local data = self.RegisteredCallbacks[addonName][name] if data then -- we skip the ones we haven't registered yet first, previous = self:SetKeyOrder(first, previous, data) end end end end for i, addonName in ipairs(self.AddonOrder) do if self.DefaultOrdersHigh[addonName] then for _, name in ipairs(self.DefaultOrdersHigh[addonName]) do local data = self.RegisteredCallbacks[addonName][name] if data then -- we skip the ones we haven't registered yet first, previous = self:SetKeyOrder(first, previous, data) end end end end self.sortKeys[previous].tiebreaker = "name" PLAYER_INVENTORY:ChangeSort("age", INVENTORY_BACKPACK, true) PLAYER_INVENTORY:ChangeSort("age", INVENTORY_BANK, true) PLAYER_INVENTORY:ChangeSort("age", INVENTORY_GUILD_BANK, true) end function LibSort:SetKeyOrder(first, previous, data) if not first then first = true self.sortKeys["age"].tiebreaker = data.key self.sortKeys["age"].reverseTiebreakerSortOrder = nil else if previous then self.sortKeys[previous].tiebreaker = data.key end end return first, data.key end function LibSort:ProcessInventory(inventoryType) local container = inventoryTypes[inventoryType] if not container then return end for i, slot in ipairs(container.data) do local slotType, bag, index = slot.data.slotType, slot.data.bagId, slot.data.slotIndex for addon, callbacks in pairs(self.RegisteredCallbacks) do for name, data in pairs(callbacks) do if not slot.data[data.key] then slot.data[data.key] = data.func(slotType, bag, index) or defaultType[data.dataType] end end end end end function LibSort:Loaded(event, name) if name ~= "ZO_Ingame" then return end self.savedVars = ZO_SavedVars:New("ZO_Ingame_SavedVariables", 1, "LibSort") EVENT_MANAGER:UnregisterForEvent("LibSortLoaded", EVENT_ADD_ON_LOADED) ZO_PreHook(PLAYER_INVENTORY, "ApplySort", function(self, inventoryType) LibSort:ProcessInventory(inventoryType) end) zo_callLater(function() LIBSORT:SetupArrows() end, 3000) end EVENT_MANAGER:RegisterForEvent("LibSortLoaded", EVENT_ADD_ON_LOADED, function(...) LibSort:Loaded(...) end) --------- API --------- function LibSort:Unregister(addonName, name) if not name then self.RegisteredCallbacks[addonName] = nil self.DefaultOrdersHigh[addonName] = nil self.DefaultOrdersLow[addonName] = nil return end if self.RegisteredCallbacks[addonName] then self.RegisteredCallbacks[addonName][name] = nil end end function LibSort:Register(addonName, name, desc, key, func, dataType) if not dataType then dataType = "isNumeric" end if not self.RegisteredCallbacks[addonName] then self.RegisteredCallbacks[addonName] = {} table.insert(self.AddonOrder, addonName) end self.RegisteredCallbacks[addonName][name] = {key = makePrefix(addonName)..key, func = func, desc = desc, dataType = dataType} if not self.DefaultOrdersHigh[addonName] then self.DefaultOrdersHigh[addonName] = {} end table.insert(self.DefaultOrdersHigh[addonName], name) self:InjectKeys() end function LibSort:RegisterNumeric(addonName, name, desc, key, func) self:Register(addonName, name, desc, key, func, "isNumeric") end function LibSort:RegisterBoolean(addonName, name, desc, key, func) self:Register(addonName, name, desc, key, func, "isBoolean") end function LibSort:RegisterString(addonName, name, desc, key, func) self:Register(addonName, name, desc, key, func, "isString") end function LibSort:RegisterDefaultOrder(addonName, keyTableLow, keyTableHigh) self.DefaultOrdersHigh[addonName] = keyTableHigh self.DefaultOrdersLow[addonName] = keyTableLow self:ReOrderKeys() end function LibSort:SetDebugging(flag) self.isDebugging = flag end