annotate ObjectiveFrame.lua @ 7:5301c68f28d8

TrackerBlock - use IsModifiedClick function to determine appropriate OnClick actions - handle 'CHATLINK' modifier - handle 'TOGGLEQUESTWATCH' modifier TrackerBlockObjectives - use a generic framework to manage frame creation for various criteria tracker types: - ProgressBar when Blizzard flag data indicates so - skip when Blizzard flag data indicates so - DynamicText otherwise - events related to the criteria are registered in the criteria frame, and unregistered when the frame is hidden, either by destruction of its parent or completion
author Nenue
date Fri, 01 Apr 2016 12:27:05 -0400
parents 589de8ea05b9
children 7923243ae972
rev   line source
Nenue@1 1 --- ${PACKAGE_NAME}
Nenue@1 2 -- @file-author@
Nenue@1 3 -- @project-revision@ @project-hash@
Nenue@1 4 -- @file-revision@ @file-hash@
Nenue@1 5 -- Created: 3/30/2016 12:49 AM
Nenue@1 6 local B = select(2,...).frame
Nenue@2 7 local ipairs, max, min, unpack, floor, pairs, tostring, type = ipairs, max, min, unpack, floor, pairs, tostring, type
Nenue@2 8 local IsResting, UnitXP, UnitXPMax, GetXPExhaustion = IsResting, UnitXP, UnitXPMax, GetXPExhaustion
Nenue@2 9 local UnitLevel, IsQuestWatched, UIParent = UnitLevel, IsQuestWatched, UIParent
Nenue@1 10 local CreateFrame = CreateFrame
Nenue@1 11 local mod = B:RegisterModule("ObjectiveTracker", _G.VeneerObjectiveWrapper, 'BuffFrame')
Nenue@1 12 local print = B.print('Objectives')
Nenue@1 13 --------------------------------------------------------------------
Nenue@1 14 --- Global frame layout
Nenue@1 15 --------------------------------------------------------------------
Nenue@1 16
Nenue@1 17 --- Upvalues
Nenue@2 18 local Wrapper = VeneerObjectiveWrapper
Nenue@1 19 local Scroller = Wrapper.scrollArea
Nenue@2 20 local Scroll = VeneerObjectiveScroll
Nenue@1 21 local orderedHandlers = mod.orderedHandlers
Nenue@1 22 local orderedNames = mod.orderedNames
Nenue@1 23
Nenue@1 24 --- Temp values set during updates
Nenue@1 25 local wrapperWidth, wrapperHeight
Nenue@1 26 local scrollWidth, scrollHeight
Nenue@1 27 local previousBlock
Nenue@1 28 local currentBlock
Nenue@1 29 --- todo: map these into config table when its sorted out
Nenue@6 30 local itemButtonSize, itemButtonSpacing = 36, 1
Nenue@1 31 local titleFont, textFont = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Regular.ttf]]
Nenue@1 32 local titleSize, textSize = 15, 15
Nenue@1 33 local titleOutline, textOutline = "OUTLINE", "OUTLINE"
Nenue@1 34 local titleSpacing, textSpacing = 4, 3
Nenue@1 35 local textIndent = 5
Nenue@1 36 local wrapperMaxWidth, wrapperMaxHeight = 280, 490 -- these are the hard bounds, actual *Height variables are changed
Nenue@2 37 local wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 16, 'NONE'
Nenue@1 38 local headerFont, headerSize, headerHeight = [[Interface\Addons\SharedMedia_MyMedia\font\ArchivoNarrow-Bold.ttf]], 18, 24
Nenue@2 39 local headerOutline, headerColor, headerSpacing = 'OUTLINE', {1,1,1,1}, 2
Nenue@1 40 local wrapperPosition = {'RIGHT', UIParent, 'RIGHT', -84, 0}
Nenue@1 41
Nenue@2 42 --- These are mostly aesthetic choices so it lives here
Nenue@1 43 mod.defaults = {
Nenue@1 44 ObjectiveTrackerAnchor = {'BOTTOM', 'RIGHT'},
Nenue@1 45 ObjectiveTrackerParent = 'DebuffButton',
Nenue@1 46 ObjectiveTrackerSize = {250, 600},
Nenue@1 47 ObjectiveWrapperParent = '',
Nenue@2 48 WrapperStyle = {
Nenue@2 49 Header = {
Nenue@6 50 Background = {Left = '', Right = '', Tile = ''},
Nenue@2 51 BackgroundCrop = {Left = {0, 0.4, 0,1}, Right={0.6,1,0,1}, Tile = {0.4,.6,0,1,}},
Nenue@2 52 BackgroundScale = {Left = 100, Right = 100},
Nenue@2 53 Font = {wrapperHeadFont, wrapperHeadSize, wrapperHeadOutline}
Nenue@2 54 }
Nenue@2 55 },
Nenue@2 56 ObjectiveHeaderStyle = {
Nenue@2 57 Normal = {
Nenue@6 58 Gradient = {MinColor = {.05,.15,0.5,0.7}, MaxColor = {.05,.15,0.5,.35}},
Nenue@2 59 Font = {headerFont, headerSize, headerOutline}, Spacing = headerSpacing,
Nenue@2 60 }
Nenue@2 61 },
Nenue@1 62 ObjectiveTrackerStyle = {
Nenue@1 63 Normal = {
Nenue@1 64 Title = {
Nenue@6 65 Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
Nenue@1 66 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@1 67 },
Nenue@1 68 Text = {
Nenue@6 69 Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
Nenue@1 70 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@1 71 },
Nenue@1 72 },
Nenue@1 73 Super = {
Nenue@1 74 Title = {
Nenue@1 75 Gradient = { MinColor = {0, .7, .6, .8}, MaxColor = {0, .7, .6, 0.2}},
Nenue@1 76 Font = {titleFont, titleSize, titleOutline},
Nenue@1 77 Spacing = titleSpacing, BackgroundFullWidth = true
Nenue@1 78 },
Nenue@1 79 Text = {
Nenue@1 80 Gradient = { MinColor = {0, .7, .6, 0.5}, MaxColor = {0, .7, .6, 0.1} },
Nenue@1 81 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@1 82 },
Nenue@1 83 },
Nenue@1 84 Active = {
Nenue@1 85 Title = {
Nenue@7 86 Gradient = { MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .4}, },
Nenue@1 87 Font = {titleFont, titleSize, titleOutline},
Nenue@1 88 Spacing = titleSpacing,
Nenue@1 89 BackgroundFullWidth = true
Nenue@1 90 },
Nenue@1 91 Text = {
Nenue@7 92 Gradient = { MinColor = {0.2, .4, 1, 1}, MaxColor = {0.2, .4, 1, .2}, },
Nenue@1 93 Font = {textFont, textSize, textOutline},
Nenue@1 94 Spacing = textSpacing,
Nenue@1 95 BackgroundFullWidth = true
Nenue@1 96 }
Nenue@1 97 },
Nenue@1 98 Complete = {
Nenue@1 99 Title = {
Nenue@1 100 Gradient = { MinColor = {0, 1, 0, 0.34}, MaxColor = {0, 1, 0, .17}, },
Nenue@1 101 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@1 102 BackgroundFullWidth = true
Nenue@1 103 },
Nenue@1 104 Text = {
Nenue@1 105 Gradient = { MinColor = {0, 1, 0, .25}, MaxColor = {0, 1, 0, 0.12}, },
Nenue@1 106 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@1 107 BackgroundFullWidth = true
Nenue@1 108 }
Nenue@1 109 },
Nenue@7 110 CheevNormal = {
Nenue@7 111
Nenue@7 112 Title = {
Nenue@7 113 Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
Nenue@7 114 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@7 115 },
Nenue@7 116 Text = {
Nenue@7 117 Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
Nenue@7 118 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@7 119 },
Nenue@7 120 },
Nenue@7 121 CheevComplete = {
Nenue@7 122
Nenue@7 123 Title = {
Nenue@7 124 Gradient = { MinColor = {0.2, .4, 1, 0.45}, MaxColor = {.7, 0, 0.9, .19}},
Nenue@7 125 Font = {titleFont, titleSize, titleOutline}, Spacing = titleSpacing,
Nenue@7 126 },
Nenue@7 127 Text = {
Nenue@7 128 Gradient = { MinColor = {0.2, .4, 1, 0.25}, MaxColor = {.7, 0, 0.9, .12}},
Nenue@7 129 Font = {textFont, textSize, textOutline}, Spacing = textSpacing,
Nenue@7 130 },
Nenue@7 131 }
Nenue@1 132 }
Nenue@1 133 }
Nenue@1 134
Nenue@3 135 local FontBank = {
Nenue@3 136 ['Normal'] = VeneerCriteriaFontNormal,
Nenue@3 137 ['Progress'] = VeneerCriteriaFontProgress,
Nenue@3 138 ['Complete'] = VeneerCriteriaFontComplete,
Nenue@3 139 ['Failed'] = VeneerCriteriaFontFailed,
Nenue@3 140 }
Nenue@3 141
Nenue@2 142 local Scroller_OnShow = function()
Nenue@2 143 Wrapper.watchMoneyReasons = 0;
Nenue@2 144 mod.UpdateWrapper()
Nenue@2 145 mod.SetEvents()
Nenue@2 146 for i, region in ipairs(Wrapper.header) do
Nenue@2 147 region:Show()
Nenue@2 148 end
Nenue@2 149 end
Nenue@2 150
Nenue@2 151 local Scroller_OnHide = function()
Nenue@2 152 local self = Wrapper
Nenue@2 153 Wrapper:UnregisterAllEvents()
Nenue@2 154 Wrapper:SetScript('OnEvent', nil)
Nenue@2 155 for i, region in ipairs(Wrapper.header) do
Nenue@2 156 region:Hide()
Nenue@2 157 end
Nenue@2 158 end
Nenue@2 159
Nenue@2 160 local Scroller_OnMouseWheel = function(self, delta)
Nenue@2 161 local r = Scroll:GetHeight() - Scroller:GetHeight()
Nenue@7 162 local s = B.Conf.ObjectiveScroll - delta * floor(r/5+.5)
Nenue@7 163 local from = self:GetVerticalScroll()
Nenue@2 164 if r == 0 then return end
Nenue@2 165 if s >= r then
Nenue@2 166 s = r
Nenue@2 167 elseif s < 1 then
Nenue@2 168 s = 0
Nenue@2 169 end
Nenue@2 170 self:SetVerticalScroll(s)
Nenue@7 171 B.Conf.ObjectiveScroll = s
Nenue@7 172 print('|cFF00FF00OnMouseWheel', 'from = ', from, 'scroll =', s, ' range =', r, 'current =', self:GetVerticalScroll())
Nenue@2 173
Nenue@6 174 mod.UpdateActionButtons('SCROLLING')
Nenue@2 175 end
Nenue@2 176
Nenue@2 177 local WrapperCloseButton_OnClick = function(self)
Nenue@2 178 if Scroller:IsVisible() then
Nenue@2 179 Scroller:Hide()
Nenue@2 180 else
Nenue@2 181 Scroller:Show()
Nenue@2 182 end
Nenue@2 183 end
Nenue@2 184
Nenue@2 185 mod.InitializeTrackers = function()
Nenue@2 186
Nenue@2 187 local c = mod.defaults.ObjectiveHeaderStyle.Normal
Nenue@2 188 local g1, g2, g3, g4 = unpack(c.Gradient.MinColor)
Nenue@2 189 local h1, h2, h3, h4 = unpack(c.Gradient.MaxColor)
Nenue@2 190
Nenue@2 191 for i, name in ipairs(orderedNames) do
Nenue@2 192 if not mod.orderedHandlers[i] then
Nenue@2 193 if mod.Tracker(name, i) then
Nenue@2 194 local handler = mod[name]
Nenue@2 195
Nenue@2 196 local tracker = CreateFrame('Frame', 'Veneer'..name..'Tracker', Scroll, 'VeneerTrackerTemplate')
Nenue@2 197 tracker.header:SetText(handler.name)
Nenue@2 198 tracker.header:SetHeight(headerHeight)
Nenue@2 199 tracker.header:SetFont(unpack(c.Font))
Nenue@2 200 tracker.header:SetTextColor(unpack(headerColor))
Nenue@2 201
Nenue@2 202 tracker.headerbg:SetGradientAlpha('HORIZONTAL', g1, g2 ,g3, g4, h1, h2, h3, h4)
Nenue@2 203 tracker.headerbg:SetHeight(headerHeight)
Nenue@2 204
Nenue@2 205 handler.Tracker = tracker
Nenue@2 206 mod.orderedTrackers[i] = tracker
Nenue@2 207 mod.namedTrackers[name] = tracker
Nenue@2 208 mod.indexedTrackers[handler] = tracker
Nenue@2 209 print('created new tracker frames for new handler')
Nenue@2 210 end
Nenue@2 211 end
Nenue@2 212 end
Nenue@2 213
Nenue@2 214 Scroller:SetScrollChild(Scroll)
Nenue@2 215 Scroller:SetScript('OnMouseWheel', Scroller_OnMouseWheel)
Nenue@2 216 Scroller:SetScript('OnShow', Scroller_OnShow)
Nenue@2 217 Scroller:SetScript('OnHide', Scroller_OnHide)
Nenue@2 218 Wrapper.close:SetScript('OnClick', WrapperCloseButton_OnClick)
Nenue@2 219 Wrapper:SetPoint(unpack(wrapperPosition))
Nenue@2 220 Scroller_OnShow(Scroller)
Nenue@2 221
Nenue@2 222 mod.UpdateWrapperStyle()
Nenue@2 223 end
Nenue@2 224
Nenue@2 225 mod.InitializeXPTracker = function()
Nenue@2 226 local XPBar = Wrapper.XPBar
Nenue@2 227 if UnitLevel('player') == 100 then
Nenue@2 228 XPBar:Hide()
Nenue@2 229 return
Nenue@2 230 end
Nenue@2 231
Nenue@2 232 --- xp bar
Nenue@6 233 XPBar:SetWidth(wrapperWidth - Wrapper.close:GetWidth())
Nenue@6 234 XPBar.bg:SetAllPoints(XPBar)
Nenue@6 235 XPBar:RegisterEvent('DISABLE_XP_GAIN')
Nenue@6 236 XPBar:RegisterEvent('ENABLE_XP_GAIN')
Nenue@2 237 XPBar:SetScript('OnEvent', mod.UpdateXP)
Nenue@6 238
Nenue@6 239 if not IsXPUserDisabled() then
Nenue@6 240 mod.EnableXP(XPBar)
Nenue@6 241 else
Nenue@6 242 mod.DisableXP(XPBar)
Nenue@6 243 end
Nenue@6 244
Nenue@6 245 mod.UpdateXP(XPBar)
Nenue@2 246 end
Nenue@2 247
Nenue@6 248 mod.EnableXP = function(self)
Nenue@6 249 self:RegisterEvent('PLAYER_XP_UPDATE')
Nenue@6 250 self:RegisterEvent('PLAYER_LEVEL_UP')
Nenue@6 251 self:RegisterEvent('PLAYER_UPDATE_RESTING')
Nenue@6 252 self.bg:SetTexture(0,0,0,.25)
Nenue@6 253 self:Show()
Nenue@6 254 end
Nenue@2 255
Nenue@6 256 mod.DisableXP = function(self)
Nenue@6 257 self:UnregisterEvent('PLAYER_XP_UPDATE')
Nenue@6 258 self:UnregisterEvent('PLAYER_LEVEL_UP')
Nenue@6 259 self:UnregisterEvent('PLAYER_UPDATE_RESTING')
Nenue@6 260 self.bg:SetTexture(0.5,0.5,0.5,0.5)
Nenue@6 261 self:Hide()
Nenue@6 262 end
Nenue@2 263
Nenue@6 264 mod.UpdateXP = function(self, event)
Nenue@6 265 if event == 'DISABLE_XP_GAIN' then
Nenue@6 266 mod.DisableXP(self)
Nenue@6 267 elseif event == 'ENABLE_XP_GAIN' then
Nenue@6 268 mod.EnableXP(self)
Nenue@2 269 end
Nenue@2 270
Nenue@6 271 if not IsXPUserDisabled() then
Nenue@6 272
Nenue@6 273 local xp = UnitXP('player')
Nenue@6 274 local xpmax = UnitXPMax('player')
Nenue@6 275 local rest = GetXPExhaustion()
Nenue@6 276 self.fg:SetWidth((xp/xpmax) * self:GetWidth())
Nenue@6 277 if rest then
Nenue@6 278 self.rested:ClearAllPoints()
Nenue@6 279 if xp == 0 then
Nenue@6 280 self.rested:SetPoint('TOPLEFT', self, 'TOPLEFT', 0, 0)
Nenue@6 281 else
Nenue@6 282 self.rested:SetPoint('TOPLEFT', self.fg, 'TOPRIGHT', 0, 0)
Nenue@6 283 end
Nenue@6 284
Nenue@6 285 if (xp + rest) > xpmax then
Nenue@6 286 self.rested:SetPoint('BOTTOMRIGHT', self, 'BOTTOMRIGHT', 0, 0)
Nenue@6 287 else
Nenue@6 288 self.rested:SetWidth((rest/xpmax) * self:GetWidth())
Nenue@6 289 end
Nenue@6 290 self.rested:SetPoint('BOTTOM', self, 'BOTTOM')
Nenue@6 291 self.rested:Show()
Nenue@2 292 else
Nenue@6 293 self.rested:Hide()
Nenue@2 294 end
Nenue@2 295
Nenue@6 296 if IsResting() then
Nenue@6 297 self.bg:SetTexture(.2,.8,.2,.5)
Nenue@2 298 else
Nenue@6 299 self.bg:SetTexture(0,0,0,.25)
Nenue@2 300 end
Nenue@6 301 self.xpText:SetText(xp .. '/'.. xpmax .. (rest and (' ('..tostring(rest)..')') or ''))
Nenue@2 302 end
Nenue@2 303 end
Nenue@2 304
Nenue@2 305 mod.UpdateReputation = function(self)
Nenue@2 306 end
Nenue@1 307
Nenue@1 308 --- Argument containers
Nenue@1 309 local a1, a2, a3, a4, b1, b2, b3, b4, f1, f2, f3, w1, w2
Nenue@1 310 mod.SetBlockStyle = function(block, name)
Nenue@1 311 -- var names intended to reflect argument order
Nenue@2 312 --@debug@
Nenue@1 313 local c = mod.defaults.ObjectiveTrackerStyle[name]
Nenue@2 314 --@end-debug@
Nenue@2 315 --[===[@non-debug
Nenue@2 316 local c = mod.Conf
Nenue@2 317 --@end-non-debug]===]
Nenue@1 318 a1, a2, a3, a4 = unpack(c.Title.Gradient.MinColor)
Nenue@1 319 b1, b2, b3, b4 = unpack(c.Title.Gradient.MaxColor)
Nenue@1 320 block.titlebg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
Nenue@1 321
Nenue@1 322 a1, a2, a3, a4 = unpack(c.Text.Gradient.MinColor)
Nenue@1 323 b1, b2, b3, b4 = unpack(c.Text.Gradient.MaxColor)
Nenue@1 324 block.bg:SetGradientAlpha('HORIZONTAL', a1, a2, a3, a4, b1, b2, b3, b4)
Nenue@1 325
Nenue@1 326 f1, f2, f3 = unpack(c.Title.Font)
Nenue@1 327 block.title:SetFont(f1, f2, f3)
Nenue@1 328
Nenue@1 329 f1, f2 ,f3 = unpack(c.Text.Font)
Nenue@1 330 block.objectives:SetFont(f1,f2,f3)
Nenue@1 331
Nenue@1 332 w1 = Wrapper:GetWidth()
Nenue@1 333 w2 = (c.Title.BackgroundFullWidth and w1 or block.title:GetStringWidth())
Nenue@1 334
Nenue@1 335 local titleSpacing, titleSpacing2 = c.Title.Spacing, (c.Title.Spacing * 2)
Nenue@1 336 local textSpacing, textSpacing2 = c.Text.Spacing, (c.Text.Spacing * 2)
Nenue@1 337
Nenue@1 338 if block.info.isTrivial then
Nenue@1 339 block.title:SetTextColor(0.7, 0.7, 0.7, 1)
Nenue@1 340 elseif block.info.isComplete then
Nenue@1 341 block.title:SetTextColor(1,1,1,1)
Nenue@1 342 else
Nenue@1 343 block.title:SetTextColor(0,.7,1,1)
Nenue@1 344 end
Nenue@1 345 block.title:SetSpacing(titleSpacing)
Nenue@1 346 block.objectives:SetSpacing(textSpacing)
Nenue@1 347 block.objectives:SetWordWrap(true)
Nenue@1 348
Nenue@7 349 local titleHeight, textHeight = block.title:GetStringHeight(), block.objectives:GetStringHeight() + block.attachmentHeight
Nenue@1 350 local blockHeight = titleHeight + titleSpacing2 + textHeight + textSpacing2
Nenue@1 351 local blockWidth = wrapperMaxWidth
Nenue@1 352
Nenue@1 353 block.titlebg:SetSize(min(w1, w2), titleHeight + titleSpacing2)
Nenue@1 354 block.bg:SetSize(w1, textHeight + textSpacing2)
Nenue@1 355 block:SetSize(blockWidth, blockHeight)
Nenue@1 356
Nenue@1 357 block.title:SetPoint('TOPLEFT', block.titlebg, 'TOPLEFT', 0, -titleSpacing)
Nenue@1 358 block.objectives:SetPoint('TOPLEFT', block.titlebg, 'BOTTOMLEFT', textIndent, -textSpacing)
Nenue@1 359
Nenue@1 360 -- store
Nenue@1 361 block.titleHeight = titleHeight
Nenue@1 362 block.textHeight = textHeight
Nenue@1 363 block.width = blockWidth
Nenue@1 364 block.height = blockHeight
Nenue@1 365
Nenue@2 366 print(' |cFF00FFFF'..block:GetName()..'|r:|cFF0088FFSetStyle|r(', blockWidth, 'x', blockHeight, '(textH', textHeight,', titleH', titleHeight, ')')
Nenue@2 367 end
Nenue@2 368
Nenue@2 369 local segments = {'Left', 'Right', 'Tile'}
Nenue@2 370 mod.UpdateWrapperStyle = function()
Nenue@2 371 local c = mod.defaults.WrapperStyle
Nenue@2 372 for _, segment in ipairs(segments) do
Nenue@2 373 Wrapper['Background'..segment]:SetAtlas(c.Header.Background[segment])
Nenue@2 374 Wrapper['Background'..segment]:SetTexCoord(unpack(c.Header.BackgroundCrop[segment]))
Nenue@2 375 if c.Header.BackgroundScale[segment] then
Nenue@2 376 Wrapper['Background'..segment]:SetWidth(c.Header.BackgroundScale[segment])
Nenue@2 377 end
Nenue@2 378 end
Nenue@1 379 end
Nenue@1 380
Nenue@1 381 --- Updates the selected block frame to display the given info batch
Nenue@1 382 -- If `previousBlock` is set, it will attempt to anchor to that
Nenue@1 383 -- @param blockNum the ordered block to be updated, not a watchIndex value
Nenue@1 384 -- @param info the reference returned by the GetXInfo functions
Nenue@1 385 -- REMEMBER: t.info and questData[questID] are the same table
Nenue@1 386 mod.UpdateTrackerBlock = function (handler, blockIndex, info)
Nenue@2 387 print(' |cFF00FFFFUpdateTrackerBlock('..blockIndex..'|r')
Nenue@1 388 if not blockIndex or not info then
Nenue@1 389 return
Nenue@1 390 end
Nenue@1 391
Nenue@1 392 local tracker = handler.Tracker
Nenue@1 393
Nenue@1 394 local t = handler:GetBlock(blockIndex)
Nenue@1 395 if previousBlock then
Nenue@1 396 if blockIndex == 1 then
Nenue@1 397 t:SetPoint('TOPLEFT', previousBlock, 'TOPLEFT', 0, -headerHeight)
Nenue@1 398 else
Nenue@1 399 t:SetPoint('TOPLEFT', previousBlock, 'BOTTOMLEFT', 0, 0)
Nenue@1 400 end
Nenue@1 401 t:SetPoint('RIGHT', tracker,'RIGHT', 0, 0)
Nenue@1 402 end
Nenue@2 403 --print(t:GetName(), t:GetSize())
Nenue@2 404 --print(t:GetPoint(1))
Nenue@1 405
Nenue@1 406 t.info = info
Nenue@1 407
Nenue@5 408 if info.questID then handler.QuestBlock[info.questID] = t end
Nenue@1 409 if info.questLogIndex then handler.LogBlock[info.questLogIndex] = t end
Nenue@1 410 if info.watchIndex then handler.WatchBlock[info.watchIndex] = t end
Nenue@1 411
Nenue@1 412 info.blockIndex = blockIndex
Nenue@1 413 handler.BlockInfo[blockIndex] = info
Nenue@7 414
Nenue@1 415 t.Select = handler.Select
Nenue@1 416 t.Open = handler.Open
Nenue@1 417 t.Remove = handler.Remove
Nenue@1 418 t.Link = handler.Link
Nenue@1 419 t:SetScript('OnMouseUp', handler.OnMouseUp)
Nenue@1 420 t:SetScript('OnMouseDown', handler.OnMouseDown)
Nenue@1 421 t.title:SetText(info.title)
Nenue@1 422
Nenue@7 423 t.attachmentHeight = 0
Nenue@1 424 if info.isComplete then
Nenue@1 425 t.objectives:Show()
Nenue@1 426 t.objectives:SetText(info.completionText)
Nenue@1 427 elseif info.numObjectives >= 1 then
Nenue@7 428 t.attachmentHeight = textSpacing
Nenue@1 429 t.objectives:Show()
Nenue@2 430 print(' - objective lines:', info.numObjectives, 'can wrap:', t.objectives:CanWordWrap())
Nenue@3 431
Nenue@1 432 local text = ''
Nenue@3 433
Nenue@3 434 --- todo: implement objective displays
Nenue@3 435 -- in an accumulator loop, call upon handler for the appropriate display frame, each defining:
Nenue@3 436 -- * height of whatever display widget is involved in conveying the task
Nenue@3 437 -- * number of non-wrapped text lines to account for line space; may be discarded depending on things
Nenue@3 438 -- * boolean that determines listening for money events or not
Nenue@4 439 t.attachmentHeight, text = mod.UpdateObjectives(t, info, text)
Nenue@3 440
Nenue@1 441 t.objectives:SetText(text)
Nenue@3 442 t.objectives:SetWordWrap(true)
Nenue@1 443
Nenue@1 444
Nenue@1 445
Nenue@1 446 elseif info.description then
Nenue@1 447 t.objectives:SetText(info.description)
Nenue@1 448 t.objectives:SetWordWrap(true)
Nenue@1 449 else
Nenue@1 450 t.objectives:SetText(nil)
Nenue@1 451 end
Nenue@1 452 local style = 'Normal'
Nenue@1 453 if info.isComplete then
Nenue@1 454 style = 'Complete'
Nenue@1 455 elseif info.superTracked then
Nenue@1 456 style = 'Super'
Nenue@1 457 end
Nenue@1 458
Nenue@5 459 if info.specialItem and not info.itemButton then
Nenue@5 460 print(' - |cFF00FFFFgenerating item button for info set')
Nenue@4 461 info.itemButton = mod.SetItemButton(t, info)
Nenue@4 462 else
Nenue@4 463 --info.itemButton = nil
Nenue@4 464 end
Nenue@4 465
Nenue@6 466 if Devian and Devian.InWorkspace() then
Nenue@6 467 t.debugText:Show()
Nenue@6 468 t.debugText:SetText(tostring(blockIndex) .. '\n' .. tostring(info.itemButton and info.itemButton:GetName()))
Nenue@6 469 end
Nenue@6 470
Nenue@3 471 --- metrics are calculated in SetStyle
Nenue@1 472 t:SetStyle(style)
Nenue@3 473 t:Show()
Nenue@1 474
Nenue@3 475 print(' |cFF00FFFF)|r -> ', t, t:GetHeight())
Nenue@1 476 return t
Nenue@1 477 end
Nenue@1 478
Nenue@4 479 mod.UpdateObjectives = function(block, info, text)
Nenue@7 480 local attachmentHeight = block.attachmentHeight
Nenue@7 481 if info.description then
Nenue@7 482 print(' -- has description text:', select('#', info.description), info.description)
Nenue@7 483 text = info.description
Nenue@7 484 end
Nenue@4 485 for o, obj in ipairs(info.objectives) do
Nenue@4 486 --- achievement criteria
Nenue@4 487 if obj.flags then
Nenue@4 488
Nenue@4 489
Nenue@4 490 if bit.band(obj.flags, 0x00000001) > 0 then
Nenue@4 491 obj.type = 'ProgressBar'
Nenue@4 492 elseif bit.band(obj.flags, 0x00000002) then
Nenue@4 493 obj.type = 'Hidden'
Nenue@4 494 obj.widget = nil
Nenue@4 495 else
Nenue@4 496 obj.type = 'Text'
Nenue@4 497 obj.widget = nil
Nenue@4 498 text = text .. ((text == '') and "" or "\n") .. obj.text
Nenue@4 499 end
Nenue@4 500
Nenue@7 501 print('obj.type =', obj.type)
Nenue@7 502 print(' ** qtyStr:', obj.quantityString, 'qty:', obj.quantity, 'assetID:', obj.assetID)
Nenue@7 503 obj.widget = mod.SetWidget(obj, info)
Nenue@4 504 --- none of the above (most quests)
Nenue@4 505 else
Nenue@4 506 local line = obj.text
Nenue@4 507 local color = '00FFFF'
Nenue@4 508 if obj.finished then
Nenue@4 509 color = 'FFFFFF'
Nenue@4 510 elseif obj.type == 'monster' then
Nenue@4 511 color = 'FFFF00'
Nenue@4 512 elseif obj.type == 'item' then
Nenue@4 513 color = '44DDFF'
Nenue@4 514 elseif obj.type == 'object' then
Nenue@4 515 color = 'FF44DD'
Nenue@4 516 end
Nenue@4 517 text = text .. ((text == '') and "" or "\n") .. '|cFF'..color.. line .. '|r'
Nenue@4 518 end
Nenue@4 519
Nenue@4 520 if obj.widget then
Nenue@7 521
Nenue@7 522 obj.widget:Show()
Nenue@7 523 obj.widget:SetPoint('TOPLEFT', block.objectives, 'BOTTOMLEFT', 0, -attachmentHeight)
Nenue@7 524 print('have a widget, height is', obj.widget.height)
Nenue@4 525 attachmentHeight = attachmentHeight + obj.widget.height
Nenue@4 526 end
Nenue@4 527
Nenue@4 528 end
Nenue@4 529 return attachmentHeight, text
Nenue@4 530 end
Nenue@4 531
Nenue@1 532 mod.UpdateTracker = function(handler)
Nenue@1 533 print('|cFF00FF88UpdateTracker(|r|cFFFF4400' .. type(handler) .. '|r :: |cFF88FFFF' .. tostring(handler) .. '|r')
Nenue@1 534 local tracker = handler.Tracker
Nenue@1 535 local blockIndex = 0
Nenue@1 536 local trackerHeight = headerHeight
Nenue@1 537 local w = 300
Nenue@1 538
Nenue@1 539 previousBlock = handler.Tracker
Nenue@1 540 local numWatched = handler.GetNumWatched()
Nenue@1 541 local numBlocks = handler.numBlocks
Nenue@1 542 local actualBlocks = handler.actualBlocks
Nenue@1 543 for watchIndex = 1, 25 do
Nenue@1 544 blockIndex = blockIndex + 1
Nenue@1 545 if watchIndex <= numWatched then
Nenue@1 546 local info = handler:GetInfo(watchIndex)
Nenue@1 547 if info then
Nenue@1 548 local currentBlock = mod.UpdateTrackerBlock(handler, blockIndex, info)
Nenue@1 549 previousBlock = currentBlock
Nenue@1 550 trackerHeight = trackerHeight + currentBlock.height
Nenue@1 551 numBlocks = max(numBlocks, watchIndex)
Nenue@1 552 actualBlocks = actualBlocks + 1
Nenue@1 553 else
Nenue@1 554 print('|cFFFF0000Failed to draw info for index #'..watchIndex)
Nenue@1 555 end
Nenue@1 556
Nenue@1 557 elseif watchIndex <= numBlocks then
Nenue@1 558 local used = handler.usedBlocks
Nenue@1 559 local free = handler.freeBlocks
Nenue@1 560 print('clean up dead quest block')
Nenue@1 561 if used[blockIndex] then
Nenue@1 562 used[blockIndex]:Hide()
Nenue@1 563 used[blockIndex]:ClearAllPoints()
Nenue@1 564 free[#free+1]= used[blockIndex]
Nenue@1 565 used[blockIndex] = nil
Nenue@1 566 end
Nenue@1 567 else
Nenue@1 568 print('Stopping scan at', blockIndex)
Nenue@1 569 break -- done with quest stuff
Nenue@1 570 end
Nenue@1 571 end
Nenue@1 572 handler.numWatched = numWatched
Nenue@1 573 handler.numBlocks = numBlocks
Nenue@1 574 handler.actualBlocks = actualBlocks
Nenue@1 575 handler:Report()
Nenue@1 576 previousBlock = nil
Nenue@1 577 if numBlocks > 0 then
Nenue@1 578 tracker.height = trackerHeight
Nenue@1 579 else
Nenue@1 580 tracker.height = 0
Nenue@1 581 end
Nenue@1 582
Nenue@1 583 print('|cFF00FF88)|r ->', numBlocks, 'blocks; height', tracker.height, 'last block: ')
Nenue@1 584 end
Nenue@1 585
Nenue@1 586 mod.Quest.numButtons = 0
Nenue@1 587 local usedButtons = mod.Quest.itemButtons
Nenue@1 588 local freeButtons = mod.Quest.freeButtons
Nenue@1 589 mod.UpdateWrapper = function()
Nenue@1 590 wrapperWidth = wrapperMaxWidth
Nenue@1 591 scrollWidth = wrapperWidth
Nenue@1 592 local wrapperBlocks = 0
Nenue@1 593 -- Update scroll child vertical size
Nenue@1 594 scrollHeight = 0
Nenue@1 595 for i, handler in ipairs(orderedHandlers) do
Nenue@1 596 mod.UpdateTracker(handler)
Nenue@1 597 if handler.actualBlocks >= 1 then
Nenue@1 598 local tracker = handler.Tracker
Nenue@1 599 print('setting', handler.Tracker, 'to anchor to offset', -scrollHeight)
Nenue@1 600 tracker:SetParent(Scroll) -- this doesn't do anything that relativeTo doesn't
Nenue@1 601 tracker:SetPoint('TOPLEFT', Scroll, 'TOPLEFT', 0, - scrollHeight)
Nenue@1 602 tracker:SetSize(wrapperWidth, tracker.height)
Nenue@1 603 print('adding ', tracker.height)
Nenue@1 604 scrollHeight = scrollHeight + tracker.height
Nenue@1 605 end
Nenue@1 606 wrapperBlocks = wrapperBlocks + handler.actualBlocks
Nenue@1 607 end
Nenue@1 608 print('final scrollHeight:', scrollHeight)
Nenue@1 609
Nenue@1 610
Nenue@1 611
Nenue@1 612 -- Update frame dimensions
Nenue@1 613 if scrollHeight > wrapperMaxHeight then
Nenue@1 614 print(' is larger than', wrapperMaxHeight)
Nenue@1 615 --ScrollBar:Show()
Nenue@1 616 --scrollWidth = wrapperMaxWidth - scrollBarWidth
Nenue@1 617 wrapperHeight = wrapperMaxHeight
Nenue@1 618 -- Make ThumbTexture reflect the viewing scale (smaller for longer scroll, bigger for shorter)
Nenue@1 619 --ScrollBar:GetThumbTexture():SetHeight((wrapperMaxHeight/scrollHeight) * (wrapperMaxHeight))
Nenue@1 620 --ScrollBar:SetWidth(scrollBarWidth)
Nenue@1 621 --ScrollBar:SetPoint('TOPRIGHT', Scroller, 'TOPRIGHT', 0, 0)
Nenue@1 622 --ScrollBar:SetPoint('BOTTOMLEFT', Scroller, 'BOTTOMRIGHT', -scrollBarWidth, 0)
Nenue@1 623 --ScrollBar:SetMinMaxValues(1, scrollHeight - wrapperMaxHeight)
Nenue@1 624 else
Nenue@1 625 --ScrollBar:Hide()
Nenue@1 626 wrapperHeight = scrollHeight
Nenue@1 627 end
Nenue@1 628 scrollWidth = floor(scrollWidth+.5)
Nenue@1 629 scrollHeight = floor(scrollHeight+.5)
Nenue@1 630 wrapperWidth = floor(wrapperWidth+.5)
Nenue@1 631 wrapperHeight = floor(wrapperHeight+.5)
Nenue@1 632 headerHeight = floor(headerHeight+.5)
Nenue@1 633
Nenue@1 634 if wrapperBlocks >= 1 then
Nenue@2 635 for i, region in ipairs(Wrapper.header) do
Nenue@2 636 region:Show()
Nenue@2 637 end
Nenue@1 638 else
Nenue@2 639 for i, region in ipairs(Wrapper.header) do
Nenue@2 640 region:Hide()
Nenue@2 641 end
Nenue@1 642 return
Nenue@1 643 end
Nenue@1 644 --wrapperHeight = scrollHeight
Nenue@1 645
Nenue@1 646 print('|cFFFFFF00params:|r scroller:', scrollWidth, 'x', scrollHeight)
Nenue@1 647 print('|cFFFFFF00params:|r scroll:', scrollWidth, 'x', scrollHeight)
Nenue@1 648 print('|cFFFFFF00params:|r wrapper:', wrapperWidth, 'x', wrapperHeight)
Nenue@1 649 print('|cFFFFFF00params:|r header:', headerHeight)
Nenue@1 650
Nenue@1 651 Scroller:SetSize(wrapperWidth, wrapperHeight)
Nenue@1 652 Scroller:SetPoint('TOPLEFT', Wrapper, 'TOPLEFT', 0, -headerHeight)
Nenue@1 653 Scroller:SetPoint('BOTTOMRIGHT', Wrapper, 'BOTTOMRIGHT')
Nenue@1 654
Nenue@7 655
Nenue@1 656 Scroll:SetSize(scrollWidth, scrollHeight)
Nenue@7 657 Scroll:SetPoint('TOPLEFT', Scroller, 'TOPLEFT', 0, B.Conf.ObjectiveScroll or 0)
Nenue@1 658 Scroll:SetPoint('RIGHT', Scroller, 'RIGHT')
Nenue@1 659
Nenue@1 660 --Scroller:UpdateScrollChildRect()
Nenue@1 661 Wrapper:SetSize(wrapperWidth, wrapperHeight + headerHeight)
Nenue@1 662
Nenue@1 663 -- update action buttons
Nenue@6 664 print('|cFF00FF00'..Scroll:GetName()..'|r:', Scroll:GetWidth(), Scroll:GetHeight(),
Nenue@6 665 '|cFF00FF00'..Scroller:GetName()..'|r:', Scroller:GetWidth(), Scroller:GetHeight(),
Nenue@6 666 '|cFF00FF00'..Wrapper:GetName()..'|r:', Wrapper:GetWidth(), Wrapper:GetHeight(),
Nenue@6 667 '|cFF0088FFvScrollRange|r:', floor(Scroller:GetVerticalScrollRange()+.5)
Nenue@6 668 )
Nenue@6 669 mod.UpdateActionButtons('FULL_UPDATE')
Nenue@1 670
Nenue@6 671 QuestPOIUpdateIcons()
Nenue@1 672 end
Nenue@1 673
Nenue@1 674 --- Queue any active item buttons for update for that frame
Nenue@6 675 mod.UpdateActionButtons = function(updateReason)
Nenue@6 676 Scroller.snap_upper = 0
Nenue@6 677 Scroller.snap_lower = 0
Nenue@6 678 local print = B.print('ItemButton')
Nenue@6 679 if updateReason then
Nenue@6 680 print = B.print('IB_'..updateReason)
Nenue@6 681 end
Nenue@6 682
Nenue@1 683 local previousItem
Nenue@2 684 for questID, itemButton in pairs(usedButtons) do
Nenue@6 685 local info= mod.Quest.Info[questID]
Nenue@6 686
Nenue@5 687 print('|cFF00FFFF'.. questID .. '|r', itemButton:GetName())
Nenue@5 688 local block = mod.Quest.QuestBlock[questID]
Nenue@1 689 if block then
Nenue@5 690 -- Dispatch the probe
Nenue@6 691 if IsQuestWatched(info.questLogIndex) then
Nenue@6 692 itemButton.previousItem = previousItem
Nenue@5 693 print(' |cFFFFFF00probing', block:GetName())
Nenue@1 694 block:SetScript('OnUpdate', function()
Nenue@5 695 if block:GetBottom() and not InCombatLockdown() then
Nenue@5 696 print(' '..block:GetName()..' |cFF00FF00probe hit!')
Nenue@6 697 mod.UpdateBlockAction(block, itemButton, itemButton.previousItem) -- needs to be previousItem from this scope
Nenue@5 698 block:SetScript('OnUpdate', nil)
Nenue@5 699 end
Nenue@5 700 end)
Nenue@6 701 previousItem = itemButton
Nenue@1 702 else
Nenue@5 703 print('hidden block or unwatched quest')
Nenue@6 704 itemButton.previousItem = nil
Nenue@5 705 itemButton:Hide()
Nenue@1 706 end
Nenue@5 707 else
Nenue@5 708 print(' |cFFFF0088missing block data', itemButton:GetName())
Nenue@6 709 itemButton.previousItem = nil
Nenue@6 710 itemButton:Hide()
Nenue@1 711 end
Nenue@1 712 end
Nenue@1 713 end
Nenue@1 714
Nenue@6 715 mod.UpdateBlockAction = function (block, itemButton)
Nenue@5 716 print('**|cFF0088FF'..itemButton:GetName(), '|r:Update()')
Nenue@5 717 if itemButton.questID ~= block.info.questID then
Nenue@5 718 print('** |cFFFF0088mismatched block assignment', itemButton.questID,'<~>', block.info.questID)
Nenue@6 719 -- something happened between this and last frame, go back and set new probes
Nenue@5 720 return mod.UpdateActionButtons()
Nenue@2 721 end
Nenue@2 722
Nenue@6 723 local previousItem = itemButton.previousItem
Nenue@6 724 local upper_bound = Scroller:GetTop() + Scroller.snap_upper
Nenue@6 725 local lower_bound = Scroller:GetBottom() + Scroller.snap_lower + itemButtonSize
Nenue@6 726 local point, anchor, relative
Nenue@6 727
Nenue@6 728 if block:GetBottom() < lower_bound then
Nenue@6 729 print('** ',block:GetName() ,'|cFFFFFF00bottom =', floor(block:GetBottom()+.5), 'threschold =', floor(lower_bound+.5))
Nenue@1 730 if previousItem then
Nenue@6 731 print('adjusting', previousItem:GetName())
Nenue@1 732 previousItem:ClearAllPoints()
Nenue@6 733 previousItem:SetPoint('BOTTOM', itemButton, 'TOP', 0, itemButtonSpacing)
Nenue@1 734 end
Nenue@1 735 itemButton:ClearAllPoints()
Nenue@6 736 itemButton.x = Wrapper:GetLeft() -4
Nenue@6 737 itemButton.y = Wrapper:GetBottom()
Nenue@6 738 point, anchor, relative = 'BOTTOMRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@6 739 Scroller.snap_lower = Scroller.snap_lower + itemButtonSize + itemButtonSpacing
Nenue@6 740
Nenue@6 741 elseif block:GetTop() > upper_bound then
Nenue@6 742 print('** ',block:GetName() ,'|cFFFFFF00top =', floor(block:GetTop()+.5), 'threschold =', floor(upper_bound+.5))
Nenue@6 743 itemButton:ClearAllPoints()
Nenue@6 744 if previousItem then
Nenue@6 745 print('latch onto another piece')
Nenue@6 746 point, anchor, relative ='TOP', previousItem, 'BOTTOM'
Nenue@6 747 itemButton.x = 0
Nenue@6 748 itemButton.y = -itemButtonSpacing
Nenue@6 749 else
Nenue@6 750 print('latch at corner', Scroller:GetLeft() -itemButtonSpacing, Scroller:GetTop())
Nenue@6 751 point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@6 752 itemButton.x = Scroller:GetLeft() -4
Nenue@6 753 itemButton.y = Scroller:GetTop()
Nenue@6 754 end
Nenue@1 755 itemButton:Show()
Nenue@6 756 Scroller.snap_upper = Scroller.snap_upper - (itemButtonSize + itemButtonSpacing)
Nenue@1 757 else
Nenue@6 758 print('** ',block:GetName() ,'|cFF00FF00span =', floor(block:GetBottom()+.5), floor(block:GetTop()+.5), 'threschold =', floor(lower_bound+.5))
Nenue@1 759 itemButton:ClearAllPoints()
Nenue@6 760 itemButton.x = block:GetLeft() - itemButtonSpacing
Nenue@6 761 itemButton.y = block:GetTop()
Nenue@6 762 point, anchor, relative = 'TOPRIGHT', UIParent, 'BOTTOMLEFT'
Nenue@1 763 end
Nenue@6 764
Nenue@6 765 itemButton:SetPoint(point, anchor, relative, itemButton.x, itemButton.y)
Nenue@6 766 itemButton:Show()
Nenue@1 767 end
Nenue@1 768
Nenue@1 769 mod.UpdateItemButtonCooldown = function(button)
Nenue@1 770
Nenue@1 771 end