comparison Devian.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 7d94df3804a7
comparison
equal deleted inserted replaced
97:34131d11e61b 98:33bc8baba858
9 DEVIAN_PNAME = 'Dvn' 9 DEVIAN_PNAME = 'Dvn'
10 DEVIAN_PID = 0 10 DEVIAN_PID = 0
11 11
12 local ADDON, D = ... 12 local ADDON, D = ...
13 local MAJOR, MINOR = 'Devian-2.0', 'r@project-revision@' 13 local MAJOR, MINOR = 'Devian-2.0', 'r@project-revision@'
14 local D = LibStub("AceAddon-3.0"):NewAddon(D, "Devian", "AceConsole-3.0", "AceEvent-3.0") 14 local D_INITIALIZED
15 local L = D.L 15 local next = next
16 Devian = D
17 local sub, GetTime, print, _G = string.sub, GetTime, print, _G 16 local sub, GetTime, print, _G = string.sub, GetTime, print, _G
18 local format, setmetatable, getprinthandler, setprinthandler = string.format, setmetatable, getprinthandler, setprinthandler 17 local format, setmetatable, getprinthandler, setprinthandler = string.format, setmetatable, getprinthandler, setprinthandler
19 local tinsert, tremove, rawset = tinsert, tremove, rawset 18 local tinsert, tremove, rawset = tinsert, tremove, rawset
20 local currentProfile 19 local currentProfile
21 local playerName = UnitName("player") 20 local playerName = UnitName("player")
22 local playerRealm = playerName .. '-' .. GetRealmName() 21 local playerRealm = playerName .. '-' .. GetRealmName()
23 local num_dock_tabs = 0 22 local num_dock_tabs = 0
24 local charStates ={} 23 local charStates ={}
25 24
25 local registeredTags = {}
26
27
28 DevianCore = {}
29
30 function DevianCore:OnLoad ()
31 self:RegisterEvent('ADDON_LOADED')
32 self:RegisterEvent('PLAYER_LOGIN')
33 self:SetShown(true)
34 end
35
36 function DevianCore:OnEvent(event, arg)
37 if event == 'ADDON_LOADED' or event == 'PLAYER_LOGIN' then
38 --print(event, arg, DevianDB)
39 if (arg == 'Devian') and not D_INITIALIZED then
40 D_INITIALIZED = true
41 self:Initialize()
42 self:UnregisterAllEvents()
43 end
44 end
45 end
46
26 DevianLoadMessage = setmetatable({}, { 47 DevianLoadMessage = setmetatable({}, {
27 __call = function(t, msg) 48 __call = function(t, msg)
28 rawset(t, #t+1, msg) 49 rawset(t, #t+1, msg)
29 end, 50 end,
30 __index = function(t) 51 __index = function(t)
35 --@debug@ 56 --@debug@
36 D.debugmode = true 57 D.debugmode = true
37 --@end-debug@ 58 --@end-debug@
38 D.print = function(...) 59 D.print = function(...)
39 if currentProfile and not currentProfile.workspace then 60 if currentProfile and not currentProfile.workspace then
40 return 61 return nop
41 end 62 end
42 63
43 if D.debugmode then 64 if D.debugmode then
44 return print('Dvn', ...) 65 return print('Dvn', ...)
45 else 66 else
48 end 69 end
49 local print = D.print 70 local print = D.print
50 71
51 D.L = setmetatable({}, { 72 D.L = setmetatable({}, {
52 __index= function(t,k) 73 __index= function(t,k)
53 return k 74 return tostring(k)
54 end, 75 end,
55 __call = function(t,k,...) 76 __call = function(t,k,...)
56 return format((t[k] or k) , ...) 77 return format((t[k]) , ...)
57 end 78 end
58 }) 79 })
59 D:SetDefaultModuleState(false)
60 D.oldprint = getprinthandler() 80 D.oldprint = getprinthandler()
61 if not _G.oldprint then _G.oldprint = D.oldprint end 81 if not _G.oldprint then _G.oldprint = D.oldprint end
62 82
63 local pairs, tostring, tonumber, ipairs, type = pairs, tostring, tonumber, ipairs, type 83 local pairs, tostring, tonumber, ipairs, type = pairs, tostring, tonumber, ipairs, type
64 local max, rand, format, print = max, math.random, string.format, print 84 local max, rand, format, print = max, math.random, string.format, print
65 local insert, wipe, concat = table.insert, table.wipe, table.concat 85 local insert, wipe, concat = table.insert, table.wipe, table.concat
66 local select, unpack = select, unpack 86 local select, unpack = select, unpack
67 local GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn = GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn 87 local GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn = GetNumAddOns, GetAddOnInfo, GetAddOnEnableState, EnableAddOn
68 local UnitName, DisableAddOn = UnitName, DisableAddOn 88 local UnitName, DisableAddOn = UnitName, DisableAddOn
69 89
70 local db 90 local db, L
71 local defaults = { 91 local defaults = {
72 global = {{}, {}}, 92 global = {{}, {}},
73 default_channel = { 93 default_channel = {
74 signature = 'Main', 94 signature = 'Main',
75 x = 100, y = 800, 95 x = 100, y = -200,
76 height = 500, width = 600, 96 height = 500, width = 600,
77 enabled = true}, 97 enabled = true},
78 current_profile = 1, 98 current_profile = 1,
79 main_profile = 1, 99 main_profile = 1,
80 last_profile = 1, 100 last_profile = 1,
147 enabled = true, -- allow enabled consoles to appear 167 enabled = true, -- allow enabled consoles to appear
148 channels = { 168 channels = {
149 { 169 {
150 index = 1, 170 index = 1,
151 signature = 'Main', 171 signature = 'Main',
152 x = 100, y = 800, 172 x = 100, y = -200,
153 height = 500, width = 600, 173 height = 500, width = 600,
154 enabled = true 174 enabled = true
155 } 175 }
156 }, 176 },
157 loadouts = {}, 177 loadouts = {},
182 end 202 end
183 end 203 end
184 end 204 end
185 end 205 end
186 206
207 D.FixProfile = function(forced)
208
209 local numChannels = 0
210 local minChannel = 400
211 local sortedChannels = {}
212 local sortedTags = {}
213 local maxChannel = 0
214 for k,v in pairs(currentProfile.channels) do
215 numChannels = numChannels + 1
216 maxChannel = max(tonumber(k), maxChannel)
217 minChannel = min(tonumber(k), minChannel)
218 tinsert(sortedChannels, v)
219 end
220 if (maxChannel > numChannels) or forced then
221 oldprint('fixing channels data')
222 table.sort(sortedChannels, function(a,b)
223 return (b.index > a.index)
224 end)
225 for i, info in ipairs(sortedChannels) do
226 for tag, tagSet in pairs(currentProfile.tags) do
227 for _, index in pairs(tagSet) do
228 if index == info.index then
229 sortedTags[tag] = sortedTags[tag] or {}
230 sortedTags[tag][i] = i
231 end
232 end
233 end
234
235 info.index = i
236 end
237 currentProfile.channels = sortedChannels
238 currentProfile.tags = sortedTags
239 else
240 minChannel = 2
241 end
242 currentProfile.lastUpdateFix = MINOR
243 end
244
187 D.Profile = function (id, name) 245 D.Profile = function (id, name)
188 246
189 if name and not id and db.profilesName[name] then 247 if name and not id and db.profilesName[name] then
190 id = db.profilesName[name] 248 id = db.profilesName[name]
191 print('ID located by name, |cFF00FF00'..name..'|r is |cFFFFFF00'.. id..'|r') 249 print('ID located by name, |cFF00FF00'..name..'|r is |cFFFFFF00'.. id..'|r')
227 currentProfile.char[playerRealm] = currentProfile.char[playerRealm] or {} 285 currentProfile.char[playerRealm] = currentProfile.char[playerRealm] or {}
228 if currentProfile.workspace then 286 if currentProfile.workspace then
229 DEVIAN_WORKSPACE = true 287 DEVIAN_WORKSPACE = true
230 DEVIAN_PNAME = currentProfile.name 288 DEVIAN_PNAME = currentProfile.name
231 DEVIAN_PID = id 289 DEVIAN_PID = id
290 print('setting phandler')
232 setprinthandler(D.Message) 291 setprinthandler(D.Message)
233 else 292 else
234 DEVIAN_WORKSPACE = false 293 DEVIAN_WORKSPACE = false
235 DEVIAN_PNAME = nil 294 DEVIAN_PNAME = nil
236 print = nop 295 print = nop
237 end 296 end
238 DEVIAN_PID =id 297 DEVIAN_PID =id
298
299
300 -- Attempt to fix bad data
301 --@debug@
302 MINOR = 70100
303 --@end-debug@
304 if (currentProfile.lastUpdateFix or 0) < MINOR then
305 D.FixProfile(true)
306 end
307
239 308
240 D.unlisted = currentProfile.unlisted 309 D.unlisted = currentProfile.unlisted
241 D.channels = currentProfile.channels 310 D.channels = currentProfile.channels
242 D.tags = currentProfile.tags 311 D.tags = currentProfile.tags
243 D.channelinfo = currentProfile.channels 312 D.channelinfo = currentProfile.channels
248 D.sig = {} 317 D.sig = {}
249 D.sigID = {} 318 D.sigID = {}
250 D.IDsig = {} 319 D.IDsig = {}
251 D.dock = _G.DevianDock 320 D.dock = _G.DevianDock
252 D.dock.buttons = D.dock.buttons or {} 321 D.dock.buttons = D.dock.buttons or {}
322
323
253 324
254 return id, name 325 return id, name
255 end 326 end
256 327
257 local targetGlobal, targetChar 328 local targetGlobal, targetChar
448 if globalState ~= 1 then 519 if globalState ~= 1 then
449 charStates[name] = globalState 520 charStates[name] = globalState
450 end 521 end
451 end 522 end
452 523
524 D.UpdateTags = function()
525
526 wipe(registeredTags)
527 for tag, tagSet in pairs(currentProfile.tags) do
528 registeredTags[tag] = registeredTags[tag] or {}
529 for _, id in pairs(tagSet) do
530 if D.console[id] then
531 tinsert(registeredTags[tag], D.console[id])
532 end
533 end
534 end
535 end
536
453 D.Tag = function(self, tag, dest) 537 D.Tag = function(self, tag, dest)
454 local sig 538 local sig
455 if tag ~= nil and dest ~= nil then 539 if tag ~= nil and dest ~= nil then
456 --@debug@ 540 --@debug@
457 --print(tag, dest) 541 --print(tag, dest)
471 --print('2 tag,dest,sig', tag, dest, sig)--@end-debug@ 555 --print('2 tag,dest,sig', tag, dest, sig)--@end-debug@
472 556
473 -- make a new channel? 557 -- make a new channel?
474 local channel 558 local channel
475 if not currentProfile.channels[dest] then 559 if not currentProfile.channels[dest] then
476 dest = D.max_channel + 1 560 dest = #D.channels + 1
477 D:Print(L('New channel created', sig and (dest..':'..sig) or dest )) 561 D:Print(L('New channel created', sig and (dest..':'..sig) or dest ))
478 channel = D:SetChannel(sig or tag,dest) 562 channel = D:GetOrCreateChannel(dest, tag)
479 else 563 else
480 channel = D.channels[dest] 564 channel = currentProfile.channels[dest]
481 end 565 end
482 --@debug@ 566 --@debug@
483 --print('3 tag,dest,channel.sig=',tag, dest, channel.signature)--@end-debug@ 567 --print('3 tag,dest,channel.sig=',tag, dest, channel.signature)--@end-debug@
484 568
485 if not currentProfile.tags[tag] then -- no tag table? 569 if not currentProfile.tags[tag] then -- no tag table?
486 currentProfile.tags[tag] = {} 570 currentProfile.tags[tag] = {}
487 end 571 end
488 572
489 if currentProfile.tags[tag][dest] then -- is tag set? 573 if currentProfile.tags[tag][dest] then -- is tag set?
490 currentProfile.tags[tag][dest] = nil 574 currentProfile.tags[tag][dest] = nil
491 D:Print(L('Tag removed from channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature)) 575 D:Print(L('Tag removed from channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature))
492 else 576 else
493 currentProfile.tags[tag][dest] = dest 577 currentProfile.tags[tag][dest] = dest
494 D:Print(L('Tag added to channel', tag, currentProfile.channels[dest].index, currentProfile.channels[dest].signature)) 578 D:Print(L('Tag added to channel', tag, channel.index, channel.signature))
495 end 579 end
496 D:UpdateDock() 580 D.UpdateTags()
581 DevianDock:Update()
497 else 582 else
498 D:Print(L['Command tag help']) 583 D:Print(L['Command tag help'])
499 end 584 end
500 end 585 end
501 586
545 --- Creates a Devian-style output. 630 --- Creates a Devian-style output.
546 -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print() 631 -- The first argument describes the channel to output on, and the remaining arguments are concatenated in a manner similar to default print()
547 -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint(). 632 -- This becomes the print handler when development mode is active. The original print() function is assigned to oldprint().
548 -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel. 633 -- @param Tag, signature, or numeric index of the channel to output on. Defaults to primary channel.
549 -- @param ... Output contents. 634 -- @param ... Output contents.
550 635 local default_sendq = {}
551 function D.Message(prefix, ...) 636 function D.Message(prefix, ...)
552 if not currentProfile.workspace then 637 if not currentProfile.workspace then
553 return D.oldprint(prefix, ...) 638 return D.oldprint(prefix, ...)
554 end 639 end
640 local print = D.oldprint
555 prefix = tostring(prefix) 641 prefix = tostring(prefix)
556 if prefix == nil then 642 if prefix == nil then
557 prefix = 'nil*' 643 prefix = 'nil*'
558 end 644 end
559 645
560 local sendq = {} 646 local sendq = default_sendq
561 local tag, id, tagged 647 local tag, id, tagged
562 local byName = true 648 local byName = true
563 if D.tags[prefix] then 649
564 for _, id in pairs(D.tags[prefix]) do 650 if registeredTags[prefix] then
565 if D.console[id] then 651 sendq = registeredTags[prefix]
566 sendq[id] = D.console[id] 652 else
567 tagged = true 653 if D.sig[prefix] then
568 end 654 sendq[D.sig[prefix].index] = D.sig[prefix]
569 end 655 elseif not tagged then
570 end 656 sendq[1] = D.console[D.primary_channel]
571 657 end
572 if D.sig[prefix] then 658 end
573 sendq[D.sig[prefix].index] = D.sig[prefix] 659
574 elseif D.console[prefix] then 660
575 sendq[D.console[prefix]] = D.console[prefix]
576 elseif not tagged then
577 sendq[D.primary_channel] = D.console[D.primary_channel]
578 end
579 661
580 -- color me timbers 662 -- color me timbers
581 local pcolor 663 local pcolor
582 if (not db.tagcolor[prefix]) and byName then 664 if (not db.tagcolor[prefix]) and byName then
583 -- numbers, use white 665 -- numbers, use white
623 local message = concat(buffer, ' ') 705 local message = concat(buffer, ' ')
624 for id, channel in pairs(sendq) do 706 for id, channel in pairs(sendq) do
625 if channel.width < 250 then 707 if channel.width < 250 then
626 prefix = sub(prefix, 0,2) 708 prefix = sub(prefix, 0,2)
627 end 709 end
628 --currentProfile.last_channel = channel.index 710 channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8)
629 channel.out:AddMessage('|cFF'.. pcolor..prefix ..'|r ' .. message, 0.8, 0.8, 0.8, nil, nil, prefix, GetTime()) 711 if channel.Dock and not channel.Dock.newMessage then
630 if not D.dock.usedButtons[id].newMessage then 712 channel.Dock.newMessage = true
631 D.dock.usedButtons[id].newMessage = true 713 channel.Dock.caption.pulse:Play()
632 D.dock.usedButtons[id].caption.pulse:Play() 714 channel.Dock:Update()
633 D.dock.usedButtons[id]:Update()
634 end 715 end
635 end 716 end
636 wipe(buffer) 717 wipe(buffer)
637 end 718 end
638 719
680 function D.ConsoleCommand (cmd) 761 function D.ConsoleCommand (cmd)
681 D:Console_Toggle(cmd) 762 D:Console_Toggle(cmd)
682 end 763 end
683 764
684 765
685 function D:OnInitialize() 766 function DevianCore:Initialize()
686 L = D.L 767 L = D.L
687 768
688 -- pull defaults 769 -- pull defaults
689 if not _G.DevianDB then 770 if not DevianDB then
690 _G.DevianDB = defaults 771 DevianDB = defaults
691 end 772 end
773 D.db = _G.DevianDB
692 db = _G.DevianDB 774 db = _G.DevianDB
693 self.db = db
694 775
695 --- 776 ---
696 if #_G.DevianLoadMessage >= 1 then 777 if #_G.DevianLoadMessage >= 1 then
697 for i, msg in ipairs(_G.DevianLoadMessage) do 778 for i, msg in ipairs(_G.DevianLoadMessage) do
698 D:Print(msg) 779 D:Print(msg)
733 D:Print('Default channel: |cFFFFFF00'..currentProfile.default_channel..'|r: |cFF00FFFF'.. D.channels[currentProfile.default_channel].signature..'|r') 814 D:Print('Default channel: |cFFFFFF00'..currentProfile.default_channel..'|r: |cFF00FFFF'.. D.channels[currentProfile.default_channel].signature..'|r')
734 end 815 end
735 end 816 end
736 817
737 818
738 for i, cinfo in pairs(D.channels) do 819
739 i = tonumber(i) 820 for index, cinfo in ipairs(D.channels) do
821 --oldprint(index, cinfo.signature)
740 if not D.primary_channel then 822 if not D.primary_channel then
741 D.primary_channel = i 823 D.primary_channel = index
742 end 824 end
743 D:SetChannel(cinfo, i) 825 D:GetOrCreateChannel(index)
744 D.num_channels = D.num_channels + 1 826 D.num_channels = #D.channels
745 end 827 end
746 D.primary_channel = D.primary_channel or 1 828 D.primary_channel = D.primary_channel or 1
747
748 D.max_channel = max(D.max_channel, currentProfile.max_channel) 829 D.max_channel = max(D.max_channel, currentProfile.max_channel)
749 if currentProfile.max_channel < D.max_channel then 830 if currentProfile.max_channel < D.max_channel then
750 for i = currentProfile.max_channel, D.max_channel do 831 for i = currentProfile.max_channel, D.max_channel do
751 D.console[i]:Hide() 832 D.console[i]:Hide()
752 end 833 end
753 end 834 end
835
836 D.UpdateTags()
754 837
755 if currentProfile.workspace then 838 if currentProfile.workspace then
756 if D.console[currentProfile.current_channel] then 839 if D.console[currentProfile.current_channel] then
757 --print('bringing', D.console[currentProfile.current_channel].signature, 'to the front') 840 --print('bringing', D.console[currentProfile.current_channel].signature, 'to the front')
758 D.console[currentProfile.current_channel]:ToFront() 841 D.console[currentProfile.current_channel]:ToFront()
759 -- bring the current channel to the front 842 -- bring the current channel to the front
760 end 843 end
761 _G.DevianDock:Show() 844 DevianDock:Update()
762 D:UpdateDock() 845 end
763 end 846
764 end 847 print('devian')
765 848 end
849
850 function D:Print (...)
851 local msg = '|cFF00FF44Devian|r:'
852 for i = 1, select('#', ...) do
853 msg = msg .. ' ' .. tostring(select(i, ...))
854 end
855 DEFAULT_CHAT_FRAME:AddMessage(msg)
856 end
857
858 function D:GetActiveChannel()
859 return D.console[currentProfile.current_channel]
860 end
861
862 function D:GetOrCreateChannel(id, name)
863 local info = D.channels[id]
864 local frame = D.console[id]
865 if not frame then
866
867 --print('new frame')
868 frame = CreateFrame('Frame', 'DevianConsole'..id, Devian, 'DevianConsoleTemplate')
869 frame:SetID(id)
870 D.console[id] = frame
871 end
872 if not info then
873 --print('new channel')
874 info = {
875 }
876 D.DeepCopy(defaults.default_channel, info)
877 info.index = id
878 info.signature = name
879 D.channels[id] = info
880 end
881
882
883 frame:Setup(info)
884 return frame
885 end