local A, L = ...
local options = L.C
--------------------------------------
-- grab from elvui chat module
local _G = _G
local gsub, strfind, gmatch, format, max = gsub, strfind, gmatch, format, max
local ipairs, sort, wipe, time, difftime = ipairs, sort, wipe, time, difftime
local pairs, unpack, select, tostring, pcall, next, tonumber, type = pairs, unpack, select, tostring, pcall, next, tonumber, type
local strlower, strsub, strlen, strupper, strtrim, strmatch = strlower, strsub, strlen, strupper, strtrim, strmatch
local tinsert, tremove, tconcat = tinsert, tremove, table.concat
local Ambiguate = Ambiguate
local BetterDate = BetterDate
local BNGetFriendInfo = BNGetFriendInfo
local BNGetFriendInfoByID = BNGetFriendInfoByID
local BNGetNumFriendInvites = BNGetNumFriendInvites
local BNGetNumFriends = BNGetNumFriends
local CreateFrame = CreateFrame
local FlashClientIcon = FlashClientIcon
local GetBNPlayerCommunityLink = GetBNPlayerCommunityLink
local GetBNPlayerLink = GetBNPlayerLink
local GetChannelName = GetChannelName
local GetChatWindowInfo = GetChatWindowInfo
local GetCursorPosition = GetCursorPosition
local GetCVar, GetCVarBool = GetCVar, GetCVarBool
local GetGuildRosterMOTD = GetGuildRosterMOTD
local GetInstanceInfo = GetInstanceInfo
local GetMouseFocus = GetMouseFocus
local GetNumGroupMembers = GetNumGroupMembers
local GetPlayerCommunityLink = GetPlayerCommunityLink
local GetPlayerInfoByGUID = GetPlayerInfoByGUID
local GetPlayerLink = GetPlayerLink
local GetRaidRosterInfo = GetRaidRosterInfo
local GMChatFrame_IsGM = GMChatFrame_IsGM
local GMError = GMError
local hooksecurefunc = hooksecurefunc
local InCombatLockdown = InCombatLockdown
local IsAltKeyDown = IsAltKeyDown
local IsInRaid, IsInGroup = IsInRaid, IsInGroup
local IsShiftKeyDown = IsShiftKeyDown
local PlaySoundFile = PlaySoundFile
local RemoveExtraSpaces = RemoveExtraSpaces
local RemoveNewlines = RemoveNewlines
local ToggleFrame = ToggleFrame
local UnitName = UnitName
local C_DateAndTime_GetCurrentCalendarTime = C_DateAndTime.GetCurrentCalendarTime
local C_Club_GetInfoFromLastCommunityChatLine = C_Club.GetInfoFromLastCommunityChatLine
local Chat_GetChatCategory = Chat_GetChatCategory
local ChatHistory_GetAccessID = ChatHistory_GetAccessID
local ChatFrame_ResolvePrefixedChannelName = ChatFrame_ResolvePrefixedChannelName
local BNet_GetValidatedCharacterName = BNet_GetValidatedCharacterName
local BNet_GetClientEmbeddedTexture = BNet_GetClientEmbeddedTexture
local BNET_CLIENT_WOW = BNET_CLIENT_WOW
local tabTexs = {
'',
'Selected',
'Highlight'
}
local function GetDockerParent(docker, chat)
if not docker then return end
local _, relativeTo = chat:GetPoint()
if relativeTo == docker then
return docker:GetParent()
end
end
local function UpdateEditboxAnchors(self)
local cvar = (type(self) == 'string' and self) or GetCVar('chatStyle')
local classic = cvar == 'classic'
local leftChat = classic and _G.LeftChatPanel
local panel = 22
for _, name in ipairs(_G.CHAT_FRAMES) do
local frame = _G[name]
local editbox = frame and frame.editBox
if not editbox then return end
editbox.chatStyle = cvar
editbox:ClearAllPoints()
local anchorTo = leftChat or frame
local below, belowInside = options.editBoxPosition == 'BELOW_CHAT', options.editBoxPosition == 'BELOW_CHAT_INSIDE'
if below or belowInside then
-- local showLeftPanel = E.db.datatexts.panels.LeftChatDataPanel.enable
editbox:SetPoint('TOPLEFT', anchorTo, 'BOTTOMLEFT', classic and 0 or -2, (classic and (belowInside and 1 or 0) or -5))
editbox:SetPoint('BOTTOMRIGHT', anchorTo, 'BOTTOMRIGHT', classic and 0 or -2, (classic and (belowInside and 1 or 0) or -5) + (belowInside and panel or -panel))
else
local aboveInside = options.editBoxPosition == 'ABOVE_CHAT_INSIDE'
editbox:SetPoint('BOTTOMLEFT', anchorTo, 'TOPLEFT', classic and (aboveInside and 1 or 0) or -2, (classic and (aboveInside and -1 or 0) or 2))
editbox:SetPoint('TOPRIGHT', anchorTo, 'TOPRIGHT', classic and (aboveInside and -1 or 0) or 2, (classic and (aboveInside and -1 or 0) or 2) + (aboveInside and -panel or panel))
end
end
end
local function RepositionOverflowButton()
_G.GeneralDockManagerOverflowButton:ClearAllPoints()
_G.GeneralDockManagerOverflowButton:SetPoint('RIGHT', _G.ChatFrameChannelButton, 'LEFT', -4, 0)
end
local function CreateChatVoicePanel()
local Holder = CreateFrame('Frame', 'ChatButtonHolder', UIParent)
Holder:ClearAllPoints()
Holder:SetPoint('BOTTOMLEFT', _G.LeftChatPanel, 'TOPLEFT', 0, 1)
Holder:SetSize(30, 86)
Holder.backdrop = L.CreateBackdrop(Holder)
Holder.backdrop:SetBackdropColor(options.panelColor.r, options.panelColor.g, options.panelColor.b, options.panelColor.a)
--create drag frame
-- rLib:CreateDragFrame(Holder, L.dragFrames, -2, true)
_G.ChatFrameChannelButton:ClearAllPoints()
_G.ChatFrameChannelButton:SetPoint('TOP', Holder, 'TOP', 0, -2)
L.HandleButton(_G.ChatFrameChannelButton, nil, nil, true)
_G.ChatFrameChannelButton.Icon:SetParent(_G.ChatFrameChannelButton)
_G.ChatFrameChannelButton.Icon:SetDesaturated(options.desaturateVoiceIcons)
_G.ChatFrameChannelButton:SetParent(Holder)
_G.ChatAlertFrame:ClearAllPoints()
_G.ChatAlertFrame:SetPoint('BOTTOM', _G.ChatFrameChannelButton, 'TOP', 1, 3)
end
local function HandleChatVoiceIcons()
-- reset this btn disabled in rchat
_G.ChatFrameChannelButton:HookScript("OnShow", _G.ChatFrameChannelButton.Show)
_G.ChatFrameChannelButton:Show()
if options.hideVoiceButtons then
_G.ChatFrameChannelButton:Hide()
elseif options.pinVoiceButtons then
L.HandleButton(_G.ChatFrameChannelButton)
_G.ChatFrameChannelButton.Icon:SetDesaturated(options.desaturateVoiceIcons)
_G.ChatFrameChannelButton:ClearAllPoints()
_G.ChatFrameChannelButton:SetPoint('RIGHT', _G.GeneralDockManager, 'RIGHT', 2, 0)
RepositionOverflowButton()
else
CreateChatVoicePanel()
end
if not options.hideVoiceButtons then
_G.GeneralDockManagerOverflowButtonList:SetFrameStrata('LOW')
_G.GeneralDockManagerOverflowButtonList:SetFrameLevel(5)
end
if not options.pinVoiceButtons then
_G.GeneralDockManagerOverflowButton:ClearAllPoints()
_G.GeneralDockManagerOverflowButton:SetPoint('RIGHT', _G.GeneralDockManager, 'RIGHT', -4, 0)
end
end
local function UpdateFading()
for _, frameName in ipairs(_G.CHAT_FRAMES) do
local frame = _G[frameName]
if frame then
frame:SetTimeVisible(options.inactivityTimer)
frame:SetFading(options.fade)
end
end
end
local canChangeMessage = function(arg1, id)
if id and arg1 == '' then return id end
end
local function MessageIsProtected(message)
return message and (message ~= gsub(message, '(:?|?)|K(.-)|k', canChangeMessage))
end
local function GetOwner(tab)
if not tab.owner then
tab.owner = _G[format('ChatFrame%s', tab:GetID())]
end
return tab.owner
end
local function GetTab(chat)
if not chat.tab then
chat.tab = _G[format('ChatFrame%sTab', chat:GetID())]
end
return chat.tab
end
local function ChatFrameTab_SetAlpha(self, _, skip)
if skip then return end
local chat = GetOwner(self)
self:SetAlpha((not chat.isDocked or self.selected) and 1 or 0.6, true)
end
local function ShowBackground(background, show)
if not background then return end
if show then
background.Show = nil
background:Show()
else
L.Kill(background)
end
end
local function TabOnEnter(tab)
tab.Text:Show()
if tab.conversationIcon then
tab.conversationIcon:Show()
end
if not options.hideCopyButton then
local chat = GetOwner(tab)
if chat and chat.copyButton and GetMouseFocus() ~= chat.copyButton then
chat.copyButton:SetAlpha(0.35)
end
end
end
local function TabOnLeave(tab)
tab.Text:Hide()
if tab.conversationIcon then
tab.conversationIcon:Hide()
end
if not options.hideCopyButton then
local chat = GetOwner(tab)
if chat and chat.copyButton and GetMouseFocus() ~= chat.copyButton then
chat.copyButton:SetAlpha(0)
end
end
end
local function ChatOnEnter(chat)
TabOnEnter(GetTab(chat))
end
local function ChatOnLeave(chat)
TabOnLeave(GetTab(chat))
end
local function IsUndocked(chat, docker)
if not docker then docker = _G.GeneralDockManager.primary end
local primaryUndocked = docker ~= rChatPlus.LeftChatWindow and docker ~= rChatPlus.RightChatWindow
return not chat.isDocked or (primaryUndocked and ((chat == docker) or GetDockerParent(docker, chat)))
end
local function HandleFadeTabs(chat, hook)
local tab = GetTab(chat)
if hook then
chat:SetScript('OnEnter', ChatOnEnter)
chat:SetScript('OnLeave', ChatOnLeave)
tab:SetScript('OnEnter', TabOnEnter)
tab:SetScript('OnLeave', TabOnLeave)
else
chat:SetScript('OnEnter', nil)
chat:SetScript('OnLeave', nil)
tab:SetScript('OnEnter', nil)
tab:SetScript('OnLeave', nil)
end
local focus = GetMouseFocus()
if not hook then
TabOnEnter(tab)
elseif focus ~= tab and focus ~= chat then
TabOnLeave(tab)
end
end
local function UpdateChatTab(chat)
local fadeLeft, fadeRight
if options.fadeTabsNoBackdrop then
local both = options.panelBackdrop == 'HIDEBOTH'
fadeLeft = (both or options.panelBackdrop == 'RIGHT')
fadeRight = (both or options.panelBackdrop == 'LEFT')
end
if chat == rChatPlus.LeftChatWindow then
GetTab(chat):SetParent(_G.LeftChatPanel or _G.UIParent)
chat:SetParent(_G.LeftChatPanel or _G.UIParent)
HandleFadeTabs(chat, fadeLeft)
elseif chat == rChatPlus.RightChatWindow then
GetTab(chat):SetParent(_G.RightChatPanel or _G.UIParent)
chat:SetParent(_G.RightChatPanel or _G.UIParent)
HandleFadeTabs(chat, fadeRight)
else
local docker = _G.GeneralDockManager.primary
local parent = GetDockerParent(docker, chat)
-- we need to update the tab parent to mimic the docker
GetTab(chat):SetParent(parent or _G.UIParent)
chat:SetParent(parent or _G.UIParent)
if parent and docker == rChatPlus.LeftChatWindow then
HandleFadeTabs(chat, fadeLeft)
elseif parent and docker == rChatPlus.RightChatWindow then
HandleFadeTabs(chat, fadeRight)
else
HandleFadeTabs(chat, options.fadeUndockedTabs and IsUndocked(chat, docker))
end
end
end
local function UpdateChatTabs()
for _, name in ipairs(_G.CHAT_FRAMES) do
UpdateChatTab(_G[name])
end
end
local function GetAnchorParents(chat)
local Left = (chat == rChatPlus.LeftChatWindow and _G.LeftChatPanel)
local Right = (chat == rChatPlus.RightChatWindow and _G.RightChatPanel)
local Chat, TabPanel = Left or Right or _G.UIParent
return TabPanel or Chat, Chat
end
local function ReparentVoiceChatIcon(parent)
if not parent then
parent = GetAnchorParents(_G.GeneralDockManager.primary)
end
_G.ChatFrameChannelButton:SetParent(parent)
end
local function FindChatWindows()
if not options.panelSnapping then return end
local left, right = rChatPlus.LeftChatWindow, rChatPlus.RightChatWindow
-- they already exist just return them :)
if left and right then
return left, right
end
local docker = _G.GeneralDockManager.primary
for _, name in ipairs(_G.CHAT_FRAMES) do
local chat = _G[name]
if (chat.isDocked and docker) or chat:IsShown() then
if not left and L.FramesOverlap(chat, _G.LeftChatPanel) then
left = chat
elseif not right and L.FramesOverlap(chat, _G.RightChatPanel) then
right = chat
end
-- if both are found just return now, don't wait
if left and right then
return left, right
end
end
end
-- none or one was found
return left, right
end
local function PositionChat(chat)
rChatPlus.LeftChatWindow, rChatPlus.RightChatWindow = FindChatWindows()
local docker = _G.GeneralDockManager.primary
if chat == docker then
local iconParent, chatParent = GetAnchorParents(chat)
_G.GeneralDockManager:SetParent(chatParent)
if options.pinVoiceButtons and not options.hideVoiceButtons then
ReparentVoiceChatIcon(iconParent or chatParent)
end
end
UpdateChatTab(chat)
if chat:IsMovable() then
chat:SetUserPlaced(true)
end
if chat.FontStringContainer then
chat.FontStringContainer:ClearAllPoints()
chat.FontStringContainer:SetPoint('TOPLEFT', chat, 'TOPLEFT', -1, 1)
chat.FontStringContainer:SetPoint('BOTTOMRIGHT', chat, 'BOTTOMRIGHT', 1, -1)
end
if chat:IsShown() then
-- that chat font container leaks outside of its frame
-- we cant clip it, so lets force that leak sooner so
-- i can position it properly, patch: 8.3.0 ~Simpy
chat:Hide()
chat:Show()
end
local BASE_OFFSET = 32
if chat == rChatPlus.LeftChatWindow then
local LOG_OFFSET = chat:GetID() == 2 and (_G.LeftChatTab:GetHeight() + 4) or 0
chat:ClearAllPoints()
chat:SetPoint('BOTTOMLEFT', _G.LeftChatPanel, 'BOTTOMLEFT', 5, 5)
chat:SetSize(options.panelWidth - 10, options.panelHeight - BASE_OFFSET - LOG_OFFSET)
ShowBackground(chat.Background, false)
elseif chat == rChatPlus.RightChatWindow then
local LOG_OFFSET = chat:GetID() == 2 and (_G.LeftChatTab:GetHeight() + 4) or 0
chat:ClearAllPoints()
chat:SetPoint('BOTTOMLEFT', _G.RightChatPanel, 'BOTTOMLEFT', 5, 5)
chat:SetSize((options.separateSizes and options.panelWidthRight or options.panelWidth) - 10, (options.separateSizes and options.panelHeightRight or options.panelHeight) - BASE_OFFSET - LOG_OFFSET)
ShowBackground(chat.Background, false)
else -- show if: not docked, or ChatFrame1, or attached to ChatFrame1
ShowBackground(chat.Background, IsUndocked(chat, docker))
end
end
local function PositionChats()
for _, name in ipairs(_G.CHAT_FRAMES) do
PositionChat(_G[name])
end
end
local copyLines = {}
function GetLines(frame)
local index = 1
for i = 1, frame:GetNumMessages() do
local message, r, g, b = frame:GetMessageInfo(i)
if message and not MessageIsProtected(message) then
--Set fallback color values
r, g, b = r or 1, g or 1, b or 1
copyLines[index] = message
index = index + 1
end
end
return index - 1
end
local function CopyChat(frame)
if not _G.CopyChatFrame:IsShown() then
local _, fontSize = _G.FCF_GetChatWindowInfo(frame:GetID())
if fontSize < 10 then fontSize = 12 end
_G.FCF_SetChatWindowFontSize(frame, frame, 0.01)
_G.CopyChatFrame:Show()
local lineCt = GetLines(frame)
local text = tconcat(copyLines, ' \n', 1, lineCt)
_G.FCF_SetChatWindowFontSize(frame, frame, fontSize)
_G.CopyChatFrameEditBox:SetText(text)
else
_G.CopyChatFrame:Hide()
end
end
local function EmoteButtonOnMouseUp(self, btn)
local chat = self:GetParent()
L.ToggleEmoteTable()
end
local function EmoteButtonOnEnter(self)
self:SetAlpha(1)
self.texture:SetDesaturated(false)
end
local function EmoteButtonOnLeave(self)
local chat = self:GetParent()
if _G[chat:GetName()..'TabText']:IsShown() then
self:SetAlpha(0.35)
else
self:SetAlpha(0)
end
self.texture:SetDesaturated(true)
end
local function CopyButtonOnMouseUp(self, btn)
local chat = self:GetParent()
if btn == 'RightButton' and chat:GetID() == 1 then
ToggleFrame(_G.ChatMenu)
else
CopyChat(chat)
end
end
local function CopyButtonOnEnter(self)
self:SetAlpha(1)
end
local function CopyButtonOnLeave(self)
local chat = self:GetParent()
if _G[chat:GetName()..'TabText']:IsShown() then
self:SetAlpha(0.35)
else
self:SetAlpha(0)
end
end
local function ToggleChatButton(button)
if button then
button:SetShown(not options.hideCopyButton)
end
end
local function Panels_ColorUpdate()
local panelColor = options.panelColor
_G.LeftChatPanel.backdrop:SetBackdropColor(panelColor.r, panelColor.g, panelColor.b, panelColor.a)
if _G.ChatButtonHolder then
_G.ChatButtonHolder:SetBackdropColor(panelColor.r, panelColor.g, panelColor.b, panelColor.a)
end
end
local function StyleChat(frame)
local name = frame:GetName()
local tab = GetTab(frame)
frame:SetTimeVisible(options.inactivityTimer)
frame:SetMaxLines(options.maxLines)
frame:SetFading(options.fade)
if frame.styled then return end
frame:SetFrameLevel(4)
frame:SetClampRectInsets(0,0,0,0)
frame:SetClampedToScreen(false)
L.StripTextures(frame, true)
L.Kill(_G[name..'ButtonFrame'])
local editbox = frame.editBox
for _, texName in pairs(tabTexs) do
_G[name..'Tab'..texName..'Left']:SetTexture()
_G[name..'Tab'..texName..'Middle']:SetTexture()
_G[name..'Tab'..texName..'Right']:SetTexture()
end
hooksecurefunc(tab, 'SetAlpha', ChatFrameTab_SetAlpha)
if not tab.left then tab.left = _G[name..'TabLeft'] end
tab.Text:ClearAllPoints()
tab.Text:SetPoint('LEFT', tab, 'LEFT', tab.left:GetWidth(), 0)
tab:SetHeight(22)
if tab.conversationIcon then
tab.conversationIcon:ClearAllPoints()
tab.conversationIcon:SetPoint('RIGHT', tab.Text, 'LEFT', -1, 0)
end
--local a, b, c = select(6, editbox:GetRegions()); a:Kill(); b:Kill(); c:Kill()
L.Kill(_G[name..'EditBoxLeft'])
L.Kill(_G[name..'EditBoxMid'])
L.Kill(_G[name..'EditBoxRight'])
editbox:SetAltArrowKeyMode(options.useAltKey)
--copy chat button
local copyButton = CreateFrame('Frame', format('%sCopyChatButton%d', A, id), frame)
copyButton:EnableMouse(true)
copyButton:SetAlpha(0.35)
copyButton:SetSize(20, 22)
copyButton:SetPoint('TOPRIGHT', 0, -4)
copyButton:SetFrameLevel(frame:GetFrameLevel() + 5)
frame.copyButton = copyButton
local copyTexture = L.CreateIcon(frame.copyButton, 'OVERLAY')
copyTexture:SetTexture(options.mediapath .. "Copy.tga")
copyButton.texture = copyTexture
copyButton:SetScript('OnMouseUp', CopyButtonOnMouseUp)
copyButton:SetScript('OnEnter', CopyButtonOnEnter)
copyButton:SetScript('OnLeave', CopyButtonOnLeave)
ToggleChatButton(copyButton)
--emote button
if options.emote.enable then
local emoteButton = CreateFrame('Frame', format('%sEmoteButton%d', A, id), frame)
emoteButton:EnableMouse(true)
emoteButton:SetAlpha(0.35)
emoteButton:SetSize(20, 20)
emoteButton:SetPoint('TOPRIGHT', 0, -30)
emoteButton:SetFrameLevel(frame:GetFrameLevel() + 5)
frame.emoteButton = emoteButton
local emoteTexture = L.CreateIcon(frame.emoteButton, 'OVERLAY')
emoteTexture:SetTexture(options.mediapath .. "Emote.blp")
emoteTexture:SetDesaturated(true)
emoteButton.texture = emoteTexture
emoteButton:SetScript('OnMouseUp', EmoteButtonOnMouseUp)
emoteButton:SetScript('OnEnter', EmoteButtonOnEnter)
emoteButton:SetScript('OnLeave', EmoteButtonOnLeave)
end
local lang = _G[name.."EditBoxLanguage"]
lang:GetRegions():SetAlpha(0)
lang:SetPoint("TOPRIGHT", editbox, "TOPRIGHT", -15, -2)
lang:SetPoint("BOTTOMRIGHT", editbox, "BOTTOMRIGHT", -15, 2)
-- L.CreateBackdrop(lang)
frame.styled = true
end
local function SetupChat()
for _, frameName in ipairs(_G.CHAT_FRAMES) do
local frame = _G[frameName]
local id = frame:GetID()
StyleChat(frame)
_G.FCFTab_UpdateAlpha(frame)
end
local chat = _G.GeneralDockManager.primary
_G.GeneralDockManager:ClearAllPoints()
_G.GeneralDockManager:SetPoint('BOTTOMLEFT', chat, 'TOPLEFT', 0, 3)
_G.GeneralDockManager:SetPoint('BOTTOMRIGHT', chat, 'TOPRIGHT', 0, 3)
_G.GeneralDockManager:SetHeight(22)
_G.GeneralDockManagerScrollFrame:SetHeight(22)
_G.GeneralDockManagerScrollFrameChild:SetHeight(22)
PositionChats()
if not rChatPlus.HookSecured then
hooksecurefunc("FCF_OpenTemporaryWindow", SetupChat)
rChatPlus.HookSecured = true
end
end
local function UpdateEditboxFont(chatFrame)
local style = GetCVar('chatStyle')
if style == 'classic' and rChatPlus.LeftChatWindow then
chatFrame = rChatPlus.LeftChatWindow
end
if chatFrame == _G.GeneralDockManager.primary then
chatFrame = _G.GeneralDockManager.selected
end
local editbox = _G.ChatEdit_ChooseBoxForSend(chatFrame)
-- the header and text will not update the placement without focus
if editbox and editbox:IsShown() then
editbox:SetFocus()
end
end
local function ChatEdit_SetLastActiveWindow(editbox)
local style = editbox.chatStyle or GetCVar('chatStyle')
if style == 'im' then editbox:SetAlpha(0.5) end
end
local function ChatEdit_DeactivateChat(editbox)
local style = editbox.chatStyle or GetCVar('chatStyle')
if style == 'im' then editbox:Hide() end
end
local function ChatEdit_ActivateChat(editbox)
if editbox and editbox.chatFrame then
UpdateEditboxFont(editbox.chatFrame)
end
end
local function ChatEdit_OnEnterPressed(editBox)
-- editBox:ClearHistory() -- we will use our own editbox history so keeping them populated on blizzards end is pointless
local chatType = editBox:GetAttribute('chatType')
local chatFrame = chatType and editBox:GetParent()
if chatFrame and (not chatFrame.isTemporary) and (_G.ChatTypeInfo[chatType].sticky == 1) then
if not options.sticky then chatType = 'SAY' end
editBox:SetAttribute('chatType', chatType)
end
end
local function GetCombatLog()
local LOG = _G.ChatFrame2 -- ChatFrame2
if LOG then return LOG, GetTab(LOG) end
end
local function FCFDock_UpdateTabs(dock)
if dock == _G.GeneralDockManager then
local logchat, logchattab = GetCombatLog()
dock.scrollFrame:ClearAllPoints()
dock.scrollFrame:SetPoint('RIGHT', dock.overflowButton, 'LEFT')
dock.scrollFrame:SetPoint('TOPLEFT', (logchat.isDocked and logchattab) or GetTab(dock.primary), 'TOPRIGHT')
end
end
local function FCF_Close(chat)
-- clear these off when it's closed, used by FCFTab_UpdateColors
local tab = GetTab(chat)
tab.whisperName = nil
tab.classColor = nil
end
local function FCF_SetWindowAlpha(frame, alpha)
frame.oldAlpha = alpha or 1
end
local function FCFTab_UpdateColors(tab, selected)
if not tab then return end
if tab:GetParent() == _G.ChatConfigFrameChatTabManager then
if selected then
tab.Text:SetTextColor(1, 1, 1)
end
local name = GetChatWindowInfo(tab:GetID())
if name then
tab.Text:SetText(name)
end
tab:SetAlpha(1) -- for some reason blizzard likes to change the alpha here? idk
else -- actual chat tab and other
local chat = GetOwner(tab)
if not chat then return end
tab.selected = selected
local whisper = tab.conversationIcon and chat.chatTarget
local name = chat.name or UNKNOWN
if whisper and not tab.whisperName then
tab.whisperName = gsub(name, '([%S]-)%-[%S]+', '%1|cFF999999*|r')
end
if selected then
if options.tabSelector == 'NONE' then
tab:SetFormattedText(rChatPlus.TabStyles.NONE, tab.whisperName or name)
else
local color = options.tabSelectorColor
local hexColor = L.RGBToHex(color.r, color.g, color.b)
tab:SetFormattedText(rChatPlus.TabStyles[options.tabSelector] or rChatPlus.TabStyles.ARROW1, hexColor, tab.whisperName or name, hexColor)
end
if options.tabSelectedTextEnabled then
local color = options.tabSelectedTextColor
tab.Text:SetTextColor(color.r, color.g, color.b)
return -- using selected text color
end
end
if whisper then
if not selected then
tab:SetText(tab.whisperName or name)
end
else
if not selected then
tab:SetText(name)
end
end
end
end
local function FCFDock_SelectWindow(_, chatFrame)
if chatFrame then
UpdateEditboxFont(chatFrame)
end
end
local function Unsnapped(chat)
if chat == rChatPlus.LeftChatWindow then
rChatPlus.LeftChatWindow = nil
elseif chat == rChatPlus.RightChatWindow then
rChatPlus.RightChatWindow = nil
end
end
local function ClearSnapping()
rChatPlus.LeftChatWindow = nil
rChatPlus.RightChatWindow = nil
end
local function SnappingChanged(chat)
Unsnapped(chat)
if chat == _G.GeneralDockManager.primary then
for _, frame in ipairs(_G.GeneralDockManager.DOCKED_CHAT_FRAMES) do
PositionChat(frame)
end
else
PositionChat(chat)
end
end
local function BuildCopyChatFrame()
local frame = CreateFrame('Frame', 'CopyChatFrame', UIParent, 'BackdropTemplate')
tinsert(_G.UISpecialFrames, 'CopyChatFrame')
frame.backdrop = L.CreateBackdrop(frame)
frame:SetSize(700, 200)
frame:SetPoint('CENTER', UIParent, 'CENTER')
frame:Hide()
frame:SetMovable(true)
frame:EnableMouse(true)
frame:SetResizable(true)
frame:SetMinResize(350, 100)
frame:SetScript('OnMouseDown', function(copyChat, button)
if button == 'LeftButton' and not copyChat.isMoving then
copyChat:StartMoving()
copyChat.isMoving = true
elseif button == 'RightButton' and not copyChat.isSizing then
copyChat:StartSizing()
copyChat.isSizing = true
end
end)
frame:SetScript('OnMouseUp', function(copyChat, button)
if button == 'LeftButton' and copyChat.isMoving then
copyChat:StopMovingOrSizing()
copyChat.isMoving = false
elseif button == 'RightButton' and copyChat.isSizing then
copyChat:StopMovingOrSizing()
copyChat.isSizing = false
end
end)
frame:SetScript('OnHide', function(copyChat)
if copyChat.isMoving or copyChat.isSizing then
copyChat:StopMovingOrSizing()
copyChat.isMoving = false
copyChat.isSizing = false
end
end)
frame:SetFrameStrata('DIALOG')
local scrollArea = CreateFrame('ScrollFrame', 'CopyChatScrollFrame', frame, 'UIPanelScrollFrameTemplate')
scrollArea:SetPoint('TOPLEFT', frame, 'TOPLEFT', 8, -30)
scrollArea:SetPoint('BOTTOMRIGHT', frame, 'BOTTOMRIGHT', -30, 8)
scrollArea:SetScript('OnSizeChanged', function(scroll)
_G.CopyChatFrameEditBox:SetWidth(scroll:GetWidth())
_G.CopyChatFrameEditBox:SetHeight(scroll:GetHeight())
end)
scrollArea:SetScript('OnVerticalScroll', function(scroll, offset)
_G.CopyChatFrameEditBox:SetHitRectInsets(0, 0, offset, (_G.CopyChatFrameEditBox:GetHeight() - offset - scroll:GetHeight()))
end)
local editBox = CreateFrame('EditBox', 'CopyChatFrameEditBox', frame)
editBox:SetMultiLine(true)
editBox:SetMaxLetters(99999)
editBox:EnableMouse(true)
editBox:SetAutoFocus(false)
editBox:SetFontObject(_G.ChatFontNormal)
editBox:SetWidth(scrollArea:GetWidth())
editBox:SetHeight(200)
editBox:SetScript('OnEscapePressed', function() _G.CopyChatFrame:Hide() end)
scrollArea:SetScrollChild(editBox)
_G.CopyChatFrameEditBox:SetScript('OnTextChanged', function(_, userInput)
if userInput then return end
local _, Max = _G.CopyChatScrollFrameScrollBar:GetMinMaxValues()
for _ = 1, Max do
_G.ScrollFrameTemplate_OnMouseWheel(_G.CopyChatScrollFrame, -1)
end
end)
local close = CreateFrame('Button', 'CopyChatFrameCloseButton', frame, 'UIPanelCloseButton, BackdropTemplate')
close:SetPoint('TOPRIGHT')
close:SetFrameLevel(close:GetFrameLevel() + 1)
close:EnableMouse(true)
end
function rChatPlus:Initialize()
SetupChat()
UpdateFading()
Panels_ColorUpdate()
HandleChatVoiceIcons()
UpdateEditboxAnchors()
hooksecurefunc("ChatEdit_SetLastActiveWindow", ChatEdit_SetLastActiveWindow)
hooksecurefunc("ChatEdit_DeactivateChat", ChatEdit_DeactivateChat)
hooksecurefunc("ChatEdit_ActivateChat", ChatEdit_ActivateChat)
hooksecurefunc("ChatEdit_OnEnterPressed", ChatEdit_OnEnterPressed)
hooksecurefunc("FCFDock_UpdateTabs", FCFDock_UpdateTabs)
hooksecurefunc("FCF_Close", FCF_Close)
hooksecurefunc("FCF_SetWindowAlpha", FCF_SetWindowAlpha)
hooksecurefunc("FCFTab_UpdateColors", FCFTab_UpdateColors)
hooksecurefunc('FCFDock_SelectWindow', FCFDock_SelectWindow)
hooksecurefunc('FCF_SavePositionAndDimensions', SnappingChanged)
hooksecurefunc('FCF_UnDockFrame', SnappingChanged)
hooksecurefunc('FCF_DockFrame', SnappingChanged)
hooksecurefunc('FCF_ResetChatWindows', ClearSnapping)
hooksecurefunc('RedockChatWindows', ClearSnapping)
self:RegisterEvent('UPDATE_CHAT_WINDOWS')
self:RegisterEvent('UPDATE_FLOATING_CHAT_WINDOWS')
self:SetScript('OnEvent', function(self, event)
if event == 'UPDATE_CHAT_WINDOWS' or event == 'UPDATE_FLOATING_CHAT_WINDOWS' then
SetupChat()
end
end)
BuildCopyChatFrame()
-- Editbox Backdrop Color
hooksecurefunc('ChatEdit_UpdateHeader', function(editbox)
local chatType = editbox:GetAttribute('chatType')
if not chatType then return end
local ChatTypeInfo = _G.ChatTypeInfo
local info = ChatTypeInfo[chatType]
local chanTarget = editbox:GetAttribute('channelTarget')
local chanName = chanTarget and GetChannelName(chanTarget)
--Increase inset on right side to make room for character count text
local insetLeft, insetRight, insetTop, insetBottom = editbox:GetTextInsets()
editbox:SetTextInsets(insetLeft, insetRight + 30, insetTop, insetBottom)
if not editbox.backdrop then
editbox.backdrop = L.CreateBackdrop(editbox)
end
if chanName and (chatType == 'CHANNEL') then
if chanName == 0 then
editbox.backdrop:SetBackdropBorderColor(unpack(options.backdrop.edgeColor))
else
info = ChatTypeInfo[chatType..chanName]
editbox.backdrop:SetBackdropBorderColor(info.r, info.g, info.b)
end
else
editbox.backdrop:SetBackdropBorderColor(info.r, info.g, info.b)
end
end)
end