Mercurial > wow > inventory
view Summary.lua @ 1:9fff13c08f99
Initial release, config and summary windows mostly working. Base functionality available.
author | Zerotorescue |
---|---|
date | Fri, 08 Oct 2010 16:11:59 +0200 |
parents | c6ff7ba0e8f6 |
children | 1a815139e4c3 |
line wrap: on
line source
local addon = LibStub("AceAddon-3.0"):GetAddon("Inventory"); local mod = addon:NewModule("Summary", "AceEvent-3.0", "AceTimer-3.0"); local AceGUI = LibStub("AceGUI-3.0"); function mod:OnEnable() self:RegisterWidgets(); -- Register our own slash commands addon:RegisterSlash(function() mod:BuildMain(); mod:Build(); end, "s", "sum", "summary"); end function mod:RegisterWidgets() -- Register InlineGroupWithButton-widget -- This widget adds a button next to the header of an inline group -- SetPoint doesn't seem usable within AceGUI. local widgetType = "InlineGroupWithButton"; local widgetVersion = 1; local function Constructor() local widget = AceGUI:Create("InlineGroup"); widget.type = widgetType; widget.MakeButton = function(self, buttonSettings) if type(buttonSettings) == "table" then local button = CreateFrame("Button", nil, self.frame, "UIPanelButtonTemplate"); button:SetText(buttonSettings.name); button:SetHeight(22); button:SetWidth(120); button:SetPoint("TOPRIGHT", self.frame, "TOPRIGHT", -10, 5); button:SetScript("OnClick", buttonSettings.exec); button.tooltipTitle = buttonSettings.name; button.tooltip = buttonSettings.desc or ""; button:SetScript("OnEnter", function(self) GameTooltip:SetOwner(self, "ANCHOR_NONE") GameTooltip:SetPoint("BOTTOM", self, "TOP") GameTooltip:SetText(self.tooltipTitle, 1, .82, 0, 1) if type(self.tooltip) == "string" then GameTooltip:AddLine(self.tooltip, 1, 1, 1, 1); end GameTooltip:Show(); end); button:SetScript("OnLeave", function(self) GameTooltip:Hide(); end); else error("settings must be a table - usage: MakeButton(table);"); end end return widget; end AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion); end local itemsCache = {}; local CACHE_ITEMS_TOTAL, CACHE_ITEMS_CURRENT, CACHE_ITEMS_PER_UPDATE = 0, 0, 5; local cacheStart; function mod:BuildMain() LibStub("AceConfigDialog-3.0"):Close("InventoryOptions"); -- Main Window mod.frame = AceGUI:Create("Frame"); mod.frame:SetTitle("Inventory Summary"); mod.frame:SetLayout("Fill"); mod.frame:SetCallback("OnClose", function(widget) AceGUI:Release(widget); end); -- ScrollFrame child mod.scrollFrame = AceGUI:Create("ScrollFrame"); mod.scrollFrame:SetLayout("Flow"); mod.frame:AddChild(mod.scrollFrame); -- Reset items cache table.wipe(itemsCache); end local sortMethod = "item"; local sortDirectory = "ASC"; local function ReSort(subject) if sortMethod == subject then sortDirectory = (sortDirectory == "ASC" and "DESC") or "ASC"; else sortDirectory = "ASC"; end sortMethod = subject; mod:Build(); end function mod:Build() local start = GetTime(); mod.scrollFrame:ReleaseChildren(); -- We are going to add hunderds of widgets to this container, but don't want it to also cause hunderds of reflows, thus pause reflowing and just do it once when everything is prepared -- This appears to be required for each container we wish to pause, so also do this for the contents mod.scrollFrame:PauseLayout(); local playerName = UnitName("player"); -- Go through all our stored groups for groupName, values in pairs(addon.db.global.groups) do local trackAt = (values.trackAtCharacters or (values.trackAtCharacters == nil and addon.db.global.defaults.trackAtCharacters)); -- Does this group have any items and do we want to track it at this char? if values.items and trackAt[playerName] then -- Get group settings local stockRequired = (values.minimumStock or (values.minimumStock == nil and addon.db.global.defaults.minimumStock)); local showWhenBelow = (values.summaryThresholdShow or (values.summaryThresholdShow == nil and addon.db.global.defaults.summaryThresholdShow)); local priceThreshold = (values.priceThreshold or (values.priceThreshold == nil and addon.db.global.defaults.priceThreshold)); local hideWhenBelowPriceThreshold = (values.hideFromSummaryWhenBelowPriceThreshold or (values.hideFromSummaryWhenBelowPriceThreshold == nil and addon.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold)); -- Make group container local iGroup = AceGUI:Create("InlineGroupWithButton"); iGroup:PauseLayout(); iGroup:SetTitle(groupName); iGroup:SetFullWidth(true); iGroup:SetLayout("Flow"); iGroup:MakeButton({ name = "Queue", desc = "Queue all items in this group.", exec = function() print(groupName); end, }); -- Headers -- Itemlink local lblItem = AceGUI:Create("InteractiveLabel"); lblItem:SetText("|cfffed000Item|r"); lblItem:SetFontObject(GameFontHighlight); lblItem:SetRelativeWidth(0.7); lblItem:SetCallback("OnClick", function() ReSort("item"); end); iGroup:AddChild(lblItem); -- Current quantity local lblQuantity = AceGUI:Create("InteractiveLabel"); lblQuantity:SetText("|cfffed000Cur.|r"); lblQuantity:SetFontObject(GameFontHighlight); lblQuantity:SetRelativeWidth(0.099); lblQuantity:SetCallback("OnClick", function() ReSort("current"); end); iGroup:AddChild(lblQuantity); -- Required stock local lblStockRequired = AceGUI:Create("InteractiveLabel"); lblStockRequired:SetText("|cfffed000Req.|r"); lblStockRequired:SetFontObject(GameFontHighlight); lblStockRequired:SetRelativeWidth(0.099); lblStockRequired:SetCallback("OnClick", function() ReSort("percentage"); end); iGroup:AddChild(lblStockRequired); -- Lowest value local lblValue = AceGUI:Create("InteractiveLabel"); lblValue:SetText("|cfffed000Value|r"); lblValue:SetFontObject(GameFontHighlight); lblValue:SetRelativeWidth(0.099); lblValue:SetCallback("OnClick", function() ReSort("value"); end); iGroup:AddChild(lblValue); if not itemsCache[groupName] then itemsCache[groupName] = {}; -- Sort item list for itemId in pairs(values.items) do local itemName, itemLink, itemRarity = GetItemInfo(itemId); table.insert(itemsCache[groupName], { id = itemId, name = itemName, link = itemLink, value = 0,--addon:GetAuctionValue(itemLink), rarity = itemRarity, count = 0,--addon:GetItemCount(itemId), set = {}, }); CACHE_ITEMS_TOTAL = CACHE_ITEMS_TOTAL + 1; end end table.sort(itemsCache[groupName], function(a, b) if sortMethod == "item" and a.rarity == b.rarity then -- Do a name-compare for items of the same rarity -- Otherwise epics first, then junk if sortDirectory == "ASC" then return a.name:upper() < b.name:upper(); else return a.name:upper() > b.name:upper(); end elseif sortMethod == "item" then if sortDirectory == "ASC" then return a.rarity > b.rarity; -- the comparers were reversed because we want epics first else return a.rarity < b.rarity; -- the comparers were reversed because we want epics first end elseif sortMethod == "current" then if sortDirectory == "ASC" then return a.count < b.count; else return a.count > b.count; end elseif sortMethod == "percentage" then if sortDirectory == "ASC" then return ( a.count / stockRequired ) < ( b.count / stockRequired ); else return ( a.count / stockRequired ) > ( b.count / stockRequired ); end elseif sortMethod == "value" then if sortDirectory == "ASC" then return a.value < b.value; else return a.value > b.value; end end end); -- Show stuff for i, item in pairs(itemsCache[groupName]) do if ( item.count / stockRequired ) < showWhenBelow and not (hideWhenBelowPriceThreshold and item.value < priceThreshold) then local btnItemLink = AceGUI:Create("ItemLinkButton"); btnItemLink:SetUserData("exec", function() print("Win."); end); btnItemLink:SetRelativeWidth(0.7); btnItemLink:SetItemId(item.id); iGroup:AddChild(btnItemLink); -- Current quantity local lblQuantity = AceGUI:Create("Label"); lblQuantity:SetText(self:ColorCode(item.count, stockRequired)); lblQuantity:SetRelativeWidth(0.099); iGroup:AddChild(lblQuantity); -- Required stock local lblStockRequired = AceGUI:Create("Label"); lblStockRequired:SetText(stockRequired); lblStockRequired:SetRelativeWidth(0.099); iGroup:AddChild(lblStockRequired); -- Value local lblValue = AceGUI:Create("Label"); lblValue:SetText(self:DisplayMoney(item.value, priceThreshold)); lblValue:SetRelativeWidth(0.099); iGroup:AddChild(lblValue); -- Remember references to the value and current fields so we can fill them later if item.set then item.set.value = lblValue; item.set.current = lblQuantity; end end end iGroup:ResumeLayout(); mod.scrollFrame:AddChild(iGroup); -- this can take up to .5 seconds, might need to look into again at a later time end end mod.scrollFrame:ResumeLayout(); mod.scrollFrame:DoLayout(); if CACHE_ITEMS_TOTAL > 0 then cacheStart = GetTime(); self.tmrUpdater = self:ScheduleRepeatingTimer("UpdateNextItem", .01); -- Once every 100 frames (or once every x frames if you have less than 100 FPS, basically, once every frame) end end function mod:UpdateNextItem() local i = 0; for groupName, items in pairs(itemsCache) do local minimumStock = addon:GetOptionByKey(groupName, "minimumStock"); local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); for _, item in pairs(items) do if item.set then item.count = addon:GetItemCount(item.id); if item.set.current then item.set.current:SetText(self:ColorCode(item.count, minimumStock)); end item.value = addon:GetAuctionValue(item.link); if item.set.value then item.set.value:SetText(self:DisplayMoney(item.value, priceThreshold)); end item.set = nil; i = i + 1; CACHE_ITEMS_CURRENT = CACHE_ITEMS_CURRENT + 1; mod.frame:SetStatusText("Caching auction values and item-counts... " .. floor(CACHE_ITEMS_CURRENT / CACHE_ITEMS_TOTAL * 100) .. "% has already been processed."); if i >= CACHE_ITEMS_PER_UPDATE then return; end end end end -- Reset trackers CACHE_ITEMS_TOTAL = 0; CACHE_ITEMS_CURRENT = 0; -- Rebuild list so hidden items due to too low prices get added self:Build(); -- Stop timer self:CancelTimer(self.tmrUpdater, true); -- Announce mod.frame:SetStatusText("All prices and itemcounts have been cached. This process took " .. ceil(GetTime() - cacheStart) .. " seconds."); -- Forget time cacheStart = nil; end function mod:ColorCode(num, required) local percentage = ( num / required ); if percentage >= addon.db.global.defaults.colors.green then return ("|cff00ff00%d|r"):format(num); elseif percentage >= addon.db.global.defaults.colors.yellow then return ("|cffffff00%d|r"):format(num); elseif percentage >= addon.db.global.defaults.colors.orange then return ("|cffff9933%d|r"):format(num); elseif percentage >= addon.db.global.defaults.colors.red then return ("|cffff0000%d|r"):format(num); end end function mod:DisplayMoney(value, priceThreshold) if value < priceThreshold then return ("|cffff0000%s|r"):format(addon:ReadableMoney(value or 0, true)); else return addon:ReadableMoney(value or 0, true); end end function mod:NumberFormat(num) local formatted = string.gsub(num, "(%d)(%d%d%d)$", "%1,%2", 1); while true do formatted, matches = string.gsub(formatted, "(%d)(%d%d%d),", "%1,%2,", 1); if matches == 0 then break; end end return formatted; end --[[ No longer used, we're now caching complete item data instead of just AH values. local AuctionValueCache = {}; function mod:GetAuctionValue(link) local itemId = addon:GetItemId(link); if AuctionValueCache[itemId] then return AuctionValueCache[itemId]; else local value = addon:GetAuctionValue(link); AuctionValueCache[itemId] = value; -- Reset the cache 1 minute after last updating it self:CancelTimer(self.tmrResetCache, true); self.tmrResetCache = self:ScheduleTimer(function() table.wipe(AuctionValueCache); mod.frame:SetStatusText("The auction item value cache has been reset."); end, 60); mod.frame:SetStatusText(""); return value; end end ]]