diff 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 diff
--- a/Summary.lua	Thu Oct 07 17:17:43 2010 +0200
+++ b/Summary.lua	Fri Oct 08 16:11:59 2010 +0200
@@ -1,13 +1,16 @@
 local addon = LibStub("AceAddon-3.0"):GetAddon("Inventory");
-local mod = addon:NewModule("Summary", "AceEvent-3.0");
+local mod = addon:NewModule("Summary", "AceEvent-3.0", "AceTimer-3.0");
 
 local AceGUI = LibStub("AceGUI-3.0");
 
 function mod:OnEnable()
 	self:RegisterWidgets();
 	
-	self:BuildMain();
-	self:Build();
+	-- Register our own slash commands
+	addon:RegisterSlash(function()
+		mod:BuildMain();
+		mod:Build();
+	end, "s", "sum", "summary");
 end
 
 function mod:RegisterWidgets()
@@ -57,21 +60,31 @@
 	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()
-	local frame = AceGUI:Create("Frame");
-	frame:SetTitle("Inventory Summary");
-	frame:SetLayout("Fill");
+	LibStub("AceConfigDialog-3.0"):Close("InventoryOptions");
 	
-	local scrollFrame = AceGUI:Create("ScrollFrame");
-	scrollFrame:SetLayout("Flow");
+	-- 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);
 	
-	frame:AddChild(scrollFrame);
+	-- ScrollFrame child
+	mod.scrollFrame = AceGUI:Create("ScrollFrame");
+	mod.scrollFrame:SetLayout("Flow");
 	
-	mod.scrollFrame = scrollFrame;
+	mod.frame:AddChild(mod.scrollFrame);
+	
+	-- Reset items cache
+	table.wipe(itemsCache);
 end
 
-local temp = {};
-
 local sortMethod = "item";
 local sortDirectory = "ASC";
 local function ReSort(subject)
@@ -86,16 +99,31 @@
 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
-		if values.items then
+		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 addon.db.global.defaults.minimumStock;
-			local showWhenBelow = (values.summaryThresholdShow or addon.db.global.defaults.summaryThresholdShow);
+			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");
@@ -108,6 +136,7 @@
 			});
 			
 			-- Headers
+			
 			-- Itemlink
 			local lblItem = AceGUI:Create("InteractiveLabel");
 			lblItem:SetText("|cfffed000Item|r");
@@ -121,7 +150,7 @@
 			local lblQuantity = AceGUI:Create("InteractiveLabel");
 			lblQuantity:SetText("|cfffed000Cur.|r");
 			lblQuantity:SetFontObject(GameFontHighlight);
-			lblQuantity:SetRelativeWidth(0.149);
+			lblQuantity:SetRelativeWidth(0.099);
 			lblQuantity:SetCallback("OnClick", function() ReSort("current"); end);
 			
 			iGroup:AddChild(lblQuantity);
@@ -130,31 +159,54 @@
 			local lblStockRequired = AceGUI:Create("InteractiveLabel");
 			lblStockRequired:SetText("|cfffed000Req.|r");
 			lblStockRequired:SetFontObject(GameFontHighlight);
-			lblStockRequired:SetRelativeWidth(0.149);
+			lblStockRequired:SetRelativeWidth(0.099);
 			lblStockRequired:SetCallback("OnClick", function() ReSort("percentage"); end);
 			
 			iGroup:AddChild(lblStockRequired);
 			
-			-- Sort item list
-			for itemId in pairs(values.items) do
-				local itemName, itemLink, itemRarity = GetItemInfo(itemId);
+			-- 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] = {};
 				
-				table.insert(temp, {
-					id = itemId,
-					name = itemName,
-					link = itemLink,
-					rarity = itemRarity,
-					count = addon:GetItemCount(itemId),
-				});
+				-- 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
 			
-			local sortNameFormat = "%d%s"; --rarity .. name
-			table.sort(temp, function(a, b)
-				if sortMethod == "item" then
+			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 sortNameFormat:format((7 - a.rarity), a.name):upper() < sortNameFormat:format((7 - b.rarity), b.name):upper();
+						return a.name:upper() < b.name:upper();
 					else
-						return sortNameFormat:format((7 - a.rarity), a.name):upper() > sortNameFormat:format((7 - b.rarity), b.name):upper();
+						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
@@ -168,41 +220,118 @@
 					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 _, item in pairs(temp) do
-				if ( item.count / stockRequired ) < showWhenBelow then
+			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:SetText(item.id);
+					btnItemLink:SetUserData("exec", function()
+						print("Win.");
+					end);
 					btnItemLink:SetRelativeWidth(0.7);
-					btnItemLink:SetCallback("OnEnter", function() end);
+					btnItemLink:SetItemId(item.id);
 					
 					iGroup:AddChild(btnItemLink);
 					
 					-- Current quantity
 					local lblQuantity = AceGUI:Create("Label");
 					lblQuantity:SetText(self:ColorCode(item.count, stockRequired));
-					lblQuantity:SetRelativeWidth(0.149);
+					lblQuantity:SetRelativeWidth(0.099);
 					
 					iGroup:AddChild(lblQuantity);
 					
 					-- Required stock
 					local lblStockRequired = AceGUI:Create("Label");
 					lblStockRequired:SetText(stockRequired);
-					lblStockRequired:SetRelativeWidth(0.149);
+					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
 			
-			-- We no longer need this, so forget about it
-			table.wipe(temp);
-	
-			mod.scrollFrame:AddChild(iGroup);
+			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)
@@ -219,6 +348,14 @@
 	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);
 	
@@ -231,4 +368,31 @@
 	end
 	
 	return formatted;
-end
\ No newline at end of file
+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
+]]
\ No newline at end of file