Mercurial > wow > devian
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 |
