comparison 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
comparison
equal deleted inserted replaced
0:c6ff7ba0e8f6 1:9fff13c08f99
1 local addon = LibStub("AceAddon-3.0"):GetAddon("Inventory"); 1 local addon = LibStub("AceAddon-3.0"):GetAddon("Inventory");
2 local mod = addon:NewModule("Summary", "AceEvent-3.0"); 2 local mod = addon:NewModule("Summary", "AceEvent-3.0", "AceTimer-3.0");
3 3
4 local AceGUI = LibStub("AceGUI-3.0"); 4 local AceGUI = LibStub("AceGUI-3.0");
5 5
6 function mod:OnEnable() 6 function mod:OnEnable()
7 self:RegisterWidgets(); 7 self:RegisterWidgets();
8 8
9 self:BuildMain(); 9 -- Register our own slash commands
10 self:Build(); 10 addon:RegisterSlash(function()
11 mod:BuildMain();
12 mod:Build();
13 end, "s", "sum", "summary");
11 end 14 end
12 15
13 function mod:RegisterWidgets() 16 function mod:RegisterWidgets()
14 -- Register InlineGroupWithButton-widget 17 -- Register InlineGroupWithButton-widget
15 -- This widget adds a button next to the header of an inline group 18 -- This widget adds a button next to the header of an inline group
55 end 58 end
56 59
57 AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion); 60 AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion);
58 end 61 end
59 62
63 local itemsCache = {};
64 local CACHE_ITEMS_TOTAL, CACHE_ITEMS_CURRENT, CACHE_ITEMS_PER_UPDATE = 0, 0, 5;
65 local cacheStart;
66
60 function mod:BuildMain() 67 function mod:BuildMain()
61 local frame = AceGUI:Create("Frame"); 68 LibStub("AceConfigDialog-3.0"):Close("InventoryOptions");
62 frame:SetTitle("Inventory Summary"); 69
63 frame:SetLayout("Fill"); 70 -- Main Window
64 71 mod.frame = AceGUI:Create("Frame");
65 local scrollFrame = AceGUI:Create("ScrollFrame"); 72 mod.frame:SetTitle("Inventory Summary");
66 scrollFrame:SetLayout("Flow"); 73 mod.frame:SetLayout("Fill");
67 74 mod.frame:SetCallback("OnClose", function(widget)
68 frame:AddChild(scrollFrame); 75 AceGUI:Release(widget);
69 76 end);
70 mod.scrollFrame = scrollFrame; 77
71 end 78 -- ScrollFrame child
72 79 mod.scrollFrame = AceGUI:Create("ScrollFrame");
73 local temp = {}; 80 mod.scrollFrame:SetLayout("Flow");
81
82 mod.frame:AddChild(mod.scrollFrame);
83
84 -- Reset items cache
85 table.wipe(itemsCache);
86 end
74 87
75 local sortMethod = "item"; 88 local sortMethod = "item";
76 local sortDirectory = "ASC"; 89 local sortDirectory = "ASC";
77 local function ReSort(subject) 90 local function ReSort(subject)
78 if sortMethod == subject then 91 if sortMethod == subject then
84 97
85 mod:Build(); 98 mod:Build();
86 end 99 end
87 100
88 function mod:Build() 101 function mod:Build()
102 local start = GetTime();
103
89 mod.scrollFrame:ReleaseChildren(); 104 mod.scrollFrame:ReleaseChildren();
90 105
106 -- 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
107 -- This appears to be required for each container we wish to pause, so also do this for the contents
108 mod.scrollFrame:PauseLayout();
109
110 local playerName = UnitName("player");
111
112 -- Go through all our stored groups
91 for groupName, values in pairs(addon.db.global.groups) do 113 for groupName, values in pairs(addon.db.global.groups) do
92 if values.items then 114 local trackAt = (values.trackAtCharacters or (values.trackAtCharacters == nil and addon.db.global.defaults.trackAtCharacters));
115
116 -- Does this group have any items and do we want to track it at this char?
117 if values.items and trackAt[playerName] then
93 -- Get group settings 118 -- Get group settings
94 local stockRequired = values.minimumStock or addon.db.global.defaults.minimumStock; 119 local stockRequired = (values.minimumStock or (values.minimumStock == nil and addon.db.global.defaults.minimumStock));
95 local showWhenBelow = (values.summaryThresholdShow or addon.db.global.defaults.summaryThresholdShow); 120 local showWhenBelow = (values.summaryThresholdShow or (values.summaryThresholdShow == nil and addon.db.global.defaults.summaryThresholdShow));
121 local priceThreshold = (values.priceThreshold or (values.priceThreshold == nil and addon.db.global.defaults.priceThreshold));
122 local hideWhenBelowPriceThreshold = (values.hideFromSummaryWhenBelowPriceThreshold or (values.hideFromSummaryWhenBelowPriceThreshold == nil and addon.db.global.defaults.hideFromSummaryWhenBelowPriceThreshold));
96 123
97 -- Make group container 124 -- Make group container
98 local iGroup = AceGUI:Create("InlineGroupWithButton"); 125 local iGroup = AceGUI:Create("InlineGroupWithButton");
126 iGroup:PauseLayout();
99 iGroup:SetTitle(groupName); 127 iGroup:SetTitle(groupName);
100 iGroup:SetFullWidth(true); 128 iGroup:SetFullWidth(true);
101 iGroup:SetLayout("Flow"); 129 iGroup:SetLayout("Flow");
102 iGroup:MakeButton({ 130 iGroup:MakeButton({
103 name = "Queue", 131 name = "Queue",
106 print(groupName); 134 print(groupName);
107 end, 135 end,
108 }); 136 });
109 137
110 -- Headers 138 -- Headers
139
111 -- Itemlink 140 -- Itemlink
112 local lblItem = AceGUI:Create("InteractiveLabel"); 141 local lblItem = AceGUI:Create("InteractiveLabel");
113 lblItem:SetText("|cfffed000Item|r"); 142 lblItem:SetText("|cfffed000Item|r");
114 lblItem:SetFontObject(GameFontHighlight); 143 lblItem:SetFontObject(GameFontHighlight);
115 lblItem:SetRelativeWidth(0.7); 144 lblItem:SetRelativeWidth(0.7);
119 148
120 -- Current quantity 149 -- Current quantity
121 local lblQuantity = AceGUI:Create("InteractiveLabel"); 150 local lblQuantity = AceGUI:Create("InteractiveLabel");
122 lblQuantity:SetText("|cfffed000Cur.|r"); 151 lblQuantity:SetText("|cfffed000Cur.|r");
123 lblQuantity:SetFontObject(GameFontHighlight); 152 lblQuantity:SetFontObject(GameFontHighlight);
124 lblQuantity:SetRelativeWidth(0.149); 153 lblQuantity:SetRelativeWidth(0.099);
125 lblQuantity:SetCallback("OnClick", function() ReSort("current"); end); 154 lblQuantity:SetCallback("OnClick", function() ReSort("current"); end);
126 155
127 iGroup:AddChild(lblQuantity); 156 iGroup:AddChild(lblQuantity);
128 157
129 -- Required stock 158 -- Required stock
130 local lblStockRequired = AceGUI:Create("InteractiveLabel"); 159 local lblStockRequired = AceGUI:Create("InteractiveLabel");
131 lblStockRequired:SetText("|cfffed000Req.|r"); 160 lblStockRequired:SetText("|cfffed000Req.|r");
132 lblStockRequired:SetFontObject(GameFontHighlight); 161 lblStockRequired:SetFontObject(GameFontHighlight);
133 lblStockRequired:SetRelativeWidth(0.149); 162 lblStockRequired:SetRelativeWidth(0.099);
134 lblStockRequired:SetCallback("OnClick", function() ReSort("percentage"); end); 163 lblStockRequired:SetCallback("OnClick", function() ReSort("percentage"); end);
135 164
136 iGroup:AddChild(lblStockRequired); 165 iGroup:AddChild(lblStockRequired);
137 166
138 -- Sort item list 167 -- Lowest value
139 for itemId in pairs(values.items) do 168 local lblValue = AceGUI:Create("InteractiveLabel");
140 local itemName, itemLink, itemRarity = GetItemInfo(itemId); 169 lblValue:SetText("|cfffed000Value|r");
141 170 lblValue:SetFontObject(GameFontHighlight);
142 table.insert(temp, { 171 lblValue:SetRelativeWidth(0.099);
143 id = itemId, 172 lblValue:SetCallback("OnClick", function() ReSort("value"); end);
144 name = itemName, 173
145 link = itemLink, 174 iGroup:AddChild(lblValue);
146 rarity = itemRarity, 175
147 count = addon:GetItemCount(itemId), 176 if not itemsCache[groupName] then
148 }); 177 itemsCache[groupName] = {};
178
179 -- Sort item list
180 for itemId in pairs(values.items) do
181 local itemName, itemLink, itemRarity = GetItemInfo(itemId);
182
183 table.insert(itemsCache[groupName], {
184 id = itemId,
185 name = itemName,
186 link = itemLink,
187 value = 0,--addon:GetAuctionValue(itemLink),
188 rarity = itemRarity,
189 count = 0,--addon:GetItemCount(itemId),
190 set = {},
191 });
192 CACHE_ITEMS_TOTAL = CACHE_ITEMS_TOTAL + 1;
193 end
149 end 194 end
150 195
151 local sortNameFormat = "%d%s"; --rarity .. name 196 table.sort(itemsCache[groupName], function(a, b)
152 table.sort(temp, function(a, b) 197 if sortMethod == "item" and a.rarity == b.rarity then
153 if sortMethod == "item" then 198 -- Do a name-compare for items of the same rarity
154 if sortDirectory == "ASC" then 199 -- Otherwise epics first, then junk
155 return sortNameFormat:format((7 - a.rarity), a.name):upper() < sortNameFormat:format((7 - b.rarity), b.name):upper(); 200 if sortDirectory == "ASC" then
156 else 201 return a.name:upper() < b.name:upper();
157 return sortNameFormat:format((7 - a.rarity), a.name):upper() > sortNameFormat:format((7 - b.rarity), b.name):upper(); 202 else
203 return a.name:upper() > b.name:upper();
204 end
205 elseif sortMethod == "item" then
206 if sortDirectory == "ASC" then
207 return a.rarity > b.rarity; -- the comparers were reversed because we want epics first
208 else
209 return a.rarity < b.rarity; -- the comparers were reversed because we want epics first
158 end 210 end
159 elseif sortMethod == "current" then 211 elseif sortMethod == "current" then
160 if sortDirectory == "ASC" then 212 if sortDirectory == "ASC" then
161 return a.count < b.count; 213 return a.count < b.count;
162 else 214 else
166 if sortDirectory == "ASC" then 218 if sortDirectory == "ASC" then
167 return ( a.count / stockRequired ) < ( b.count / stockRequired ); 219 return ( a.count / stockRequired ) < ( b.count / stockRequired );
168 else 220 else
169 return ( a.count / stockRequired ) > ( b.count / stockRequired ); 221 return ( a.count / stockRequired ) > ( b.count / stockRequired );
170 end 222 end
223 elseif sortMethod == "value" then
224 if sortDirectory == "ASC" then
225 return a.value < b.value;
226 else
227 return a.value > b.value;
228 end
171 end 229 end
172 end); 230 end);
173 231
174 -- Show stuff 232 -- Show stuff
175 for _, item in pairs(temp) do 233 for i, item in pairs(itemsCache[groupName]) do
176 if ( item.count / stockRequired ) < showWhenBelow then 234 if ( item.count / stockRequired ) < showWhenBelow and not (hideWhenBelowPriceThreshold and item.value < priceThreshold) then
177 local btnItemLink = AceGUI:Create("ItemLinkButton"); 235 local btnItemLink = AceGUI:Create("ItemLinkButton");
178 btnItemLink:SetText(item.id); 236 btnItemLink:SetUserData("exec", function()
237 print("Win.");
238 end);
179 btnItemLink:SetRelativeWidth(0.7); 239 btnItemLink:SetRelativeWidth(0.7);
180 btnItemLink:SetCallback("OnEnter", function() end); 240 btnItemLink:SetItemId(item.id);
181 241
182 iGroup:AddChild(btnItemLink); 242 iGroup:AddChild(btnItemLink);
183 243
184 -- Current quantity 244 -- Current quantity
185 local lblQuantity = AceGUI:Create("Label"); 245 local lblQuantity = AceGUI:Create("Label");
186 lblQuantity:SetText(self:ColorCode(item.count, stockRequired)); 246 lblQuantity:SetText(self:ColorCode(item.count, stockRequired));
187 lblQuantity:SetRelativeWidth(0.149); 247 lblQuantity:SetRelativeWidth(0.099);
188 248
189 iGroup:AddChild(lblQuantity); 249 iGroup:AddChild(lblQuantity);
190 250
191 -- Required stock 251 -- Required stock
192 local lblStockRequired = AceGUI:Create("Label"); 252 local lblStockRequired = AceGUI:Create("Label");
193 lblStockRequired:SetText(stockRequired); 253 lblStockRequired:SetText(stockRequired);
194 lblStockRequired:SetRelativeWidth(0.149); 254 lblStockRequired:SetRelativeWidth(0.099);
195 255
196 iGroup:AddChild(lblStockRequired); 256 iGroup:AddChild(lblStockRequired);
257
258 -- Value
259 local lblValue = AceGUI:Create("Label");
260 lblValue:SetText(self:DisplayMoney(item.value, priceThreshold));
261 lblValue:SetRelativeWidth(0.099);
262
263 iGroup:AddChild(lblValue);
264
265 -- Remember references to the value and current fields so we can fill them later
266 if item.set then
267 item.set.value = lblValue;
268 item.set.current = lblQuantity;
269 end
197 end 270 end
198 end 271 end
199 272
200 -- We no longer need this, so forget about it 273 iGroup:ResumeLayout();
201 table.wipe(temp); 274 mod.scrollFrame:AddChild(iGroup); -- this can take up to .5 seconds, might need to look into again at a later time
202
203 mod.scrollFrame:AddChild(iGroup);
204 end 275 end
205 end 276 end
277
278 mod.scrollFrame:ResumeLayout();
279 mod.scrollFrame:DoLayout();
280
281 if CACHE_ITEMS_TOTAL > 0 then
282 cacheStart = GetTime();
283 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)
284 end
285 end
286
287 function mod:UpdateNextItem()
288 local i = 0;
289
290 for groupName, items in pairs(itemsCache) do
291 local minimumStock = addon:GetOptionByKey(groupName, "minimumStock");
292 local priceThreshold = addon:GetOptionByKey(groupName, "priceThreshold");
293
294 for _, item in pairs(items) do
295 if item.set then
296 item.count = addon:GetItemCount(item.id);
297 if item.set.current then
298 item.set.current:SetText(self:ColorCode(item.count, minimumStock));
299 end
300
301 item.value = addon:GetAuctionValue(item.link);
302 if item.set.value then
303 item.set.value:SetText(self:DisplayMoney(item.value, priceThreshold));
304 end
305
306 item.set = nil;
307
308 i = i + 1;
309 CACHE_ITEMS_CURRENT = CACHE_ITEMS_CURRENT + 1;
310
311 mod.frame:SetStatusText("Caching auction values and item-counts... " .. floor(CACHE_ITEMS_CURRENT / CACHE_ITEMS_TOTAL * 100) .. "% has already been processed.");
312
313 if i >= CACHE_ITEMS_PER_UPDATE then
314 return;
315 end
316 end
317 end
318 end
319
320 -- Reset trackers
321 CACHE_ITEMS_TOTAL = 0;
322 CACHE_ITEMS_CURRENT = 0;
323
324 -- Rebuild list so hidden items due to too low prices get added
325 self:Build();
326
327 -- Stop timer
328 self:CancelTimer(self.tmrUpdater, true);
329
330 -- Announce
331 mod.frame:SetStatusText("All prices and itemcounts have been cached. This process took " .. ceil(GetTime() - cacheStart) .. " seconds.");
332
333 -- Forget time
334 cacheStart = nil;
206 end 335 end
207 336
208 function mod:ColorCode(num, required) 337 function mod:ColorCode(num, required)
209 local percentage = ( num / required ); 338 local percentage = ( num / required );
210 339
217 elseif percentage >= addon.db.global.defaults.colors.red then 346 elseif percentage >= addon.db.global.defaults.colors.red then
218 return ("|cffff0000%d|r"):format(num); 347 return ("|cffff0000%d|r"):format(num);
219 end 348 end
220 end 349 end
221 350
351 function mod:DisplayMoney(value, priceThreshold)
352 if value < priceThreshold then
353 return ("|cffff0000%s|r"):format(addon:ReadableMoney(value or 0, true));
354 else
355 return addon:ReadableMoney(value or 0, true);
356 end
357 end
358
222 function mod:NumberFormat(num) 359 function mod:NumberFormat(num)
223 local formatted = string.gsub(num, "(%d)(%d%d%d)$", "%1,%2", 1); 360 local formatted = string.gsub(num, "(%d)(%d%d%d)$", "%1,%2", 1);
224 361
225 while true do 362 while true do
226 formatted, matches = string.gsub(formatted, "(%d)(%d%d%d),", "%1,%2,", 1); 363 formatted, matches = string.gsub(formatted, "(%d)(%d%d%d),", "%1,%2,", 1);
230 end 367 end
231 end 368 end
232 369
233 return formatted; 370 return formatted;
234 end 371 end
372
373 --[[
374 No longer used, we're now caching complete item data instead of just AH values.
375 local AuctionValueCache = {};
376 function mod:GetAuctionValue(link)
377 local itemId = addon:GetItemId(link);
378
379 if AuctionValueCache[itemId] then
380 return AuctionValueCache[itemId];
381 else
382 local value = addon:GetAuctionValue(link);
383
384 AuctionValueCache[itemId] = value;
385
386 -- Reset the cache 1 minute after last updating it
387 self:CancelTimer(self.tmrResetCache, true);
388 self.tmrResetCache = self:ScheduleTimer(function()
389 table.wipe(AuctionValueCache);
390
391 mod.frame:SetStatusText("The auction item value cache has been reset.");
392 end, 60);
393 mod.frame:SetStatusText("");
394
395 return value;
396 end
397 end
398 ]]