Mercurial > wow > inventory
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 ]] |