Files
Freewood-OctoWoW-Core/UI/ChannelsTab.lua
T

776 lines
30 KiB
Lua

-- Freewood-OctoWoW-Core: Reiter "Kanaele" als Chatfenster (Kategorien links, Chat Mitte, Mitglieder rechts).
-- ALLES UNGEPRUEFT im Spiel. Datenschicht: Core/Channels.lua (Mitglieder) und Core/ChatLog.lua (Verlauf).
local ADDON, FW = ...
local UI = FW.UI
local Ch = FW.Channels
local CL = FW.ChatLog
local LEFT_W, RIGHT_W = 220, 220
local ROW = 24
local MAX_BUBBLES = 60
local LOG_LINES = 200
local LOGO = "Interface\\AddOns\\Freewood-OctoWoW-Core\\Media\\FreeWood_Logo.tga"
local QMARK = "Interface\\Icons\\INV_Misc_QuestionMark"
local ICONS = {
general = "Interface\\Icons\\INV_Misc_Note_01",
localdefense = "Interface\\Icons\\INV_Shield_06",
world = "Interface\\Icons\\INV_Misc_Map_01",
lookingforgroup = "Interface\\Icons\\INV_Misc_GroupLooking",
lft = "Interface\\Icons\\INV_Misc_GroupNeedMore",
}
local ICON_GUILD = "Interface\\Icons\\INV_Shirt_GuildTabard_01"
local ICON_GROUP = "Interface\\Icons\\Spell_Holy_PrayerOfHealing"
local ICON_WHISPER = "Interface\\Icons\\INV_Letter_02"
local STD = { general = true, localdefense = true, world = true, lookingforgroup = true,
allgemein = true, lokaleverteidigung = true }
local function Hex(r, g, b)
return string.format("|cff%02x%02x%02x", math.floor(r * 255 + 0.5), math.floor(g * 255 + 0.5), math.floor(b * 255 + 0.5))
end
local function SetClassIcon(tex, token)
local c = token and CL.ICON_COORDS[token]
if c then
tex:SetTexture(CL.ICON_FILE)
tex:SetTexCoord(c[1], c[2], c[3], c[4])
else
tex:SetTexture(QMARK)
tex:SetTexCoord(0.08, 0.92, 0.08, 0.92)
end
end
local function SetIcon(tex, path)
tex:SetTexture(path or QMARK)
tex:SetTexCoord(0.08, 0.92, 0.08, 0.92)
end
local G_date = _G.date
local function TimeText(t)
if not (t and G_date) then return "" end
local ok, s = pcall(G_date, "%H:%M", t)
return ok and s or ""
end
local function Build(content)
local L = FW.L
local f = CreateFrame("Frame", nil, content)
f:SetAllPoints(content)
local selKey = nil
local entries = {}
local search = ""
local seen = { cl = -1, ch = -1, w = 0 }
local stick = true
local lastH, lastViewH = 0, 0
------------------------------------------------------------------
-- Kopierfeld und Menue (gemeinsam)
------------------------------------------------------------------
local copy = UI.CreatePanel(UIParent, "bgDeep", "gold")
copy:SetSize(560, 96)
copy:SetPoint("CENTER", UIParent, "CENTER", 0, 120)
copy:SetFrameStrata("FULLSCREEN_DIALOG")
copy:Hide()
local copyHint = UI.CreateLabel(copy, L.CHAT_COPY_HINT, { size = 11, color = "textDim" })
copyHint:SetPoint("TOPLEFT", copy, "TOPLEFT", 12, -8)
local cbox = UI.CreatePanel(copy, "bg", "bronze")
cbox:SetPoint("TOPLEFT", copy, "TOPLEFT", 10, -28)
cbox:SetPoint("TOPRIGHT", copy, "TOPRIGHT", -10, -28)
cbox:SetHeight(26)
local cedit = CreateFrame("EditBox", nil, cbox)
cedit:SetAutoFocus(false)
cedit:SetPoint("TOPLEFT", cbox, "TOPLEFT", 6, -3)
cedit:SetPoint("BOTTOMRIGHT", cbox, "BOTTOMRIGHT", -6, 3)
cedit:SetMaxLetters(600)
if not cedit:SetFont(UI.GetFontPath("body"), 12, "") then cedit:SetFont("Fonts\\FRIZQT__.TTF", 12, "") end
cedit:SetTextColor(UI.Color("text"))
cedit:SetScript("OnEscapePressed", function() copy:Hide() end)
local copyMsg, copyUrl
local bMsg = UI.CreateButton(copy, L.CHAT_COPY_MSG, 100, 24, function()
if copyMsg then cedit:SetText(copyMsg); cedit:SetFocus(); cedit:HighlightText() end
end)
bMsg:SetPoint("BOTTOMLEFT", copy, "BOTTOMLEFT", 10, 8)
local bUrl = UI.CreateButton(copy, L.CHAT_COPY_LINK, 100, 24, function()
if copyUrl then cedit:SetText(copyUrl); cedit:SetFocus(); cedit:HighlightText() end
end)
bUrl:SetPoint("LEFT", bMsg, "RIGHT", 6, 0)
local bX = UI.CreateButton(copy, "X", 30, 24, function() copy:Hide() end)
bX:SetPoint("BOTTOMRIGHT", copy, "BOTTOMRIGHT", -10, 8)
local function ShowCopy(text, url)
copyMsg, copyUrl = text, url
cedit:SetText(text or "")
if url then bUrl:Show() else bUrl:Hide() end
copy:Show()
cedit:SetFocus()
cedit:HighlightText()
end
local menu, menuCatcher, menuTitle
local menuName
local selectKey, Redraw
local input
local function HideMenu()
if menu then menu:Hide() end
if menuCatcher then menuCatcher:Hide() end
end
local function BuildMenu()
menuCatcher = CreateFrame("Button", nil, UIParent)
menuCatcher:SetAllPoints(UIParent)
menuCatcher:SetFrameStrata("FULLSCREEN_DIALOG")
menuCatcher:RegisterForClicks("LeftButtonUp", "RightButtonUp")
menuCatcher:SetScript("OnClick", HideMenu)
menuCatcher:Hide()
menu = UI.CreatePanel(UIParent, "bgDeep", "gold")
menu:SetSize(180, 28 + 6 * 24 + 8)
menu:SetFrameStrata("FULLSCREEN_DIALOG")
menu:SetFrameLevel(menuCatcher:GetFrameLevel() + 5)
menu:Hide()
menuTitle = UI.CreateLabel(menu, "", { size = 12, color = "gold" })
menuTitle:SetPoint("TOPLEFT", menu, "TOPLEFT", 10, -8)
local acts = {
{ L.CHAN_WHISPER, function(n)
CL.OpenWhisper(n)
if selectKey then selectKey("w:" .. n) end
if input then input:SetFocus() end
end },
{ L.CHAN_INVITE, function(n) Ch.Invite(n) end },
{ L.CHAN_IGNORE, function(n) Ch.Ignore(n) end },
{ L.CHAT_MENU_FRIEND, function(n) if _G.AddFriend then pcall(_G.AddFriend, n) end end },
{ L.CHAT_MENU_WHO, function(n) CL.Ask(n, true) end },
{ L.CHAT_MENU_COPY, function(n) ShowCopy(n, nil) end },
}
local i = 1
while i <= 6 do
local a = acts[i]
local b = UI.CreateButton(menu, a[1], 164, 22, function()
local n = menuName
HideMenu()
if n then a[2](n) end
end)
b:SetPoint("TOPLEFT", menu, "TOPLEFT", 8, -28 - (i - 1) * 24)
i = i + 1
end
end
local function ShowMenu(name)
if not name or name == "" then return end
if not menu then BuildMenu() end
menuName = name
menuTitle:SetText(name)
local x, y = GetCursorPosition()
local sc = UIParent:GetEffectiveScale()
menu:ClearAllPoints()
menu:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", x / sc, y / sc)
menuCatcher:Show()
menu:Show()
end
------------------------------------------------------------------
-- Linke Spalte: Kategorien und Chats
------------------------------------------------------------------
local left = UI.CreateScrollFrame(f)
left:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
left:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 0)
left:SetWidth(LEFT_W)
local lrows = {}
local function LeftRow(i)
local r = lrows[i]
if not r then
r = CreateFrame("Button", nil, left.child)
r:SetHeight(ROW)
r:SetPoint("TOPLEFT", left.child, "TOPLEFT", 0, -(i - 1) * ROW)
r:SetPoint("TOPRIGHT", left.child, "TOPRIGHT", 0, -(i - 1) * ROW)
r:RegisterForClicks("LeftButtonUp")
r.sel = r:CreateTexture(nil, "BACKGROUND")
r.sel:SetAllPoints()
r.sel:SetColorTexture(UI.Color("bronze", 0.35))
r.hl = r:CreateTexture(nil, "HIGHLIGHT")
r.hl:SetAllPoints()
r.hl:SetColorTexture(UI.Color("gold", 0.15))
r.icon = r:CreateTexture(nil, "ARTWORK")
r.icon:SetSize(18, 18)
r.icon:SetPoint("LEFT", r, "LEFT", 8, 0)
r.text = UI.CreateLabel(r, "", { size = 12, justify = "LEFT" })
r.text:SetPoint("LEFT", r.icon, "RIGHT", 6, 0)
r.text:SetPoint("RIGHT", r, "RIGHT", -26, 0)
r.x = CreateFrame("Button", nil, r)
r.x:SetSize(18, 18)
r.x:SetPoint("RIGHT", r, "RIGHT", -4, 0)
r.xt = UI.CreateLabel(r.x, "x", { size = 13, color = "textDim" })
r.xt:SetPoint("CENTER", r.x, "CENTER", 0, 0)
r.x:SetScript("OnEnter", function() r.xt:SetTextColor(UI.Color("danger")) end)
r.x:SetScript("OnLeave", function() r.xt:SetTextColor(UI.Color("textDim")) end)
lrows[i] = r
end
return r
end
local function BuildEntries()
local std, other, service = {}, {}, {}
local k = 1
while k <= table.getn(Ch.list) do
local e = Ch.list[k]
local low = string.lower(e.name)
local en = { key = "c:" .. e.name, kind = "channel", num = e.num, label = e.num .. ". " .. e.name,
count = e.stamp and e.count or nil, e = e }
if string.find(e.name, "^Freewood") then
en.mode = "data"; en.logo = true
service[table.getn(service) + 1] = en
elseif low == "lft" then
en.mode = "log"; en.icon = ICONS.lft
service[table.getn(service) + 1] = en
elseif STD[low] then
en.mode = "bubble"; en.icon = ICONS[low] or ICONS.general
std[table.getn(std) + 1] = en
else
en.mode = "bubble"; en.icon = ICONS[low] or ICONS.general
other[table.getn(other) + 1] = en
end
k = k + 1
end
local out = {}
local function Head(t) out[table.getn(out) + 1] = { head = t } end
local function Add(en) out[table.getn(out) + 1] = en end
if table.getn(std) > 0 then
Head(L.CHAT_CAT_STD)
k = 1; while k <= table.getn(std) do Add(std[k]); k = k + 1 end
end
if table.getn(other) > 0 then
Head(L.CHAT_CAT_OTHER)
k = 1; while k <= table.getn(other) do Add(other[k]); k = k + 1 end
end
Head(L.CHAT_CAT_GUILD)
Add({ key = "guild", kind = "guild", mode = "bubble", label = L.CHAT_GUILD, icon = ICON_GUILD,
count = table.getn(CL.guild) })
Head(L.CHAT_CAT_GROUP)
Add({ key = "group", kind = "group", mode = "bubble", label = L.CHAT_GROUP, icon = ICON_GROUP })
Head(L.CHAT_CAT_WHISPER)
local ws = CL.OpenWhispers()
k = 1
while k <= table.getn(ws) do
Add({ key = "w:" .. ws[k].name, kind = "whisper", mode = "bubble", label = ws[k].name,
icon = ICON_WHISPER, closable = true, name = ws[k].name })
k = k + 1
end
if table.getn(ws) == 0 then out[table.getn(out) + 1] = { note = L.CHAT_NOWHISPER } end
if table.getn(service) > 0 then
Head(L.CHAT_CAT_SERVICE)
k = 1; while k <= table.getn(service) do Add(service[k]); k = k + 1 end
end
return out
end
local function EntryByKey(key)
local k = 1
while k <= table.getn(entries) do
if entries[k].key == key then return entries[k] end
k = k + 1
end
return nil
end
local function FirstEntry()
local k = 1
while k <= table.getn(entries) do
if entries[k].key then return entries[k] end
k = k + 1
end
return nil
end
local function DrawLeft()
entries = BuildEntries()
if not selKey or not EntryByKey(selKey) then
local fe = FirstEntry()
selKey = fe and fe.key or nil
stick = true
end
local n = table.getn(entries)
local i = 1
local y = 0
while i <= n do
local en = entries[i]
local r = LeftRow(i)
r:ClearAllPoints()
r:SetPoint("TOPLEFT", left.child, "TOPLEFT", 0, -y)
r:SetPoint("TOPRIGHT", left.child, "TOPRIGHT", 0, -y)
r.x:Hide()
if en.head then
r:SetHeight(26)
r.sel:Hide(); r.hl:Hide(); r.icon:Hide()
r.text:ClearAllPoints()
r.text:SetPoint("LEFT", r, "LEFT", 8, -4)
r.text:SetPoint("RIGHT", r, "RIGHT", -4, -4)
r.text:SetText(Hex(UI.Color("gold")) .. string.upper(en.head) .. "|r")
r:SetScript("OnClick", nil)
y = y + 26
elseif en.note then
r:SetHeight(44)
r.sel:Hide(); r.hl:Hide(); r.icon:Hide()
r.text:ClearAllPoints()
r.text:SetPoint("LEFT", r, "LEFT", 8, 0)
r.text:SetPoint("RIGHT", r, "RIGHT", -8, 0)
r.text:SetText("|cff9a978c" .. en.note .. "|r")
r:SetScript("OnClick", nil)
y = y + 44
else
r:SetHeight(ROW)
r.hl:Show(); r.icon:Show()
r.text:ClearAllPoints()
r.text:SetPoint("LEFT", r.icon, "RIGHT", 6, 0)
r.text:SetPoint("RIGHT", r, "RIGHT", en.closable and -26 or -6, 0)
if en.logo then
r.icon:SetTexture(LOGO); r.icon:SetTexCoord(0, 1, 0, 1)
else
SetIcon(r.icon, en.icon)
end
local txt = en.label
if en.count then txt = txt .. " |cff9a978c(" .. en.count .. ")|r" end
local un = CL.unread[en.key]
if un and un > 0 and en.key ~= selKey then txt = txt .. " |cffc89b3c+" .. un .. "|r" end
r.text:SetText(txt)
if en.key == selKey then r.sel:Show() else r.sel:Hide() end
local key = en.key
r:SetScript("OnClick", function() selectKey(key) end)
if en.closable then
local nm = en.name
r.x:Show()
r.x:SetScript("OnClick", function()
CL.CloseWhisper(nm)
if selKey == "w:" .. nm then selKey = nil end
Redraw()
end)
end
y = y + ROW
end
r:Show()
i = i + 1
end
while lrows[i] do lrows[i]:Hide(); i = i + 1 end
left:SetContentHeight(math.max(1, y))
end
------------------------------------------------------------------
-- Mitte: Kopf, Chat (Blasen / Log), Eingabe
------------------------------------------------------------------
local head = UI.CreateLabel(f, "", { font = "heading", size = 15, color = "gold", justify = "LEFT" })
head:SetPoint("TOPLEFT", f, "TOPLEFT", LEFT_W + 14, -2)
head:SetPoint("TOPRIGHT", f, "TOPRIGHT", -(RIGHT_W + 14), -2)
local sub = UI.CreateLabel(f, "", { size = 11, color = "textDim", justify = "LEFT" })
sub:SetPoint("TOPLEFT", f, "TOPLEFT", LEFT_W + 14, -24)
sub:SetPoint("TOPRIGHT", f, "TOPRIGHT", -(RIGHT_W + 14), -24)
local chat = UI.CreateScrollFrame(f)
chat:SetPoint("TOPLEFT", f, "TOPLEFT", LEFT_W + 14, -44)
chat:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -(RIGHT_W + 14), 40)
local logArea = UI.CreateTextArea(f)
logArea:SetPoint("TOPLEFT", f, "TOPLEFT", LEFT_W + 14, -44)
logArea:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -(RIGHT_W + 14), 40)
logArea:Hide()
local empty = UI.CreateLabel(f, "", { size = 12, color = "textDim", justify = "LEFT", justifyV = "TOP" })
empty:SetPoint("TOPLEFT", f, "TOPLEFT", LEFT_W + 24, -56)
empty:SetPoint("TOPRIGHT", f, "TOPRIGHT", -(RIGHT_W + 24), -56)
empty:SetHeight(60)
local measure = f:CreateFontString(nil, "OVERLAY")
UI.SetFont(measure, "body", 12)
measure:Hide()
local ibox = UI.CreatePanel(f, "bgDeep", "bronze")
ibox:SetHeight(28)
ibox:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", LEFT_W + 14, 6)
ibox:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -(RIGHT_W + 14 + 96), 6)
input = CreateFrame("EditBox", nil, ibox)
input:SetAutoFocus(false)
input:SetPoint("TOPLEFT", ibox, "TOPLEFT", 8, -3)
input:SetPoint("BOTTOMRIGHT", ibox, "BOTTOMRIGHT", -8, 3)
input:SetMaxLetters(255)
if not input:SetFont(UI.GetFontPath("body"), 12, "") then input:SetFont("Fonts\\FRIZQT__.TTF", 12, "") end
input:SetTextColor(UI.Color("text"))
local ihint = UI.CreateLabel(ibox, L.CHAT_INPUT, { size = 12, color = "textDim" })
ihint:SetPoint("LEFT", ibox, "LEFT", 10, 0)
local function DoSend()
local txt = input:GetText() or ""
local en = selKey and EntryByKey(selKey)
if txt == "" or not en then return end
if en.kind == "channel" then CL.Send("channel", en.num, txt)
elseif en.kind == "guild" then CL.Send("guild", nil, txt)
elseif en.kind == "group" then CL.Send("group", nil, txt)
elseif en.kind == "whisper" then CL.Send("whisper", en.name, txt) end
input:SetText("")
end
input:SetScript("OnEnterPressed", function() DoSend(); input:SetFocus() end)
input:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
input:SetScript("OnTextChanged", function(self)
if (self:GetText() or "") == "" then ihint:Show() else ihint:Hide() end
end)
local sendBtn = UI.CreateButton(f, L.CHAT_SEND, 88, 28, DoSend)
sendBtn:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", -(RIGHT_W + 14), 6)
-- Blasen-Pool
local bubbles = {}
local function Bubble(i)
local b = bubbles[i]
if b then return b end
b = CreateFrame("Frame", nil, chat.child)
b:SetHeight(60)
b.avBtn = CreateFrame("Button", nil, b)
b.avBtn:SetSize(36, 36)
b.avBtn:RegisterForClicks("LeftButtonUp", "RightButtonUp")
b.av = b.avBtn:CreateTexture(nil, "ARTWORK")
b.av:SetAllPoints()
b.lvl = UI.CreateLabel(b, "", { size = 11, color = "textDim" })
b.panel = CreateFrame("Button", nil, b)
b.panel:RegisterForClicks("LeftButtonUp", "RightButtonUp")
b.bg = b.panel:CreateTexture(nil, "BACKGROUND")
b.bg:SetAllPoints()
b.hl = b.panel:CreateTexture(nil, "HIGHLIGHT")
b.hl:SetAllPoints()
b.hl:SetColorTexture(1, 1, 1, 0.05)
b.name = UI.CreateLabel(b.panel, "", { size = 12, justify = "LEFT" })
b.name:SetPoint("TOPLEFT", b.panel, "TOPLEFT", 10, -7)
b.time = UI.CreateLabel(b.panel, "", { size = 10, color = "textDim", justify = "RIGHT" })
b.time:SetPoint("TOPRIGHT", b.panel, "TOPRIGHT", -8, -8)
b.text = UI.CreateLabel(b.panel, "", { size = 12, justify = "LEFT", justifyV = "TOP" })
b.text:SetPoint("TOPLEFT", b.panel, "TOPLEFT", 10, -24)
bubbles[i] = b
return b
end
local function Plain(t) return CL.Plain(t) end
local function DrawBubbles(key)
local lines = CL.Lines(key) or {}
local n = table.getn(lines)
local first = math.max(1, n - MAX_BUBBLES + 1)
local areaW = chat.child:GetWidth()
if not areaW or areaW < 200 then areaW = 560 end
seen.w = areaW
local maxBub = math.floor(areaW * 0.68)
local atBottom = stick or (chat.scroll:GetVerticalScroll() >= lastH - lastViewH - 8)
local y = 6
local idx = 0
local i = first
while i <= n do
local ln = lines[i]
idx = idx + 1
local b = Bubble(idx)
local own = ln.o ~= nil
local who = ln.s or "?"
local cls, lv = CL.Info(who)
SetClassIcon(b.av, cls)
b.lvl:SetText(lv and tostring(lv) or "?")
local r, g, bl = CL.ClassColor(cls)
b.name:SetTextColor(r, g, bl)
b.name:SetText(who)
b.time:SetText(TimeText(ln.t))
local txt = ln.m or ""
measure:SetText(Plain(txt))
local tw = measure:GetStringWidth() or 0
if tw <= 0 then tw = maxBub end
local nameW = (b.name:GetStringWidth() or 60) + 50
local pw = math.floor(math.max(math.min(math.max(tw, nameW) + 22, maxBub), 110))
b.text:SetWidth(pw - 20)
b.text:SetText(txt)
local th = (b.text.GetStringHeight and b.text:GetStringHeight()) or b.text:GetHeight() or 14
if not th or th < 14 then th = 14 end
local ph = math.floor(th + 38)
b.panel:SetSize(pw, ph)
if own then b.bg:SetColorTexture(0.13, 0.27, 0.46, 0.95) else b.bg:SetColorTexture(UI.Color("card", 0.95)) end
local rowH = math.max(ph, 56)
b:SetSize(areaW - 8, rowH)
b:ClearAllPoints()
b:SetPoint("TOPLEFT", chat.child, "TOPLEFT", 0, -y)
b.avBtn:ClearAllPoints(); b.lvl:ClearAllPoints(); b.panel:ClearAllPoints()
if own then
b.avBtn:SetPoint("TOPRIGHT", b, "TOPRIGHT", -6, 0)
b.lvl:SetPoint("TOP", b.avBtn, "BOTTOM", 0, -1)
b.panel:SetPoint("TOPRIGHT", b.avBtn, "TOPLEFT", -8, 0)
else
b.avBtn:SetPoint("TOPLEFT", b, "TOPLEFT", 6, 0)
b.lvl:SetPoint("TOP", b.avBtn, "BOTTOM", 0, -1)
b.panel:SetPoint("TOPLEFT", b.avBtn, "TOPRIGHT", 8, 0)
end
local msg, sender = Plain(txt), who
local url = CL.FirstUrl(txt)
b.avBtn:SetScript("OnClick", function() ShowMenu(sender) end)
b.panel:SetScript("OnClick", function(_, btn)
btn = btn or arg1
if btn == "RightButton" then ShowMenu(sender) else ShowCopy(msg, url) end
end)
b:Show()
y = y + rowH + 8
i = i + 1
end
idx = idx + 1
while bubbles[idx] do bubbles[idx]:Hide(); idx = idx + 1 end
local viewH = chat.scroll:GetHeight() or 300
chat:SetContentHeight(math.max(1, y))
lastH, lastViewH = y, viewH
if atBottom then
chat.scroll:SetVerticalScroll(math.max(0, y - viewH))
chat.UpdateScroll()
stick = false
end
return n
end
local function DrawLog(key)
local lines = CL.Lines(key) or {}
local n = table.getn(lines)
local first = math.max(1, n - LOG_LINES + 1)
local parts = {}
local i = first
while i <= n do
local ln = lines[i]
parts[table.getn(parts) + 1] = "[" .. TimeText(ln.t) .. "] " .. (ln.s or "?") .. ": " .. Plain(ln.m or "")
i = i + 1
end
if not logArea.edit:HasFocus() then
local text = table.concat(parts, "\n")
if logArea.lastText ~= text then
logArea.lastText = text
logArea:SetText(text)
if C_Timer and C_Timer.After then
C_Timer.After(0.15, function()
local h = logArea.child:GetHeight() or 0
local v = logArea.scroll:GetHeight() or 0
logArea.scroll:SetVerticalScroll(math.max(0, h - v))
logArea.UpdateScroll()
end)
end
end
end
return n
end
local function DrawCenter()
local en = selKey and EntryByKey(selKey)
if not en then
head:SetText(""); sub:SetText(""); empty:SetText("")
chat:Hide(); logArea:Hide(); ibox:Hide(); sendBtn:Hide()
return
end
local title = en.label
if en.kind == "whisper" then
local c, lv = CL.Info(en.name)
title = en.name
sub:SetText((lv and (tostring(lv)) or "?") .. " - " .. L.CHAT_KEPT)
else
sub:SetText(L.CHAT_KEPT)
end
head:SetText(title)
local canWrite = en.mode ~= "data"
if canWrite then ibox:Show(); sendBtn:Show() else ibox:Hide(); sendBtn:Hide() end
if en.mode == "data" then
chat:Hide(); logArea:Hide()
empty:SetText(L.CHAT_DATA)
elseif en.mode == "log" then
chat:Hide(); logArea:Show()
local n = DrawLog(en.key)
if n == 0 then empty:SetText(L.CHAT_EMPTY) else empty:SetText("") end
else
logArea:Hide(); chat:Show()
local n = DrawBubbles(en.key)
if n == 0 then empty:SetText(L.CHAT_EMPTY) else empty:SetText("") end
end
if en.kind == "guild" and not (IsInGuild and IsInGuild()) then empty:SetText(L.CHAT_NOGUILD) end
end
------------------------------------------------------------------
-- Rechte Spalte: Suche und Mitglieder
------------------------------------------------------------------
local box = UI.CreatePanel(f, "bgDeep", "bronze")
box:SetHeight(26)
box:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -2)
box:SetWidth(RIGHT_W)
local edit = CreateFrame("EditBox", nil, box)
edit:SetAutoFocus(false)
edit:SetPoint("TOPLEFT", box, "TOPLEFT", 8, -2)
edit:SetPoint("BOTTOMRIGHT", box, "BOTTOMRIGHT", -8, 2)
edit:SetMaxLetters(40)
if not edit:SetFont(UI.GetFontPath("body"), 12, "") then edit:SetFont("Fonts\\FRIZQT__.TTF", 12, "") end
edit:SetTextColor(UI.Color("text"))
edit:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
local hint = UI.CreateLabel(box, L.CHAN_SEARCH, { size = 11, color = "textDim" })
hint:SetPoint("LEFT", box, "LEFT", 8, 0)
hint:SetPoint("RIGHT", box, "RIGHT", -4, 0)
local rhead = UI.CreateLabel(f, "", { size = 11, color = "textDim", justify = "LEFT" })
rhead:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -34)
rhead:SetWidth(RIGHT_W)
local refresh = UI.CreateButton(f, L.CHAN_REFRESH, RIGHT_W, 24, function()
Ch.RefreshAll()
CL.RequestGuild()
end)
refresh:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 6)
local right = UI.CreateScrollFrame(f)
right:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -54)
right:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 36)
right:SetWidth(RIGHT_W)
local rrows = {}
local function RightRow(i)
local r = rrows[i]
if not r then
r = CreateFrame("Button", nil, right.child)
r:SetHeight(22)
r:SetPoint("TOPLEFT", right.child, "TOPLEFT", 0, -(i - 1) * 22)
r:SetPoint("TOPRIGHT", right.child, "TOPRIGHT", 0, -(i - 1) * 22)
r:RegisterForClicks("LeftButtonUp", "RightButtonUp")
r.hl = r:CreateTexture(nil, "HIGHLIGHT")
r.hl:SetAllPoints()
r.hl:SetColorTexture(UI.Color("gold", 0.15))
r.icon = r:CreateTexture(nil, "ARTWORK")
r.icon:SetSize(16, 16)
r.icon:SetPoint("LEFT", r, "LEFT", 4, 0)
r.text = UI.CreateLabel(r, "", { size = 12, justify = "LEFT" })
r.text:SetPoint("LEFT", r.icon, "RIGHT", 6, 0)
r.text:SetPoint("RIGHT", r, "RIGHT", -4, 0)
rrows[i] = r
end
return r
end
local function MembersOf(en)
local out = {}
if not en then return out end
if en.kind == "channel" and en.e then
local k = 1
while k <= table.getn(en.e.members) do
out[table.getn(out) + 1] = { name = en.e.members[k] }
k = k + 1
end
elseif en.kind == "guild" then
local k = 1
while k <= table.getn(CL.guild) do
local g = CL.guild[k]
out[table.getn(out) + 1] = { name = g.name, class = g.class, level = g.level }
k = k + 1
end
elseif en.kind == "group" then
out = CL.ScanGroup()
elseif en.kind == "whisper" then
out[1] = { name = en.name }
end
return out
end
local function DrawRight()
local en = selKey and EntryByKey(selKey)
local items = {}
if search ~= "" then
local hits = Ch.Find(search, 300)
local h = 1
while h <= table.getn(hits) do
items[h] = { name = hits[h].name, extra = table.concat(hits[h].chans, ", ") }
h = h + 1
end
rhead:SetText(table.getn(items) == 0 and L.CHAN_NO_HITS or (Ch.moreFound and L.CHAN_MORE or ""))
Ch.moreFound = nil
else
items = MembersOf(en)
local title = (en and en.kind == "guild") and L.CHAT_ONLINE_HDR or L.CHAT_MEMBERS_HDR
rhead:SetText(title .. " (" .. table.getn(items) .. ")")
if en and en.kind == "group" and table.getn(items) <= 1 then rhead:SetText(L.CHAT_NOGROUP) end
end
local cnt = math.min(table.getn(items), 400)
local i = 1
while i <= cnt do
local it = items[i]
local r = RightRow(i)
local nm = it.name
local cls, lv = it.class, it.level
if not cls or not lv then
local c2, l2 = CL.Info(nm)
cls = cls or c2; lv = lv or l2
end
SetClassIcon(r.icon, cls)
local cr, cg, cb = CL.ClassColor(cls)
local txt = Hex(cr, cg, cb) .. nm .. "|r"
if lv then txt = txt .. " |cff9a978c" .. lv .. "|r" end
if it.extra then txt = txt .. " |cff9a978c" .. it.extra .. "|r" end
r.text:SetText(txt)
r:SetScript("OnClick", function() ShowMenu(nm) end)
r:Show()
i = i + 1
end
while rrows[i] do rrows[i]:Hide(); i = i + 1 end
right:SetContentHeight(math.max(1, cnt * 22))
end
edit:SetScript("OnTextChanged", function(self)
search = self:GetText() or ""
if search == "" then hint:Show() else hint:Hide() end
right:ScrollToTop()
DrawRight()
end)
------------------------------------------------------------------
-- Zusammenspiel
------------------------------------------------------------------
Redraw = function()
seen.cl, seen.ch = CL.version, Ch.version
DrawLeft()
CL.viewKey = selKey
if selKey then CL.unread[selKey] = nil end
DrawCenter()
DrawRight()
end
selectKey = function(key)
selKey = key
stick = true
CL.unread[key] = nil
Redraw()
end
f.Refresh = function()
CL.viewVisible = true
if Ch.dirty or table.getn(Ch.list) == 0 then
Ch.dirty = nil
Ch.RefreshAll()
else
Ch.Rescan()
end
CL.RequestGuild()
stick = true
Redraw()
end
f:SetScript("OnHide", function()
CL.viewVisible = false
HideMenu()
copy:Hide()
end)
local acc = 0
f:SetScript("OnUpdate", function(_, el)
acc = acc + (el or arg1 or 0)
if acc < 0.4 then return end
acc = 0
if not f:IsShown() then return end
local w = chat.child:GetWidth()
if seen.cl ~= CL.version or seen.ch ~= Ch.version or (w and math.abs(w - seen.w) > 4) then
Redraw()
end
end)
return f
end
UI:RegisterTab("channels", {
label = function() return FW.L.TAB_CHANNELS end,
order = 115,
build = Build,
onShow = function(f) f.Refresh() end,
})