annotate UI.lua @ 98:33bc8baba858

start of a lot of v3 groundwork based on better knowledge of the addon interface: - use of mixin as a lexical center for generated frames - removal of unfinished segments
author Nenue
date Wed, 26 Oct 2016 10:17:43 -0400
parents f6fae1a4c66c
children
rev   line source
Nenue@50 1 --- Devian - UI.lua
Nenue@35 2 -- @file-author@
Nenue@35 3 -- @project-revision@ @project-hash@
Nenue@35 4 -- @file-revision@ @file-hash@
Nenue@35 5 -- Created: 12/27/2015 3:01 AM
Nenue@35 6 if not LibStub then
Nenue@35 7 print('Something has happened...')
Nenue@35 8 end
Nenue@66 9 local _, D = ...
Nenue@35 10 local DEVIAN_FRAME = 'DevianConsole'
Nenue@66 11 local insert, tonumber, pairs, concat = tinsert, tonumber, pairs, table.concat
Nenue@66 12 local L = D.L
Nenue@66 13 local print = D.print
Nenue@66 14
Nenue@66 15
Nenue@66 16
Nenue@66 17
Nenue@66 18 local Console_OnMovementChanged = function(self, event)
Nenue@66 19 local db = D.db
Nenue@66 20 if self.enabled then
Nenue@66 21 if event == 'PLAYER_STARTED_MOVING' then
Nenue@66 22 self.moveFade:Stop()
Nenue@66 23 local F1 = self.moveFade.alphaOut
Nenue@66 24 F1:SetFromAlpha(db.movement_fade_from)
Nenue@66 25 F1:SetToAlpha(db.movement_fade_to)
Nenue@66 26 F1:SetDuration(db.movement_fade_time)
Nenue@66 27 self.moveFade:Play()
Nenue@66 28 self:EnableMouse(false)
Nenue@66 29 else
Nenue@66 30 self.moveFade:Stop()
Nenue@66 31 local F1 = self.moveFade.alphaOut
Nenue@66 32 F1:SetToAlpha(db.movement_fade_from)
Nenue@66 33 F1:SetFromAlpha(db.movement_fade_to)
Nenue@66 34 F1:SetDuration(db.movement_fade_time)
Nenue@66 35 self.moveFade:Play()
Nenue@66 36 self:EnableMouse(true)
Nenue@66 37 end
Nenue@66 38 end
Nenue@66 39 end
Nenue@66 40
Nenue@35 41
Nenue@35 42
Nenue@35 43 local function Console_MinMax(self)
Nenue@35 44 end
Nenue@35 45
Nenue@35 46 local function Console_Minimize(self)
Nenue@35 47 end
Nenue@35 48
Nenue@35 49 local function Console_Maximize(self)
Nenue@35 50 self:Save()
Nenue@35 51 end
Nenue@35 52
Nenue@35 53
Nenue@35 54 local function Console_Save(self)
Nenue@70 55 local db = D.currentProfile.channels[self.index]
Nenue@35 56 db.x = self:GetLeft()
Nenue@35 57 db.y = (self:GetTop() - GetScreenHeight())
Nenue@35 58 db.width = self:GetWidth()
Nenue@35 59
Nenue@35 60 if not self.minimized then
Nenue@55 61 db.height = self:GetHeight()
Nenue@35 62 self:SetHeight(db.height)
Nenue@35 63 end
Nenue@35 64
Nenue@35 65 db.dockedTo = self.dockedTo
Nenue@35 66 db.docked = self.docked
Nenue@35 67
Nenue@70 68 db.minimized = self.minimized
Nenue@70 69 db.enabled = self.enabled
Nenue@70 70 db.active = self.active
Nenue@35 71 self:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', db.x, db.y)
Nenue@35 72 self:SetWidth(db.width)
Nenue@35 73 end
Nenue@35 74
Nenue@35 75 --- Brings the console to the front.
Nenue@35 76 -- Frame method used to bring a console frame to the front of the display stack.
Nenue@35 77 local function Console_ToFront(c)
Nenue@35 78 local db = D.db
Nenue@68 79 local profile = D.currentProfile
Nenue@35 80 c:Raise()
Nenue@35 81 c:SetAlpha(db.frontalpha)
Nenue@83 82 c.out.backdrop:SetColorTexture(unpack(db.frontdrop))
Nenue@35 83 c.out.backdrop:SetGradientAlpha(unpack(db.frontgrad))
Nenue@35 84 c.out.backdrop:SetBlendMode(db.frontblend)
Nenue@45 85 c.dropmenu.icon:SetVertexColor(unpack(db.frontheader))
Nenue@45 86 c.title:SetTextColor(unpack(db.frontborder))
Nenue@60 87
Nenue@62 88 --oldprint('changing current toplevel from', db.current_channel, 'to', c.index)
Nenue@68 89 profile.current_channel = c.index
Nenue@35 90
Nenue@62 91 --oldprint('toplevel is now', db.current_channel)
Nenue@60 92 c:Save()
Nenue@60 93
Nenue@60 94
Nenue@50 95 -- update dock buttons
Nenue@93 96 local beacon = c.dockButton
Nenue@50 97 beacon.selected = true
Nenue@58 98 beacon.newMessage = nil
Nenue@93 99 beacon:Update()
Nenue@50 100
Nenue@35 101 for _, part in pairs(c.border) do
Nenue@83 102 part:SetColorTexture(unpack(db.frontborder))
Nenue@35 103 end
Nenue@35 104
Nenue@35 105 for id, bc in pairs(D.console) do
Nenue@35 106 if id ~= c.index then
Nenue@35 107 bc:SetAlpha(db.backalpha)
Nenue@83 108 bc.out.backdrop:SetColorTexture(unpack(db.backdrop))
Nenue@35 109 bc.out.backdrop:SetGradientAlpha(unpack(db.backgrad))
Nenue@35 110 bc.out.backdrop:SetBlendMode(db.backblend)
Nenue@45 111 bc.dropmenu.icon:SetVertexColor(unpack(db.backheader))
Nenue@36 112 bc.title:SetTextColor(unpack(db.backborder))
Nenue@35 113
Nenue@93 114 local beacon = D.dock.usedButtons[bc.index]
Nenue@58 115 beacon.raised = nil
Nenue@58 116 beacon.showName = nil
Nenue@50 117 beacon.selected = nil
Nenue@93 118 beacon:Update()
Nenue@50 119
Nenue@35 120 for _, part in pairs(bc.border) do
Nenue@83 121 part:SetColorTexture(unpack(db.backborder))
Nenue@35 122 end
Nenue@35 123 end
Nenue@35 124 end
Nenue@35 125 end
Nenue@35 126
Nenue@35 127 local function Console_MouseDown(self, button, up)
Nenue@35 128 if button == 'LeftButton' then
Nenue@35 129 if up then
Nenue@35 130 self:StopMovingOrSizing()
Nenue@35 131 elseif self.out.grip:IsMouseOver() then
Nenue@35 132 self:StartSizing()
Nenue@35 133 else
Nenue@35 134 self:StartMoving()
Nenue@35 135 end
Nenue@35 136 else
Nenue@35 137 if up then
Nenue@35 138 self:MinMax()
Nenue@35 139 end
Nenue@35 140 end
Nenue@35 141 end
Nenue@35 142 local function Console_MouseUp(self, button)
Nenue@35 143 return Console_MouseDown(self, button, true)
Nenue@35 144 end
Nenue@35 145
Nenue@35 146
Nenue@35 147 --- Constructs the frame object for a console channel
Nenue@35 148 -- Initializes the console channel at a specified index.
Nenue@35 149 -- Configuration data can be overridden by passing a desired settings table.
Nenue@35 150 -- @param i Numeric index of the channel as it manifests in db.channels
Nenue@35 151 -- @param vars Optional settings table to be used.
Nenue@35 152 local function CreateConsole(i, vars)
Nenue@35 153 local db = D.db
Nenue@35 154 if tonumber(i) == nil or math.floor(i) ~= i then
Nenue@35 155 error('Non-integer index value.')
Nenue@35 156 end
Nenue@35 157 if not vars then
Nenue@35 158 vars = D.channels[i] and D.channels[i] or D.channels[db.primary_channel]
Nenue@35 159 end
Nenue@35 160 local f
Nenue@70 161 f = CreateFrame('Frame', 'DevianChannelFrame' .. i, UIParent, DEVIAN_FRAME)
Nenue@47 162
Nenue@35 163 --@debug@
Nenue@35 164 --print(f:GetName())
Nenue@35 165
Nenue@35 166 --print('create(2)')
Nenue@35 167 for k,v in pairs(vars) do
Nenue@35 168 f[k] = v
Nenue@35 169 --@debug@
Nenue@36 170 --print(' f['..type(k)..' '..tostring(k)..'] = '..type(v)..' '..tostring(v))
Nenue@35 171 end
Nenue@35 172
Nenue@35 173 f:SetPoint('TOPLEFT', UIParent, 'TOPLEFT', vars.x, vars.y)
Nenue@35 174 f:SetSize(vars.width, vars.height)
Nenue@35 175 f:Lower()
Nenue@35 176 f.out:SetFont(db.font, db.fontsize, db.fontoutline)
Nenue@35 177 if (db.current_channel == i) then
Nenue@83 178 f.out.backdrop:SetColorTexture(unpack(db.frontdrop))
Nenue@36 179 f.dropmenu.icon:SetVertexColor(unpack(db.headerfontcolor))
Nenue@36 180 f.title:SetTextColor(unpack(db.headerfontcolor))
Nenue@45 181 f.header:SetAlpha(db.headeralpha)
Nenue@35 182 else
Nenue@83 183 f.out.backdrop:SetColorTexture(unpack(db.backdrop))
Nenue@35 184 end
Nenue@35 185
Nenue@35 186 f.Save = Console_Save
Nenue@35 187 f.Minimize = Console_Minimize
Nenue@35 188 f.Maximize = Console_Maximize
Nenue@35 189 f.MinMax = Console_MinMax
Nenue@35 190 f.ToFront = Console_ToFront
Nenue@35 191 f.Toggle = D.Console_Toggle
Nenue@35 192 f:SetScript('OnMouseDown', Console_MouseDown)
Nenue@35 193 f:SetScript('OnMouseUp', Console_MouseUp)
Nenue@66 194 f.profileID = db.current_profile
Nenue@35 195
Nenue@36 196
Nenue@36 197 UIDropDownMenu_Initialize(f.menuFrame, function()
Nenue@36 198 local info = { {
Nenue@36 199 text= "Close",
Nenue@36 200 value = "OptClose",
Nenue@36 201 func = function ()
Nenue@36 202 f.enabled = nil
Nenue@36 203 f:Hide()
Nenue@36 204 f:Save()
Nenue@38 205 end },--[[
Nenue@36 206 {
Nenue@36 207 text = "Dock",
Nenue@36 208 value = "OptDock",
Nenue@38 209 func = function() print('Dvn', 'docking shenanary') end }]]
Nenue@36 210 }
Nenue@36 211 for _, v in ipairs(info) do
Nenue@36 212 UIDropDownMenu_AddButton(v)
Nenue@36 213 end
Nenue@36 214 end, 'MENU')
Nenue@36 215
Nenue@66 216 if db.movement_fade then
Nenue@66 217 f:RegisterEvent('PLAYER_STARTED_MOVING')
Nenue@66 218 f:RegisterEvent('PLAYER_STOPPED_MOVING')
Nenue@66 219 f:SetScript('OnEvent', Console_OnMovementChanged)
Nenue@66 220 end
Nenue@66 221
Nenue@93 222 f.dockButton = D:GetDockButton(f)
Nenue@93 223
Nenue@47 224
Nenue@35 225 if vars.minimized then
Nenue@35 226 f:Minimize()
Nenue@35 227 else
Nenue@35 228 f:Maximize()
Nenue@35 229 end
Nenue@68 230 if db.enabled then
Nenue@68 231 f.enabled = true
Nenue@35 232 f:Show()
Nenue@35 233 end
Nenue@35 234
Nenue@35 235 return f
Nenue@35 236 end
Nenue@35 237
Nenue@35 238
Nenue@35 239 --- Updates console information and returns the handle of the channel object that was worked on.
Nenue@35 240 -- When key is nil or not a valid handle, a new channel is created using whatever signature can be found in cinfo.
Nenue@35 241 -- The signature can be passed as a string, or as a table entry under the key 'signature'
Nenue@35 242 -- If the signature of a new channel is also a tag, the channel will be added to that tag
Nenue@35 243 -- @param cinfo string signature of a new channel, or a table of config variables to be imposed on the channel
Nenue@35 244 -- @param key string signature or index number of channel to operate on
Nenue@35 245 -- @usage channel = D:SetChannel('new', nil) -- creates a new channel
Nenue@35 246 -- @usage channel = D:SetChannel({x = 200, y = 100}, 4) -- updates channel #4
Nenue@35 247 function D:SetChannel(cinfo, key)
Nenue@66 248 local profile = D.currentProfile
Nenue@35 249 local t_info = {}
Nenue@35 250 local channel, isNew, id, sig, t_id
Nenue@36 251 --@debug@
Nenue@68 252 --print('setchan(0) cinfo, key', cinfo, key)--@end-debug@
Nenue@35 253 -- obtain source data
Nenue@66 254 if tonumber(key) ~= nil and D.channels[key] then
Nenue@35 255 id = tonumber(key)
Nenue@35 256 elseif D.sigID[tostring(key)] then
Nenue@35 257 id = D.sigID[tostring(key)]
Nenue@35 258 else
Nenue@66 259 id = profile.default_channel
Nenue@35 260 isNew = true
Nenue@35 261 end
Nenue@66 262 local dbvars = D.channels[id]
Nenue@35 263 t_id = id -- overridden later if new
Nenue@35 264 t_info.index = t_id --
Nenue@35 265 --@debug@
Nenue@68 266 --print('setchan(1) cinfo, key, id=', cinfo, key, id)--@end-debug@
Nenue@35 267
Nenue@35 268
Nenue@35 269 -- obtain config info
Nenue@35 270 if type(cinfo) == 'string' then
Nenue@35 271 sig = cinfo
Nenue@35 272 cinfo = {signature = sig}
Nenue@35 273 elseif type(cinfo) ~= 'table' then -- stop here if a table wans't passed
Nenue@66 274 error('Expecting table of string as arg1')
Nenue@35 275 elseif cinfo.signature then -- new sig
Nenue@66 276 sig = cinfo.signature
Nenue@35 277 elseif isNew then -- new channel sig
Nenue@66 278 sig = 'Ch'
Nenue@35 279 else -- old sig
Nenue@66 280 sig = D.channels[id].signature
Nenue@35 281 end
Nenue@35 282 t_info.signature = sig
Nenue@35 283 --@debug@
Nenue@68 284 --print('setchan(2) sig,id,isNew=', sig, id, isNew)--@end-debug@
Nenue@35 285
Nenue@35 286 for k,v in pairs(cinfo) do -- allow all cinfo to pass
Nenue@35 287 t_info[k] = v
Nenue@35 288 end
Nenue@35 289
Nenue@35 290 local blocked = { -- ignore these vars:
Nenue@35 291 ['docked'] = true, -- table
Nenue@35 292 ['dockedTo'] = true, -- table-related
Nenue@35 293 ['signature'] = true} -- already determined
Nenue@35 294 for k,v in pairs(dbvars) do
Nenue@35 295 if not t_info[k] and not blocked[k] then -- already set or blocked?
Nenue@70 296 --print('assign', k, '=', v)
Nenue@35 297 t_info[k] = v
Nenue@35 298 end
Nenue@35 299 end
Nenue@35 300 -- new channel overrides
Nenue@35 301 if isNew then
Nenue@72 302 if D.sigID[sig] then -- find a non-clashing signature
Nenue@35 303 local result, i = sig, 1
Nenue@35 304 while D.sigID[result] do
Nenue@35 305 result = sig .. i
Nenue@35 306 i = i + 1
Nenue@35 307 end
Nenue@35 308 t_info.signature = result
Nenue@35 309 end
Nenue@36 310 t_id = self.max_channel + 1
Nenue@35 311 t_info.index = t_id
Nenue@72 312
Nenue@72 313 self.max_channel = t_id
Nenue@35 314 --@debug@
Nenue@68 315 --print('setchan(3a) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@
Nenue@35 316 else
Nenue@35 317 --@debug@
Nenue@68 318 --print('setchan(3b) t_id, isNew, sig, t_info.signature=', t_id, isNew, sig, t_info.signature)--@end-debug@
Nenue@35 319 end
Nenue@35 320
Nenue@35 321 local channel
Nenue@35 322 if not self.console[t_id] then -- create a frame
Nenue@66 323 if isNew then -- position the channel frame
Nenue@66 324 profile.max_channel = t_id
Nenue@66 325 t_info.x = t_info.x + 20
Nenue@66 326 t_info.y = t_info.y - 20
Nenue@66 327 profile.channels[t_id] = t_info
Nenue@66 328 --@debug@
Nenue@68 329 --print('setchan(4a)', 't_id, x, y=', t_id, t_info.x, t_info.y)--@end-debug@
Nenue@66 330 end
Nenue@66 331 channel = CreateConsole(t_id, t_info)
Nenue@66 332 self.console[t_id] = channel
Nenue@66 333 self.sig[t_info.signature] = channel
Nenue@66 334 self.sigID[t_info.signature] = t_id
Nenue@66 335 self.IDsig[t_id] = t_info.signature
Nenue@35 336 end
Nenue@35 337 channel = self.console[t_id]
Nenue@35 338 if channel.minimized then
Nenue@35 339 channel:Minimize()
Nenue@35 340 else
Nenue@35 341 channel:Maximize()
Nenue@35 342 end
Nenue@35 343
Nenue@55 344 if channel.enabled then -- hide or show last since Min/Max mess with visibility
Nenue@70 345 --print('setchan(5a) enable')
Nenue@55 346 channel:Show()
Nenue@60 347 --channel:ToFront()
Nenue@35 348 else
Nenue@68 349 --print('setchan(5a) disable')
Nenue@35 350 channel:Hide()
Nenue@35 351 end
Nenue@35 352 --@debug@
Nenue@68 353 --print('setchan(end); c:IsVisible(), c.enabled, db.enabled=', channel:IsVisible(), channel.enabled, profile.enabled)--@end-debug@
Nenue@35 354 return channel
Nenue@66 355 end
Nenue@66 356
Nenue@66 357 --- Console frame toggler
Nenue@66 358 -- @paramsig [...]
Nenue@66 359 -- @param ... one or more space-seperated channel keys
Nenue@87 360 function D:Console_Toggle(cmd, force)
Nenue@87 361
Nenue@87 362
Nenue@88 363 local search = {}
Nenue@87 364 if cmd then
Nenue@87 365 cmd = tostring(cmd)
Nenue@87 366 local i, j = 0, 0
Nenue@87 367 repeat
Nenue@87 368 i, j = cmd:find("%S+", j+1)
Nenue@87 369 if i and j then
Nenue@87 370 local key = cmd:sub(i, j)
Nenue@87 371 if self.sig[key] then
Nenue@87 372 --print(key, self.sigID[key])
Nenue@87 373 insert(search, self.sigID[key])
Nenue@87 374 elseif self.console[tonumber(key)] then
Nenue@87 375 --print(key, tonumber(key))
Nenue@87 376 insert(search, tonumber(key))
Nenue@87 377 end
Nenue@87 378 end
Nenue@87 379 until not(i or j)
Nenue@87 380 end
Nenue@87 381
Nenue@66 382 local profile = D.currentProfile
Nenue@66 383 local setAll
Nenue@70 384
Nenue@70 385 -- if nothing was found, then do an all toggle
Nenue@66 386 if #search < 1 then
Nenue@70 387 search = self.sigID -- using this since it lists frame ID's
Nenue@66 388 setAll = true
Nenue@66 389 end
Nenue@70 390
Nenue@70 391 -- sort global enable state
Nenue@66 392 if setAll then
Nenue@66 393 --oldprint('setall', setAll)
Nenue@66 394 profile.enabled = (not profile.enabled) and true or nil
Nenue@66 395 if force == 0 then
Nenue@66 396 profile.enabled = nil
Nenue@66 397 end
Nenue@66 398 end
Nenue@66 399
Nenue@70 400 -- sort local enable states: if global enable, apply that change to channel
Nenue@70 401 -- else, channel enable takes precedence
Nenue@66 402 for i, id in pairs(search) do
Nenue@66 403 local c = self.console[id]
Nenue@66 404 if setAll then
Nenue@70 405 c.enabled = profile.enabled
Nenue@66 406 else
Nenue@66 407 c.enabled = (not c.enabled) and true or nil
Nenue@66 408 if force == 0 then
Nenue@66 409 c.enabled = nil
Nenue@66 410 end
Nenue@66 411 end
Nenue@66 412
Nenue@70 413 if c.enabled then
Nenue@70 414 profile.enabled = true
Nenue@66 415 c:Show()
Nenue@70 416 else
Nenue@66 417 c:Hide()
Nenue@66 418 end
Nenue@66 419 c:Save()
Nenue@66 420 end
Nenue@66 421
Nenue@66 422 if setAll then
Nenue@66 423 if profile.enabled then
Nenue@66 424 self:Print('toggled all consoles ON')
Nenue@66 425 if D.console[profile.current_channel] then
Nenue@66 426 D.console[profile.current_channel]:ToFront()
Nenue@66 427 end
Nenue@66 428 else
Nenue@66 429 self:Print('toggled all consoles OFF')
Nenue@66 430 end
Nenue@66 431 else
Nenue@66 432 local result = {}
Nenue@66 433 for i, id in pairs(search) do
Nenue@66 434 result[i] = tostring(id) .. ' = ' .. (self.console[id].enabled and 'ON' or 'OFF')
Nenue@66 435 end
Nenue@66 436 self:Print('toggled: '..concat(result, ', '))
Nenue@66 437 end
Nenue@66 438 end