comparison ObjectiveTracker/ObjectiveTracker.lua @ 28:c33c17dd97e7

file renames
author Nenue
date Wed, 13 Apr 2016 20:19:37 -0400
parents
children adcd7c328d07
comparison
equal deleted inserted replaced
27:c3aa94bc6be2 28:c33c17dd97e7
1 --- ${PACKAGE_NAME}
2 -- @file-author@
3 -- @project-revision@ @project-hash@
4 -- @file-revision@ @file-hash@
5 -- Created: 3/26/2016 1:51 AM
6 local B, _G = select(2,...).frame, _G
7 local pairs, setmetatable, type, tostring, band, format = _G.pairs, _G.setmetatable, _G.type, _G.tostring, bit.band, string.format
8 local ipairs, tinsert, hooksecurefunc = _G.ipairs, _G.tinsert, _G.hooksecurefunc
9 local PlaySoundFile, IsQuestTask, SortQuestWatches, GetCurrentMapAreaID, GetZoneText, GetMinimapZoneText = PlaySoundFile, IsQuestTask, SortQuestWatches, GetCurrentMapAreaID, GetZoneText, GetMinimapZoneText
10 local AddQuestWatch, SetSuperTrackedQuestID, GetNumQuestWatches, AUTO_QUEST_WATCH, MAX_WATCHABLE_QUESTS = AddQuestWatch, SetSuperTrackedQuestID, GetNumQuestWatches, AUTO_QUEST_WATCH, MAX_WATCHABLE_QUESTS
11 local QuestPOIUpdateIcons, GetCVar, IsPlayerInMicroDungeon, WorldMapFrame, GetCVarBool, SetMapToCurrentZone = QuestPOIUpdateIcons, GetCVar, IsPlayerInMicroDungeon, WorldMapFrame, GetCVarBool, SetMapToCurrentZone
12 local AddAutoQuestPopUp = AddAutoQuestPopUp
13 local T = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
14 local print = B.print('Objectives')
15 local ObjectiveTrackerFrame, VeneerObjectiveScroll, CreateFrame = _G.ObjectiveTrackerFrame, _G.VeneerObjectiveScroll, _G.CreateFrame
16 local Wrapper = _G.VeneerObjectiveWrapper
17 local Scroller = VeneerObjectiveWrapper.scrollArea
18 local Scroll = _G.VeneerObjectiveScroll
19 local unitLevel = UnitLevel('player')
20
21 --- Performance values
22 --[[
23 self:RegisterEvent("QUEST_LOG_UPDATE");
24 self:RegisterEvent("TRACKED_ACHIEVEMENT_LIST_CHANGED");
25 self:RegisterEvent("QUEST_WATCH_LIST_CHANGED");
26 self:RegisterEvent("QUEST_AUTOCOMPLETE");
27 self:RegisterEvent("QUEST_ACCEPTED");
28 self:RegisterEvent("SUPER_TRACKED_QUEST_CHANGED");
29 self:RegisterEvent("SCENARIO_UPDATE");
30 self:RegisterEvent("SCENARIO_CRITERIA_UPDATE");
31 self:RegisterEvent("TRACKED_ACHIEVEMENT_UPDATE");
32 self:RegisterEvent("ZONE_CHANGED_NEW_AREA");
33 self:RegisterEvent("ZONE_CHANGED");
34 self:RegisterEvent("QUEST_POI_UPDATE");
35 self:RegisterEvent("VARIABLES_LOADED");
36 self:RegisterEvent("QUEST_TURNED_IN");
37 self:RegisterEvent("PLAYER_MONEY");
38 ]]
39
40
41 --- These are the bitfields used by Blizzard_ObjectiveTracker to determine which segments get parsed.
42 --- They are replicated here so that plugins can make use of any securehook args involving this info.
43 local OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST -- 0x0100
44 local OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP = OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP -- 0x0200
45 local OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE -- 0x0400
46 local OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO = OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO -- 0x0800
47 local OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT -- 0x1000
48
49
50 local OBJECTIVE_TRACKER_UPDATE_STATIC = OBJECTIVE_TRACKER_UPDATE_STATIC -- 0x0000
51 local OBJECTIVE_TRACKER_UPDATE_ALL = OBJECTIVE_TRACKER_UPDATE_ALL -- 0xFFFF
52 local OBJECTIVE_TRACKER_UPDATE_ID = OBJECTIVE_TRACKER_UPDATE_ID -- 0
53
54 local OBJECTIVE_TRACKER_UPDATE_QUEST = OBJECTIVE_TRACKER_UPDATE_QUEST -- 0x0001
55 local OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED = OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED -- 0x0002
56 local OBJECTIVE_TRACKER_UPDATE_TASK_ADDED = OBJECTIVE_TRACKER_UPDATE_TASK_ADDED -- 0x0004
57 local OBJECTIVE_TRACKER_UPDATE_SCENARIO = OBJECTIVE_TRACKER_UPDATE_SCENARIO -- 0x0008
58 local OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE = OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE -- 0x0010
59 local OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT -- 0x0020
60 local OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED -- 0x0040
61 local OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED = OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED -- 0x0080
62
63 local OBJECTIVE_TRACKER_UPDATE_REASON = OBJECTIVE_TRACKER_UPDATE_ALL -- default
64 --- Used to determine which trackers are listening for money events
65
66 T.strings = {}
67 T.strings.CLICK_TO_ACCCEPT = 'Click to Accept'
68 T.strings.CLICK_TO_COMPLETE = 'Click to complete'
69 T.colors ={
70 enable = true,
71 default = {
72 titlebg = {'HORIZONTAL', 1, 0, .7, .25, 1, 0, .7, .125},
73 textbg = {'HORIZONTAL', 0, 0, 0, 0.4, 0, 0, 0, 0 },
74 selectionbg = {'HORIZONTAL', 1, 1, 1, 0, 1, 1, 1, 0.225},
75 },
76 daily = {
77 titlebg = {'HORIZONTAL', 0, .7, 1, .25, 0, 1, .7, .125},
78 textbg = {'HORIZONTAL', 0, .7, 1, .1, 0, 1, .7, .075 },
79 },
80 weekly = {
81 titlebg = {'HORIZONTAL', 0, .35, .7, .25, 0, .35, .7, .125},
82 textbg = {'HORIZONTAL', 0, .35, .7, .1, 0, .35, .7, .075 },
83 },
84 account = {
85 titlebg = {'HORIZONTAL', .1, .1, .1, .25, .1, .1, .1, .125},
86 textbg = {'HORIZONTAL', .1, .1, .1, 0.4, .1, .1, .1, .085 },
87 },
88 -- alliance
89 faction_1 = {
90 titlebg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 },
91 textbg = {'HORIZONTAL', .2, .4, 1, 0.4, .2, .4, 1, .085 },
92 },
93 -- horde
94 faction_2 = {
95 titlebg = {'HORIZONTAL', .6, 0, 0.4, 0.4, .6, 0, 0.4, .085 },
96 textbg = {'HORIZONTAL', .6, 0, 0.4, 0.4, .6, 0, 0.4, .085 },
97 }
98 }
99
100 T.watchMoneyReasons = 0
101
102 --- Baseline defaults table; values defined in the files that they pertain to
103 T.defaults = {}
104
105 --- Tracker display order
106 T.orderedNames = {'Bonus', 'AutoQuest', 'Quest', 'Cheevs'}
107
108 --- ipairs() argument tables
109 T.orderedHandlers = setmetatable({}, {__mode = "k"})
110 T.orderedTrackers = setmetatable({}, {__mode = "k"})
111 T.indexedTrackers = setmetatable({}, {__mode = "k"})
112
113 --- pairs() argument tables
114 T.namedTrackers = setmetatable({}, {__mode = "k"})
115
116 local WRAPPER_ANCHOR_POINT = 'TOPRIGHT'
117 local WRAPPER_OFFSET_X = 0
118 local WRAPPER_OFFSET_Y = -200
119 local WRAPPER_MAX_HEIGHT = 670
120 local WRAPPER_WIDTH = 280
121 local WRAPPER_HEADER_HEIGHT = 24
122
123 T.defaults.Wrapper = {
124 AnchorPoint = WRAPPER_ANCHOR_POINT,
125 OffsetX = WRAPPER_OFFSET_X,
126 OffsetY = WRAPPER_OFFSET_Y,
127 Height = WRAPPER_MAX_HEIGHT,
128 Width = WRAPPER_WIDTH,
129 HeaderHeight = WRAPPER_HEADER_HEIGHT,
130 TextSpacing = 3,
131 TitleSpacing = 3,
132 }
133
134
135
136 --- Tracker module definitions begin here; innards dealing with data retreival and output are defined further in
137 T.DefaultHandler = {
138 previousHeight = 0,
139
140 name = "temp",
141 displayName = "temp",
142 updateReasonModule = 0xFF00,
143 updateReasonEvent = 0x00FF,
144
145 numWatched = 0, --- number of entries being handled
146 numBlocks = 0, --- number of blocks created
147 actualBlocks = 0, --- number of blocks in use
148
149 freeBlocks = {}, --- block heap
150 usedBlocks = {},
151
152 Info = {}, -- find data by ID
153 BlockInfo = {}, -- find data by block ID
154 Watched = {}, -- find watchIndex by data ID
155 WatchInfo = {}, -- find data by watch index
156 WatchBlock = {}, -- find block by watch index
157 }
158
159 T.AutoQuest = {
160 name = "AutoQuest",
161 displayName = "Notice",
162 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST,
163 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED,
164 }
165 T.Quest = {
166 name = "Quest",
167 displayName = "Quests",
168 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST,
169 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED,
170 itemButtons = {},
171 freeButtons = {},
172 }
173 T.Cheevs = {
174 name = "Cheevs",
175 displayName = "Achievements",
176 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_ACHIEVEMENT,
177 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT +
178 OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED,
179 }
180 T.Bonus = {
181 name = "Bonus",
182 displayName = "Bonus Objectives",
183 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE,
184 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_QUEST + OBJECTIVE_TRACKER_UPDATE_TASK_ADDED
185 }
186
187 T.Scenario = {
188 name = 'Scenario',
189 displayName = 'Scenario Objectives',
190 updateReasonModule = OBJECTIVE_TRACKER_UPDATE_MODULE_SCENARIO,
191 updateReasonEvents = OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE + OBJECTIVE_TRACKER_UPDATE_SCENARIO_BONUS_DELAYED
192 }
193
194 local Tracker_string = function (self)
195 return self.name
196 end
197 local Tracker_call = function (self, reason)
198 self:Update(reason)
199 end
200 local Handler_Initialize = function (self, name, index)
201 local c = T.Conf.Wrapper
202 print('Initializing |cFF00FFFF'..name..'|r module...')
203
204 local handler = setmetatable(T[name] or {}, {
205 __tostring = Tracker_string,
206 __call = Tracker_call
207 })
208 if type(T.orderedHandlers[index]) == 'table' then
209 return T.orderedHandlers[index]
210 end
211
212 print('|cFFFFFF00Acquiring locals')
213 local preset = {}
214 for k, _ in pairs(handler) do
215 preset[k] = true
216 end
217
218
219 print('|cFFFF8800Inheriting')
220 for k, v in pairs(self) do
221 if not handler[k] then
222 if type(v) == 'table' then
223 -- assume all tables to be local data; don't inherit or ref
224 handler[k] = {}
225 else
226 handler[k] = self[k]
227 end
228 print('copying', k)
229 end
230 end
231 print('|cFFFF4400'..tostring(name)..'|r:')
232 for k, v in pairs(handler) do
233 print(format("%32s %8s %s", (preset[k] and '|cFFFFFFFF' or '|cFFFFFF00') .. k .. '|r', type(v), tostring(v)))
234 end
235
236 T[name] = handler
237
238 local trackerName = 'Veneer'..name..'Tracker'
239 local handler = T[name]
240 local frame = CreateFrame('Frame', trackerName, _G.VeneerObjectiveScroll, 'VeneerTrackerTemplate')
241 frame.title:SetText(handler.displayName)
242 frame:SetWidth(c.Width)
243 handler.frame = frame
244 handler.trackerName = trackerName
245 handler.lines = {}
246 T.orderedTrackers[index] = frame
247 T.namedTrackers[name] = frame
248 T.indexedTrackers[handler] = frame
249 print('|cFFFF0088' .. trackerName .. '|r created for |cFF00FFFF' .. handler.displayName .. '|r module')
250
251 T.orderedHandlers[index] = handler
252 return true
253 end
254
255 local Event = {}
256 Event.QUEST_LOG_UPDATE = function()
257 return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST + OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE
258 end
259 Event.QUEST_ACCEPTED = function(questLogIndex, questID)
260 if ( IsQuestTask(questID) ) then
261 return OBJECTIVE_TRACKER_UPDATE_TASK_ADDED, questID
262 else
263 if ( AUTO_QUEST_WATCH == "1" and GetNumQuestWatches() < MAX_WATCHABLE_QUESTS ) then
264 AddQuestWatch(questLogIndex);
265 SetSuperTrackedQuestID(questID);
266 end
267 return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST
268 end
269 end
270
271 Event.QUEST_WATCH_LIST_CHANGED = function(questID, added)
272 if ( added ) then
273 if ( not IsQuestTask(questID) ) then
274 return OBJECTIVE_TRACKER_UPDATE_QUEST_ADDED, questID, added
275 end
276 else
277 return OBJECTIVE_TRACKER_UPDATE_QUEST, questID, added
278 end
279 end
280
281 Event.QUEST_POI_UPDATE = function()
282 QuestPOIUpdateIcons();
283 if ( GetCVar("trackQuestSorting") == "proximity" ) then
284 SortQuestWatches();
285 end
286 return OBJECTIVE_TRACKER_UPDATE_ALL
287 end
288 Event.SUPER_TRACKED_QUEST_CHANGED = function()
289 return OBJECTIVE_TRACKER_UPDATE_QUEST
290 end
291 Event.ZONE_CHANGED = function()
292
293 local inMicroDungeon = IsPlayerInMicroDungeon();
294 if ( inMicroDungeon ~= T.inMicroDungeon ) then
295 if ( not WorldMapFrame:IsShown() and GetCVarBool("questPOI") ) then
296 SetMapToCurrentZone(); -- update the zone to get the right POI numbers for the tracker
297 end
298 --SortQuestWatches();
299 T.inMicroDungeon = inMicroDungeon;
300 end
301 end
302 Event.QUEST_AUTOCOMPLETE = function(questId)
303 AddAutoQuestPopUp(questId, "COMPLETE");
304 return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST + OBJECTIVE_TRACKER_UPDATE_MODULE_AUTO_QUEST_POPUP
305 end
306 Event.SCENARIO_CRITERIA_UPDATE = function()
307 return OBJECTIVE_TRACKER_UPDATE_SCENARIO
308 end
309 Event.SCENARIO_UPDATE = function(newStage)
310 if ( newStage ) then
311 return OBJECTIVE_TRACKER_UPDATE_SCENARIO_NEW_STAGE
312 else
313 return OBJECTIVE_TRACKER_UPDATE_SCENARIO
314 end
315 end
316 Event.TRACKED_ACHIEVEMENT_UPDATE = function()
317 return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT
318 end
319 Event.TRACKED_ACHIEVEMENT_LIST_CHANGED = function(achievementID, added)
320 if ( added ) then
321 return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT_ADDED, achievementID
322 else
323 return OBJECTIVE_TRACKER_UPDATE_ACHIEVEMENT
324 end
325 end
326 Event.ZONE_CHANGED_NEW_AREA = function ()
327 if ( not WorldMapFrame:IsShown() and GetCVarBool("questPOI") ) then
328 SetMapToCurrentZone(); -- update the zone to get the right POI numbers for the tracker
329 end
330 SortQuestWatches();
331 T.currentZoneArea = GetCurrentMapAreaID()
332 print('Updating zone ID to', T.currentZoneArea, '=', GetZoneText(), GetMinimapZoneText())
333
334
335 return OBJECTIVE_TRACKER_UPDATE_TASK_ADDED
336 end
337
338
339 Event.PLAYER_MONEY = function()
340 if T.watchMoneyReasons > 0 then
341 return T.watchMoneyReasons
342 end
343 end
344 Event.CRITERIA_COMPLETE = function()
345 return OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE
346 end
347 Event.QUEST_TURN_IN = function(questID, xp, money)
348 if ( IsQuestTask(questID) ) then
349 T.Bonus:OnTurnIn(questID, xp, money)
350 print('updating bonus modules (code', OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE, ',', questID, xp, money)
351 return OBJECTIVE_TRACKER_UPDATE_MODULE_BONUS_OBJECTIVE, questID, xp, money
352 else
353 return OBJECTIVE_TRACKER_UPDATE_MODULE_QUEST, questID, xp, money
354 end
355 end
356 T.Event = Event
357
358 --- Done once per ui load
359 local BlizzHooks = {
360 ['AddQuestWatch'] = 'AddQuestWatch',
361 ['RemoveQuestWatch'] = 'RemoveQuestWatch',
362 ['AbandonQuest'] = 'AbandonQuest',
363 ['AcknowledgeAutoAcceptQuest'] = 'AcknowledgeAutoAcceptQuest',
364 ['AddAutoQuestPopUp'] = 'AddAutoQuestPopUp',
365 ['RemoveAutoQuestPopUp'] = 'RemoveAutoQuestPopUp',
366 ['AddTrackedAchievement'] = 'AddTrackedAchievement',
367 ['RemoveTrackedAchievement'] = 'RemoveTrackedAchievement',
368 ['SetSuperTrackedQuestID'] = 'SetSuperTrackedQuestID'
369 }
370 local VeneerData
371
372 T.SetWatchMoney = function(watchMoney, reason)
373 if watchMoney then
374 if band(T.watchMoneyReasons, reason) == 0 then
375 T.watchMoneyReasons = T.watchMoneyReasons + reason;
376 end
377 else
378 if band(T.watchMoneyReasons, reason) > 0 then
379 T.watchMoneyReasons = T.watchMoneyReasons - reason;
380 end
381 end
382 end
383 T.animateReasons = 0
384 T.SetAnimate = function(reason)
385 print('comparing', T.animateReasons, reason)
386 if animate then
387 if band(T.animateReasons, reason) == 0 then
388 T.animateReasons = T.animateReasons + reason
389 end
390 else
391 if band(T.animateReasons, reason) > 0 then
392 T.animateReasons = T.animateReasons - reason
393 end
394 end
395 end
396
397 local Play = function(file) if Devian and Devian.InWorkspace() then PlaySoundFile(file) end end
398
399 function T:OnEvent (event, ...)
400 local isHandled
401 print('OnEvent(|cFF00FF00'.. event ..'|r):', ...)
402 local reason, arg1, arg2, arg3
403 if Event[event] then
404 if type(Event[event]) == 'function' then
405 Play([[Interface\Addons\SharedMedia_MyMedia\sound\Info.ogg]])
406 reason, arg1, arg2, arg3 = Event[event](...)
407 elseif type(Event[event]) == 'table' then
408 Play([[Interface\Addons\SharedMedia_MyMedia\sound\Link.ogg]])
409 for i, action in ipairs(Event[event]) do
410 if type(action) == 'function' then
411 reason, arg1, arg2, arg3 = action(event, ...)
412 else
413 reason = action
414 end
415
416 if reason then
417 T:Update(reason, arg1, arg2, arg3)
418 end
419 end
420 else
421 Play([[Interface\Addons\SharedMedia_MyMedia\sound\Heart.ogg]])
422 reason = Event[event]
423 end
424 else
425 Play([[Interface\Addons\SharedMedia_MyMedia\sound\Quack.ogg]])
426 end
427 if reason then
428 T:Update(reason, arg1, arg2, arg3)
429 else
430 print('no reason value returned')
431 Play([[Interface\Addons\SharedMedia_MyMedia\sound\Quack.ogg]])
432 end
433
434 end
435
436
437 function T:OnInitialize()
438 local c = T.Conf.Wrapper
439 VeneerData = _G.VeneerData
440 VeneerData.CallLog = VeneerData.CallLog or {}
441 if not T.isHooked then
442 T.isHooked = true
443 for blizzFunc, veneerFunc in pairs(BlizzHooks) do
444 if T[veneerFunc] then
445 hooksecurefunc(blizzFunc, T[veneerFunc])
446 else
447 hooksecurefunc(blizzFunc, function(...)
448 print('|cFFFF0088securehook('..tostring(blizzFunc)..')|r args:', ...)
449 tinsert(VeneerData.CallLog, {blizzFunc, ...})
450 end)
451 end
452 end
453 end
454
455 T.Conf.TasksLog = T.Conf.TasksLog or {}
456
457 ObjectiveTrackerFrame:UnregisterAllEvents()
458 ObjectiveTrackerFrame:Hide()
459
460
461 for id, name in ipairs(T.orderedNames) do
462 if not T.orderedHandlers[id] then
463 Handler_Initialize(T.DefaultHandler, name, id)
464 end
465 end
466 self:SetSize(c.Width, 40)
467 T.InitializeWidgets()
468 end
469
470 --- Done any time the the minimize button is toggled up
471 function T:OnEnable()
472
473 print(B.Conf.VeneerObjectiveWrapper.enabled)
474 if not B.Conf.VeneerObjectiveWrapper.enabled then
475 return
476 end
477
478 for event, action in pairs(Event) do
479 print('|cFFFF0088listen to', event, 'for action|r', tostring(action))
480 Wrapper:RegisterEvent(event)
481 end
482
483 local c = T.Conf.Wrapper
484
485 Scroller:SetScrollChild(Scroll)
486 Scroller:SetWidth(c.Width)
487 Scroll:SetWidth(c.Width)
488 Scroll:ClearAllPoints()
489 Scroll:SetPoint('TOP', Scroller, 'TOP')
490 self:SetScript('OnEvent', T.OnEvent)
491
492 Scroller:Show()
493
494 local from, target, to, x, y = Wrapper:GetPoint(1)
495 print(from, target:GetName(), to, x,y)
496
497 T:Update()
498
499 -- run once to prime the data structure
500 T.UpdateActionButtons()
501 end
502
503 function T:OnDisable()
504 self:UnregisterAllEvents()
505 Scroller:Hide()
506 end
507