Zerotorescue@62: local addon = select(2, ...); -- Get a reference to the main addon object Zerotorescue@205: local mod = addon:NewModule("Summary", "AceTimer-3.0"); -- register a new module, Summary: resposible for building the summary window Zerotorescue@0: Zerotorescue@122: local _G = _G; -- prevent looking up of the global table Zerotorescue@122: local sformat, sgsub, supper, mceil, mfloor, tinsert, twipe, tsort = _G.string.format, _G.string.gsub, _G.string.upper, _G.math.ceil, _G.math.floor, _G.table.insert, _G.table.wipe, _G.table.sort; Zerotorescue@122: local pairs, type, select = _G.pairs, _G.type, _G.select; Zerotorescue@122: Zerotorescue@23: local unknownItemName = "Unknown (#%d)"; Zerotorescue@23: Zerotorescue@62: local CACHE_ITEMS_TOTAL, CACHE_ITEMS_CURRENT, itemsCache = 0, 0, {}; Zerotorescue@62: local AceGUI, cacheStart; Zerotorescue@23: Zerotorescue@0: function mod:OnEnable() Zerotorescue@62: -- Register the summary specific widget Zerotorescue@62: addon:GetModule("Widgets"):InlineGroupWithButton(); Zerotorescue@62: Zerotorescue@62: AceGUI = LibStub("AceGUI-3.0"); Zerotorescue@0: Zerotorescue@1: -- Register our own slash commands Zerotorescue@62: -- /im summary Zerotorescue@1: addon:RegisterSlash(function() Zerotorescue@205: if self:IsFrameOpen() then Zerotorescue@205: self:CloseFrame(); Zerotorescue@205: else Zerotorescue@205: self:Show(); Zerotorescue@205: end Zerotorescue@36: end, { "s", "sum", "summary" }, "|Hfunction:InventoriumCommandHandler:summary|h|cff00fff7/im summary|r|h (or /im s) - Show the summary window containing an overview of all items within the groups tracked at this current character."); Zerotorescue@62: Zerotorescue@62: -- /im reset Zerotorescue@23: addon:RegisterSlash(function() Zerotorescue@23: if mod.frame then Zerotorescue@73: mod.frame:SetWidth(700); Zerotorescue@23: mod.frame:SetHeight(600); Zerotorescue@23: Zerotorescue@98: addon:Print("Resetting width and height of the summary frame."); Zerotorescue@23: end Zerotorescue@36: end, { "r", "reset" }, "|Hfunction:InventoriumCommandHandler:reset|h|cff00fff7/im reset|r|h (or /im r) - Reset the size of the summary frame."); Zerotorescue@0: end Zerotorescue@0: Zerotorescue@13: local function ShowTooltip(self) Zerotorescue@13: -- If this function is called from a widget, self is the widget and self.frame the actual frame Zerotorescue@13: local this = self.frame or self; Zerotorescue@13: Zerotorescue@13: GameTooltip:SetOwner(this, "ANCHOR_NONE"); Zerotorescue@13: GameTooltip:SetPoint("BOTTOM", this, "TOP"); Zerotorescue@13: GameTooltip:SetText(this.tooltipTitle, 1, .82, 0, 1); Zerotorescue@13: Zerotorescue@13: if type(this.tooltip) == "string" then Zerotorescue@13: GameTooltip:AddLine(this.tooltip, 1, 1, 1, 1); Zerotorescue@13: end Zerotorescue@13: Zerotorescue@13: GameTooltip:Show(); Zerotorescue@13: end Zerotorescue@13: Zerotorescue@13: local function HideTooltip() Zerotorescue@13: GameTooltip:Hide(); Zerotorescue@13: end Zerotorescue@13: Zerotorescue@0: function mod:BuildMain() Zerotorescue@205: if not self.frame then Zerotorescue@205: -- Main Window Zerotorescue@205: self.frame = AceGUI:Create("Frame"); Zerotorescue@205: _G["InventoriumSummary"] = self.frame; -- name the global frame so it can be put in the UISpecialFrames Zerotorescue@205: self.frame:SetTitle("Inventory Summary"); Zerotorescue@205: self.frame:SetLayout("Fill"); Zerotorescue@205: self.frame:SetCallback("OnClose", function(widget) Zerotorescue@205: mod:CancelTimer(self.tmrUpdater, true); Zerotorescue@205: mod:CloseFrame(); Zerotorescue@205: end); Zerotorescue@205: self.frame:SetWidth(addon.db.profile.defaults.summary.width); Zerotorescue@205: self.frame:SetHeight(addon.db.profile.defaults.summary.height); Zerotorescue@205: self.frame.OnWidthSet = function(_, width) Zerotorescue@205: addon.db.profile.defaults.summary.width = width; Zerotorescue@205: end; Zerotorescue@205: self.frame.OnHeightSet = function(_, height) Zerotorescue@205: addon.db.profile.defaults.summary.height = height; Zerotorescue@205: end; Zerotorescue@205: Zerotorescue@205: -- Close on escape Zerotorescue@205: tinsert(UISpecialFrames, "InventoriumSummary"); Zerotorescue@205: Zerotorescue@205: -- ScrollFrame child Zerotorescue@205: self.scrollFrame = AceGUI:Create("ScrollFrame"); Zerotorescue@205: self.scrollFrame:SetLayout("Flow"); Zerotorescue@205: Zerotorescue@205: self.frame:AddChild(self.scrollFrame); Zerotorescue@205: Zerotorescue@205: -- Reset items cache Zerotorescue@205: twipe(itemsCache); Zerotorescue@205: end Zerotorescue@205: end Zerotorescue@205: Zerotorescue@205: function mod:Show() Zerotorescue@205: -- We don't want any other windows open at this time. Zerotorescue@205: for name, module in addon:IterateModules() do Zerotorescue@205: if module.CloseFrame then Zerotorescue@205: module:CloseFrame(); Zerotorescue@205: end Zerotorescue@205: end Zerotorescue@0: Zerotorescue@205: self:BuildMain(); Zerotorescue@205: self:Build(); Zerotorescue@205: end Zerotorescue@205: Zerotorescue@205: function mod:IsFrameOpen() Zerotorescue@205: return (self.frame and self.frame:IsShown()); Zerotorescue@0: end Zerotorescue@0: Zerotorescue@9: function mod:CloseFrame() Zerotorescue@205: if self:IsFrameOpen() then Zerotorescue@205: --self.scrollFrame:Release(); Zerotorescue@205: --self.scrollFrame = nil; Zerotorescue@205: Zerotorescue@205: self.frame:Hide(); Zerotorescue@10: Zerotorescue@10: -- Stop caching Zerotorescue@10: Zerotorescue@10: -- Stop timer Zerotorescue@10: self:CancelTimer(self.tmrUpdater, true); Zerotorescue@10: Zerotorescue@10: -- Reset trackers Zerotorescue@10: CACHE_ITEMS_TOTAL = 0; Zerotorescue@10: CACHE_ITEMS_CURRENT = 0; Zerotorescue@9: end Zerotorescue@9: end Zerotorescue@9: Zerotorescue@0: local sortMethod = "item"; Zerotorescue@0: local sortDirectory = "ASC"; Zerotorescue@0: local function ReSort(subject) Zerotorescue@0: if sortMethod == subject then Zerotorescue@0: sortDirectory = (sortDirectory == "ASC" and "DESC") or "ASC"; Zerotorescue@0: else Zerotorescue@0: sortDirectory = "ASC"; Zerotorescue@0: end Zerotorescue@0: sortMethod = subject; Zerotorescue@0: Zerotorescue@0: mod:Build(); Zerotorescue@0: end Zerotorescue@57: Zerotorescue@10: -- From http://www.wowwiki.com/API_sort Zerotorescue@10: local function pairsByKeys (t, f) Zerotorescue@10: local a = {} Zerotorescue@62: for n in pairs(t) do tinsert(a, n) end Zerotorescue@122: tsort(a, f) Zerotorescue@10: local i = 0 -- iterator variable Zerotorescue@10: local iter = function () -- iterator function Zerotorescue@10: i = i + 1 Zerotorescue@10: if a[i] == nil then return nil Zerotorescue@10: else return a[i], t[a[i]] Zerotorescue@10: end Zerotorescue@10: end Zerotorescue@10: return iter Zerotorescue@10: end Zerotorescue@0: Zerotorescue@0: function mod:Build() Zerotorescue@10: local buildStartTime, times = GetTime(), {}; Zerotorescue@0: Zerotorescue@205: self.frame:Show(); Zerotorescue@205: Zerotorescue@1: -- 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 Zerotorescue@1: -- This appears to be required for each container we wish to pause, so also do this for the contents Zerotorescue@1: mod.scrollFrame:PauseLayout(); Zerotorescue@1: Zerotorescue@10: mod.scrollFrame:ReleaseChildren(); Zerotorescue@10: Zerotorescue@10: -- Refresh button Zerotorescue@10: local btnRefresh = AceGUI:Create("Button"); Zerotorescue@10: btnRefresh:SetText("Refresh"); Zerotorescue@10: btnRefresh:SetRelativeWidth(.2); Zerotorescue@10: btnRefresh:SetCallback("OnClick", function() Zerotorescue@10: -- Reset items cache Zerotorescue@122: twipe(itemsCache); Zerotorescue@10: Zerotorescue@10: -- Rebuild itemlist and start caching Zerotorescue@10: mod:Build(); Zerotorescue@10: end); Zerotorescue@13: btnRefresh:SetCallback("OnEnter", ShowTooltip); Zerotorescue@13: btnRefresh:SetCallback("OnLeave", HideTooltip); Zerotorescue@13: btnRefresh.frame.tooltipTitle = "Refresh Cache"; Zerotorescue@13: btnRefresh.frame.tooltip = "Refresh the list and recache the item counts and auction values."; Zerotorescue@10: Zerotorescue@10: mod.scrollFrame:AddChild(btnRefresh); Zerotorescue@10: Zerotorescue@13: local lblSpacer = AceGUI:Create("Label"); Zerotorescue@13: lblSpacer:SetRelativeWidth(.03); Zerotorescue@13: Zerotorescue@13: mod.scrollFrame:AddChild(lblSpacer); Zerotorescue@13: Zerotorescue@10: -- Speed slider Zerotorescue@13: local sdrSpeed = AceGUI:Create("Slider"); Zerotorescue@13: sdrSpeed:SetLabel("Processing speed"); Zerotorescue@62: sdrSpeed:SetSliderValues(0.01, 5, 0.01); -- min, max, interval Zerotorescue@13: sdrSpeed:SetIsPercent(true); Zerotorescue@13: sdrSpeed:SetRelativeWidth(.3); Zerotorescue@13: sdrSpeed:SetCallback("OnMouseUp", function(self, event, value) Zerotorescue@122: addon.db.profile.defaults.summary.speed = mceil( ( ( value * 100 ) / 5) - .5 ); Zerotorescue@10: end); Zerotorescue@61: sdrSpeed:SetValue( addon.db.profile.defaults.summary.speed * 5 / 100 ); Zerotorescue@13: sdrSpeed:SetCallback("OnEnter", ShowTooltip); Zerotorescue@13: sdrSpeed:SetCallback("OnLeave", HideTooltip); Zerotorescue@13: sdrSpeed.frame.tooltipTitle = "Caching Processing Speed"; Zerotorescue@13: sdrSpeed.frame.tooltip = "Change the speed at which item counts and auction values are being cached. Higher is faster but may drastically reduce your FPS while caching.\n\nAnything above 100% will probably become uncomfortable."; Zerotorescue@10: Zerotorescue@13: mod.scrollFrame:AddChild(sdrSpeed); Zerotorescue@13: Zerotorescue@13: local lblSpacer = AceGUI:Create("Label"); Zerotorescue@13: lblSpacer:SetRelativeWidth(.23); Zerotorescue@13: Zerotorescue@13: mod.scrollFrame:AddChild(lblSpacer); Zerotorescue@13: Zerotorescue@13: -- Config button Zerotorescue@13: --[[local btnConfig = AceGUI:Create("Button"); Zerotorescue@13: btnConfig:SetText("Config"); Zerotorescue@13: btnConfig:SetRelativeWidth(.2); Zerotorescue@13: btnConfig:SetCallback("OnClick", function() Zerotorescue@13: --TODO: Tidy up Zerotorescue@13: SlashCmdList["INVENTORIUM"]("config"); Zerotorescue@13: end); Zerotorescue@13: btnConfig:SetCallback("OnEnter", ShowTooltip); Zerotorescue@13: btnConfig:SetCallback("OnLeave", HideTooltip); Zerotorescue@13: btnConfig.frame.tooltipTitle = "Config"; Zerotorescue@13: btnConfig.frame.tooltip = "Click to open the config window. This will close the current window."; Zerotorescue@13: Zerotorescue@13: mod.scrollFrame:AddChild(btnConfig);]] Zerotorescue@13: Zerotorescue@13: local lblSpacer = AceGUI:Create("Label"); Zerotorescue@13: lblSpacer:SetRelativeWidth(.03); Zerotorescue@13: Zerotorescue@13: mod.scrollFrame:AddChild(lblSpacer); Zerotorescue@13: Zerotorescue@13: -- Queue all button Zerotorescue@13: local btnQueueAll = AceGUI:Create("Button"); Zerotorescue@13: btnQueueAll:SetText("Queue All"); Zerotorescue@13: btnQueueAll:SetRelativeWidth(.2); Zerotorescue@13: btnQueueAll:SetCallback("OnClick", function() Zerotorescue@14: self:SendMessage("IM_QUEUE_ALL"); Zerotorescue@13: end); Zerotorescue@13: btnQueueAll:SetCallback("OnEnter", ShowTooltip); Zerotorescue@13: btnQueueAll:SetCallback("OnLeave", HideTooltip); Zerotorescue@13: btnQueueAll.frame.tooltipTitle = "Queue all"; Zerotorescue@13: btnQueueAll.frame.tooltip = "Queue everything that requires restocking within every single visible group."; Zerotorescue@13: Zerotorescue@13: mod.scrollFrame:AddChild(btnQueueAll); Zerotorescue@10: Zerotorescue@122: times.init = mceil( ( GetTime() - buildStartTime ) * 1000 ); Zerotorescue@10: addon:Debug("Time spent legend: (init / sorting / preparing / building / all)."); Zerotorescue@10: Zerotorescue@1: local playerName = UnitName("player"); Zerotorescue@1: Zerotorescue@1: -- Go through all our stored groups Zerotorescue@61: for groupName, values in pairsByKeys(addon.db.profile.groups, function(a, b) return a:lower() < b:lower(); end) do Zerotorescue@10: local groupStartTime, groupTimes = GetTime(), {}; Zerotorescue@10: Zerotorescue@50: local trackAt = addon:GetOptionByKey(groupName, "trackAtCharacters"); Zerotorescue@50: Zerotorescue@1: Zerotorescue@1: -- Does this group have any items and do we want to track it at this char? Zerotorescue@1: if values.items and trackAt[playerName] then Zerotorescue@10: Zerotorescue@10: Zerotorescue@0: -- Get group settings Zerotorescue@62: local minLocalStock = addon:GetOptionByKey(groupName, "minLocalStock"); Zerotorescue@62: local minGlobalStock = addon:GetOptionByKey(groupName, "minGlobalStock"); Zerotorescue@50: local showWhenBelow = addon:GetOptionByKey(groupName, "summaryThresholdShow"); Zerotorescue@50: local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); Zerotorescue@50: local hideWhenBelowPriceThreshold = addon:GetOptionByKey(groupName, "summaryHidePriceThreshold"); Zerotorescue@50: local alwaysGetAuctionValue = addon:GetOptionByKey(groupName, "alwaysGetAuctionValue"); Zerotorescue@10: Zerotorescue@0: -- Make group container Zerotorescue@0: local iGroup = AceGUI:Create("InlineGroupWithButton"); Zerotorescue@1: iGroup:PauseLayout(); Zerotorescue@0: iGroup:SetTitle(groupName); Zerotorescue@0: iGroup:SetFullWidth(true); Zerotorescue@0: iGroup:SetLayout("Flow"); Zerotorescue@0: iGroup:MakeButton({ Zerotorescue@0: name = "Queue", Zerotorescue@0: desc = "Queue all items in this group.", Zerotorescue@0: exec = function() Zerotorescue@136: addon:Print(("Queuing all items within %s craftable by the currently open profession."):format(groupName)); Zerotorescue@14: self:SendMessage("IM_QUEUE_GROUP", groupName); Zerotorescue@0: end, Zerotorescue@0: }); Zerotorescue@0: Zerotorescue@10: Zerotorescue@10: Zerotorescue@0: -- Headers Zerotorescue@1: Zerotorescue@0: -- Itemlink Zerotorescue@0: local lblItem = AceGUI:Create("InteractiveLabel"); Zerotorescue@0: lblItem:SetText("|cfffed000Item|r"); Zerotorescue@0: lblItem:SetFontObject(GameFontHighlight); Zerotorescue@57: lblItem:SetRelativeWidth(.7); Zerotorescue@0: lblItem:SetCallback("OnClick", function() ReSort("item"); end); Zerotorescue@13: lblItem:SetCallback("OnEnter", ShowTooltip); Zerotorescue@13: lblItem:SetCallback("OnLeave", HideTooltip); Zerotorescue@13: lblItem.frame.tooltipTitle = "Item"; Zerotorescue@13: lblItem.frame.tooltip = "Sort on the item quality, then name."; Zerotorescue@0: Zerotorescue@0: iGroup:AddChild(lblItem); Zerotorescue@0: Zerotorescue@50: -- Local quantity Zerotorescue@50: local lblLocal = AceGUI:Create("InteractiveLabel"); Zerotorescue@50: lblLocal:SetText("|cfffed000Loc.|r"); Zerotorescue@50: lblLocal:SetFontObject(GameFontHighlight); Zerotorescue@50: lblLocal:SetRelativeWidth(.099); Zerotorescue@50: lblLocal:SetCallback("OnClick", function() ReSort("local"); end); Zerotorescue@50: lblLocal:SetCallback("OnEnter", ShowTooltip); Zerotorescue@50: lblLocal:SetCallback("OnLeave", HideTooltip); Zerotorescue@50: lblLocal.frame.tooltipTitle = "Local stock"; Zerotorescue@50: lblLocal.frame.tooltip = "Sort on the amount of items currently in local stock."; Zerotorescue@50: Zerotorescue@50: iGroup:AddChild(lblLocal); Zerotorescue@50: Zerotorescue@0: -- Current quantity Zerotorescue@0: local lblQuantity = AceGUI:Create("InteractiveLabel"); Zerotorescue@0: lblQuantity:SetText("|cfffed000Cur.|r"); Zerotorescue@0: lblQuantity:SetFontObject(GameFontHighlight); Zerotorescue@10: lblQuantity:SetRelativeWidth(.099); Zerotorescue@0: lblQuantity:SetCallback("OnClick", function() ReSort("current"); end); Zerotorescue@13: lblQuantity:SetCallback("OnEnter", ShowTooltip); Zerotorescue@13: lblQuantity:SetCallback("OnLeave", HideTooltip); Zerotorescue@13: lblQuantity.frame.tooltipTitle = "Current stock"; Zerotorescue@13: lblQuantity.frame.tooltip = "Sort on the amount of items currently in stock."; Zerotorescue@0: Zerotorescue@0: iGroup:AddChild(lblQuantity); Zerotorescue@0: Zerotorescue@1: -- Lowest value Zerotorescue@1: local lblValue = AceGUI:Create("InteractiveLabel"); Zerotorescue@1: lblValue:SetText("|cfffed000Value|r"); Zerotorescue@1: lblValue:SetFontObject(GameFontHighlight); Zerotorescue@10: lblValue:SetRelativeWidth(.099); Zerotorescue@1: lblValue:SetCallback("OnClick", function() ReSort("value"); end); Zerotorescue@13: lblValue:SetCallback("OnEnter", ShowTooltip); Zerotorescue@13: lblValue:SetCallback("OnLeave", HideTooltip); Zerotorescue@13: lblValue.frame.tooltipTitle = "Value"; Zerotorescue@13: lblValue.frame.tooltip = "Sort on the item auction value."; Zerotorescue@1: Zerotorescue@1: iGroup:AddChild(lblValue); Zerotorescue@1: Zerotorescue@10: Zerotorescue@10: -- Retrieve items list Zerotorescue@1: if not itemsCache[groupName] then Zerotorescue@1: itemsCache[groupName] = {}; Zerotorescue@74: end Zerotorescue@74: Zerotorescue@74: if #(itemsCache[groupName]) == 0 then Zerotorescue@74: -- If the item cache is empty Zerotorescue@12: for itemId, _ in pairs(values.items) do Zerotorescue@74: local newItemData = addon.ItemData:New(itemId); Zerotorescue@1: Zerotorescue@74: -- if no price threshold is set for this item and you don't want to always get the auction value, then don't look it up either Zerotorescue@74: if priceThreshold == 0 and not alwaysGetAuctionValue then Zerotorescue@74: newItemData.value = -4; Zerotorescue@74: end Zerotorescue@74: Zerotorescue@74: tinsert(itemsCache[groupName], newItemData); Zerotorescue@74: Zerotorescue@1: CACHE_ITEMS_TOTAL = CACHE_ITEMS_TOTAL + 1; Zerotorescue@1: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@122: groupTimes.init = mceil( ( GetTime() - groupStartTime ) * 1000 ); Zerotorescue@10: Zerotorescue@10: Zerotorescue@10: Zerotorescue@10: -- Sort items Zerotorescue@122: tsort(itemsCache[groupName], function(a, b) Zerotorescue@73: local aRarity = a.rarity or 1; Zerotorescue@73: local bRarity = b.rarity or 1; Zerotorescue@73: Zerotorescue@73: if sortMethod == "item" and aRarity == bRarity then Zerotorescue@1: -- Do a name-compare for items of the same rarity Zerotorescue@1: -- Otherwise epics first, then junk Zerotorescue@73: Zerotorescue@106: local aName = a.name or sformat(unknownItemName, a.id); Zerotorescue@106: local bName = b.name or sformat(unknownItemName, b.id); Zerotorescue@73: Zerotorescue@0: if sortDirectory == "ASC" then Zerotorescue@73: return supper(aName) < supper(bName); Zerotorescue@0: else Zerotorescue@73: return supper(aName) > supper(bName); Zerotorescue@1: end Zerotorescue@1: elseif sortMethod == "item" then Zerotorescue@1: if sortDirectory == "ASC" then Zerotorescue@73: return aRarity > bRarity; -- the comparers were reversed because we want epics first Zerotorescue@1: else Zerotorescue@73: return aRarity < bRarity; -- the comparers were reversed because we want epics first Zerotorescue@0: end Zerotorescue@0: elseif sortMethod == "current" then Zerotorescue@0: if sortDirectory == "ASC" then Zerotorescue@74: return a.globalCount < b.globalCount; Zerotorescue@0: else Zerotorescue@74: return a.globalCount > b.globalCount; Zerotorescue@0: end Zerotorescue@50: elseif sortMethod == "local" then Zerotorescue@50: if sortDirectory == "ASC" then Zerotorescue@50: return a.localCount < b.localCount; Zerotorescue@50: else Zerotorescue@50: return a.localCount > b.localCount; Zerotorescue@50: end Zerotorescue@1: elseif sortMethod == "value" then Zerotorescue@1: if sortDirectory == "ASC" then Zerotorescue@1: return a.value < b.value; Zerotorescue@1: else Zerotorescue@1: return a.value > b.value; Zerotorescue@1: end Zerotorescue@0: end Zerotorescue@0: end); Zerotorescue@0: Zerotorescue@122: groupTimes.sorting = mceil( ( GetTime() - groupStartTime ) * 1000 ); Zerotorescue@10: Zerotorescue@10: Zerotorescue@10: Zerotorescue@10: Zerotorescue@10: -- Show itemslist Zerotorescue@1: for i, item in pairs(itemsCache[groupName]) do Zerotorescue@31: -- Go through all items for this group Zerotorescue@31: Zerotorescue@74: if (( item.globalCount / minGlobalStock ) < showWhenBelow or ( item.localCount / minLocalStock ) < showWhenBelow) and (not hideWhenBelowPriceThreshold or priceThreshold == 0 or item.value < 0 or item.value >= priceThreshold) then Zerotorescue@31: -- if the option "hide when below threshold" is disabled or no price threshold is set or the value is above the price threshold or the value could not be determined, proceed Zerotorescue@62: Zerotorescue@0: local btnItemLink = AceGUI:Create("ItemLinkButton"); Zerotorescue@23: btnItemLink:SetUserData("exec", function(_, itemId, _, buttonName) Zerotorescue@23: local itemName, itemLink = GetItemInfo(itemId); Zerotorescue@23: Zerotorescue@23: if buttonName == "LeftButton" and IsShiftKeyDown() and itemLink then Zerotorescue@23: ChatEdit_InsertLink(itemLink); Zerotorescue@23: elseif buttonName == "LeftButton" and IsAltKeyDown() and itemName and AuctionFrame and AuctionFrame:IsShown() and AuctionFrameBrowse then Zerotorescue@23: -- Start search at page 0 Zerotorescue@23: AuctionFrameBrowse.page = 0; Zerotorescue@23: Zerotorescue@23: -- Set the search field (even though we could use "ChatEdit_InsertLink", this ensures the right field is updated) Zerotorescue@23: BrowseName:SetText(itemName) Zerotorescue@23: Zerotorescue@23: QueryAuctionItems(itemName, nil, nil, 0, 0, 0, 0, 0, 0); Zerotorescue@23: end Zerotorescue@23: end); Zerotorescue@57: btnItemLink:SetRelativeWidth(.7); Zerotorescue@73: btnItemLink:SetItem(item); Zerotorescue@0: Zerotorescue@0: iGroup:AddChild(btnItemLink); Zerotorescue@0: Zerotorescue@50: -- Local quantity Zerotorescue@50: local lblLocal = AceGUI:Create("Label"); Zerotorescue@106: lblLocal:SetText(addon:DisplayItemCount(item.localCount, minLocalStock)); Zerotorescue@50: lblLocal:SetRelativeWidth(.099); Zerotorescue@50: Zerotorescue@50: iGroup:AddChild(lblLocal); Zerotorescue@50: Zerotorescue@0: -- Current quantity Zerotorescue@0: local lblQuantity = AceGUI:Create("Label"); Zerotorescue@106: lblQuantity:SetText(addon:DisplayItemCount(item.globalCount, minGlobalStock)); Zerotorescue@10: lblQuantity:SetRelativeWidth(.099); Zerotorescue@0: Zerotorescue@0: iGroup:AddChild(lblQuantity); Zerotorescue@0: Zerotorescue@1: -- Value Zerotorescue@1: local lblValue = AceGUI:Create("Label"); Zerotorescue@1: lblValue:SetText(self:DisplayMoney(item.value, priceThreshold)); Zerotorescue@10: lblValue:SetRelativeWidth(.099); Zerotorescue@1: Zerotorescue@1: iGroup:AddChild(lblValue); Zerotorescue@1: Zerotorescue@1: -- Remember references to the value and current fields so we can fill them later Zerotorescue@74: item.set.value = lblValue; Zerotorescue@74: item.set.globalCount = lblQuantity; Zerotorescue@74: item.set.localCount = lblLocal; Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@122: groupTimes.preparing = mceil( ( GetTime() - groupStartTime ) * 1000 ); Zerotorescue@10: Zerotorescue@1: iGroup:ResumeLayout(); Zerotorescue@1: mod.scrollFrame:AddChild(iGroup); -- this can take up to .5 seconds, might need to look into again at a later time Zerotorescue@10: Zerotorescue@122: groupTimes.building = mceil( ( GetTime() - groupStartTime ) * 1000 ); Zerotorescue@0: end Zerotorescue@10: Zerotorescue@13: if groupStartTime and groupTimes then Zerotorescue@122: addon:Debug("Building of %s took %d ms (%d / %d / %d / %d / %d).", groupName, mceil( ( GetTime() - groupStartTime ) * 1000 ), groupTimes.init or 0, groupTimes.sorting or 0, groupTimes.preparing or 0, groupTimes.building or 0, mceil( ( GetTime() - buildStartTime ) * 1000 )); Zerotorescue@13: end Zerotorescue@0: end Zerotorescue@1: Zerotorescue@1: mod.scrollFrame:ResumeLayout(); Zerotorescue@1: mod.scrollFrame:DoLayout(); Zerotorescue@1: Zerotorescue@122: addon:Debug("Done building summary after %d ms.", mceil( ( GetTime() - buildStartTime ) * 1000 )); Zerotorescue@10: Zerotorescue@1: if CACHE_ITEMS_TOTAL > 0 then Zerotorescue@1: cacheStart = GetTime(); Zerotorescue@7: self:CancelTimer(self.tmrUpdater, true); Zerotorescue@1: 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) Zerotorescue@1: end Zerotorescue@1: end Zerotorescue@1: Zerotorescue@1: function mod:UpdateNextItem() Zerotorescue@1: local i = 0; Zerotorescue@1: Zerotorescue@1: for groupName, items in pairs(itemsCache) do Zerotorescue@61: local minGlobalStock = addon:GetOptionByKey(groupName, "minGlobalStock"); Zerotorescue@61: local minLocalStock = addon:GetOptionByKey(groupName, "minLocalStock"); Zerotorescue@1: local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold"); Zerotorescue@1: Zerotorescue@1: for _, item in pairs(items) do Zerotorescue@74: if item.globalCount == -3 or item.localCount == -3 or item.value == -3 then Zerotorescue@74: if item.globalCount == -3 then Zerotorescue@10: -- Only if item count was queued, update it Zerotorescue@74: item.globalCount = addon:GetItemCount(item.id, groupName); Zerotorescue@74: if item.set.globalCount and item.set.globalCount.SetText then Zerotorescue@106: item.set.globalCount:SetText(addon:DisplayItemCount(item.globalCount, minGlobalStock)); Zerotorescue@10: end Zerotorescue@1: end Zerotorescue@1: Zerotorescue@50: if item.localCount == -3 then Zerotorescue@50: -- Only if item count was queued, update it Zerotorescue@54: item.localCount = addon:GetLocalItemCount(item.id, groupName); Zerotorescue@50: if item.set.localCount and item.set.localCount.SetText then Zerotorescue@106: item.set.localCount:SetText(addon:DisplayItemCount(item.localCount, minLocalStock)); Zerotorescue@50: end Zerotorescue@50: end Zerotorescue@50: Zerotorescue@10: if item.value == -3 then Zerotorescue@10: -- Only if item value was queued, update it Zerotorescue@23: Zerotorescue@23: -- The itemlink might not have been loaded yet in which case we retry Zerotorescue@23: item.link = item.link or select(2, GetItemInfo(item.id)); Zerotorescue@23: Zerotorescue@23: if item.link then Zerotorescue@23: item.value = addon:GetAuctionValue(item.link, groupName); Zerotorescue@23: if item.set.value and item.set.value.SetText then Zerotorescue@23: item.set.value:SetText(self:DisplayMoney(item.value, priceThreshold)); Zerotorescue@23: end Zerotorescue@10: end Zerotorescue@1: end Zerotorescue@1: Zerotorescue@1: i = i + 1; Zerotorescue@1: CACHE_ITEMS_CURRENT = CACHE_ITEMS_CURRENT + 1; Zerotorescue@1: Zerotorescue@9: if mod.frame then Zerotorescue@122: mod.frame:SetStatusText(sformat("Caching auction values and item-counts... %d%% has already been processed.", mfloor(CACHE_ITEMS_CURRENT / CACHE_ITEMS_TOTAL * 100))); Zerotorescue@9: end Zerotorescue@1: Zerotorescue@61: if i >= addon.db.profile.defaults.summary.speed then Zerotorescue@1: return; Zerotorescue@1: end Zerotorescue@1: end Zerotorescue@1: end Zerotorescue@1: end Zerotorescue@1: Zerotorescue@1: -- Reset trackers Zerotorescue@1: CACHE_ITEMS_TOTAL = 0; Zerotorescue@1: CACHE_ITEMS_CURRENT = 0; Zerotorescue@1: Zerotorescue@1: -- Stop timer Zerotorescue@1: self:CancelTimer(self.tmrUpdater, true); Zerotorescue@10: Zerotorescue@10: -- Rebuild list so hidden items due to too low prices get added Zerotorescue@10: self:Build(); Zerotorescue@1: Zerotorescue@1: -- Announce Zerotorescue@122: mod.frame:SetStatusText("All required prices and itemcounts have been cached. This process took " .. mceil(GetTime() - cacheStart) .. " seconds."); Zerotorescue@1: Zerotorescue@1: -- Forget time Zerotorescue@1: cacheStart = nil; Zerotorescue@0: end Zerotorescue@0: Zerotorescue@1: function mod:DisplayMoney(value, priceThreshold) Zerotorescue@7: if value == -1 then Zerotorescue@7: return "|cff0000ffNone up|r"; Zerotorescue@7: elseif value == -2 then Zerotorescue@7: return "|cff0000ffNo AH mod|r"; Zerotorescue@9: elseif value == -3 then Zerotorescue@9: return "|cffffff00Unknown|r"; Zerotorescue@13: elseif value == -4 then Zerotorescue@13: return "|cff00ff00-|r"; Zerotorescue@23: elseif value == -5 then Zerotorescue@23: return "|cffff9933Error|r"; Zerotorescue@23: elseif priceThreshold and value < priceThreshold then Zerotorescue@106: return sformat("|cffaaaaaa%s|r", sgsub(addon:ReadableMoney(value or 0, true), "|([a-fA-F0-9]+)([gsc]+)|r", "%2")); Zerotorescue@1: else Zerotorescue@1: return addon:ReadableMoney(value or 0, true); Zerotorescue@1: end Zerotorescue@1: end Zerotorescue@1: Zerotorescue@0: function mod:NumberFormat(num) Zerotorescue@62: local formatted = sgsub(num, "(%d)(%d%d%d)$", "%1,%2", 1); Zerotorescue@122: local matches; Zerotorescue@0: Zerotorescue@0: while true do Zerotorescue@62: formatted, matches = sgsub(formatted, "(%d)(%d%d%d),", "%1,%2,", 1); Zerotorescue@0: Zerotorescue@0: if matches == 0 then Zerotorescue@0: break; Zerotorescue@0: end Zerotorescue@0: end Zerotorescue@0: Zerotorescue@0: return formatted; Zerotorescue@1: end