-- CHAT PROTOTYPE STUFF
SELECTED_DOCK_FRAME = nil;
DOCKED_CHAT_FRAMES = {};
DOCK_COPY = {};
MOVING_CHATFRAME = nil;
CHAT_TAB_SHOW_DELAY = 0.2;
CHAT_TAB_HIDE_DELAY = 1;
CHAT_FRAME_FADE_TIME = 0.15;
CHAT_FRAME_FADE_OUT_TIME = 2.0;
CHAT_FRAME_BUTTON_FRAME_MIN_ALPHA = 0.2;
CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA = 1.0;
CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA = 0.4;
CHAT_FRAME_TAB_ALERTING_MOUSEOVER_ALPHA = 1.0;
CHAT_FRAME_TAB_ALERTING_NOMOUSE_ALPHA = 1.0;
CHAT_FRAME_TAB_NORMAL_MOUSEOVER_ALPHA = 0.6;
CHAT_FRAME_TAB_NORMAL_NOMOUSE_ALPHA = 0.2;
DEFAULT_CHATFRAME_ALPHA = 0.25;
DEFAULT_CHATFRAME_COLOR = {r = 0, g = 0, b = 0};
CHAT_FRAME_NORMAL_MIN_HEIGHT = 120;
CHAT_FRAME_BIGGER_MIN_HEIGHT = 147;
CHAT_FRAME_MIN_WIDTH = 296;
CURRENT_CHAT_FRAME_ID = nil;
CHAT_FRAME_TEXTURES = {
"Background",
"TopLeftTexture",
"BottomLeftTexture",
"TopRightTexture",
"BottomRightTexture",
"LeftTexture",
"RightTexture",
"BottomTexture",
"TopTexture",
--"ResizeButton",
"ButtonFrameBackground",
"ButtonFrameTopLeftTexture",
"ButtonFrameBottomLeftTexture",
"ButtonFrameTopRightTexture",
"ButtonFrameBottomRightTexture",
"ButtonFrameLeftTexture",
"ButtonFrameRightTexture",
"ButtonFrameBottomTexture",
"ButtonFrameTopTexture",
}
CHAT_FRAMES = {};
function FloatingChatFrame_OnLoad(self)
--IMPORTANT NOTE: This function isn't run by ChatFrame1.
tinsert(CHAT_FRAMES, self:GetName());
FCF_SetTabPosition(self, 0);
FloatingChatFrame_Update(self:GetID());
FCFTab_UpdateColors(_G[self:GetName().."Tab"], true);
self:SetClampRectInsets(-35, 35, 26, -50);
local chatTab = _G[self:GetName().."Tab"];
chatTab.mouseOverAlpha = CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA;
chatTab.noMouseAlpha = CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA;
FRAMELOCK_STATES.PETBATTLEOPENING[self:GetName()] = "hidden";
FRAMELOCK_STATES.PETBATTLEOPENING[chatTab:GetName()] = "hidden";
UpdateFrameLock(self);
UpdateFrameLock(chatTab);
end
function FloatingChatFrame_OnEvent(self, event, ...)
if ( (event == "UPDATE_CHAT_WINDOWS") or (event == "UPDATE_FLOATING_CHAT_WINDOWS") ) then
FloatingChatFrame_Update(self:GetID(), 1);
self.isInitialized = 1;
elseif ( event == "UPDATE_CHAT_COLOR" ) then
local chatType, r, g, b = ...;
if ( self.isTemporary and self.chatType == chatType ) then
local tab = _G[self:GetName().."Tab"];
tab.selectedColorTable.r, tab.selectedColorTable.g, tab.selectedColorTable.b = r, g, b;
FCFTab_UpdateColors(tab, not self.isDocked or self == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK));
end
end
end
function FloatingChatFrame_OnMouseScroll(self, delta)
if ( delta > 0 ) then
self:ScrollUp();
else
self:ScrollDown();
end
end
function FCF_GetChatWindowInfo(id)
if ( id > NUM_CHAT_WINDOWS ) then
local frame = _G["ChatFrame"..id];
local tab = _G["ChatFrame"..id.."Tab"];
local background = _G["ChatFrame"..id.."Background"];
if ( frame and tab and background ) then
local r, g, b, a = background:GetVertexColor();
return tab:GetText(), select(2, frame:GetFont()), r, g, b, a, frame:IsShown(), frame.isLocked, frame.isDocked, frame.isUninteractable;
--This is a temporary chat window. Pass this to whatever handles those options.
end
else
return GetChatWindowInfo(id);
end
end
function FCF_CopyChatSettings(copyTo, copyFrom)
local name, fontSize, r, g, b, a, shown, locked, docked, uninteractable = FCF_GetChatWindowInfo(copyFrom:GetID());
FCF_SetWindowColor(copyTo, r, g, b, 1);
FCF_SetWindowAlpha(copyTo, a, 1);
--If we're copying to a docked window, we don't want to copy locked.
if ( not copyTo.isDocked ) then
FCF_SetLocked(copyTo, locked);
end
FCF_SetUninteractable(copyTo, uninteractable);
FCF_SetChatWindowFontSize(nil, copyTo, fontSize);
end
function FloatingChatFrame_Update(id, onUpdateEvent)
local chatFrame = _G["ChatFrame"..id];
local chatTab = _G["ChatFrame"..id.."Tab"];
local name, fontSize, r, g, b, a, shown, locked, docked, uninteractable = FCF_GetChatWindowInfo(id);
-- Set Tab Name
FCF_SetWindowName(chatFrame, name, 1)
if ( onUpdateEvent ) then
-- Set Frame Color and Alpha
FCF_SetWindowColor(chatFrame, r, g, b, 1);
FCF_SetWindowAlpha(chatFrame, a, 1);
FCF_SetLocked(chatFrame, locked);
FCF_SetUninteractable(chatFrame, uninteractable);
end
if ( shown ) then
if ( not chatFrame.minimized ) then
chatFrame:Show();
end
FCF_SetTabPosition(chatFrame, 0);
else
if ( not chatFrame.isDocked ) then
chatFrame:Hide();
chatTab:Hide();
end
end
if ( docked ) then
FCF_DockFrame(chatFrame, docked, (id == 1));
else
if ( shown ) then
FCF_UnDockFrame(chatFrame);
if ( not chatFrame.minimized ) then
chatTab:Show();
end
elseif ( not chatFrame.isTemporary ) then
FCF_Close(chatFrame);
end
end
if ( not chatFrame.isTemporary and (chatFrame == DEFAULT_CHAT_FRAME or not chatFrame.isDocked)) then
FCF_RestorePositionAndDimensions(chatFrame);
end
FCF_UpdateButtonSide(chatFrame);
end
-- Channel Dropdown
function FCFOptionsDropDown_OnLoad(self)
CURRENT_CHAT_FRAME_ID = self:GetParent():GetID();
UIDropDownMenu_Initialize(self, FCFOptionsDropDown_Initialize, "MENU");
UIDropDownMenu_SetButtonWidth(self, 50);
UIDropDownMenu_SetWidth(self, 50);
end
function FCFOptionsDropDown_Initialize(dropDown)
-- Window preferences
local name, fontSize, r, g, b, a, shown = FCF_GetChatWindowInfo(FCF_GetCurrentChatFrameID());
local info;
local chatFrame = FCF_GetCurrentChatFrame();
local isTemporary = chatFrame and chatFrame.isTemporary;
-- If level 2
if ( UIDROPDOWNMENU_MENU_LEVEL == 2 ) then
-- If this is the font size menu then create dropdown
if ( UIDROPDOWNMENU_MENU_VALUE == FONT_SIZE ) then
-- Add the font heights from the font height table
local value;
for i=1, #CHAT_FONT_HEIGHTS do
value = CHAT_FONT_HEIGHTS[i];
info = UIDropDownMenu_CreateInfo();
info.text = format(FONT_SIZE_TEMPLATE, value);
info.value = value;
info.func = FCF_SetChatWindowFontSize;
local fontFile, fontHeight, fontFlags = FCF_GetCurrentChatFrame():GetFont();
if ( value == floor(fontHeight+0.5) ) then
info.checked = 1;
end
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);
end
return;
end
return;
end
-- Window options
info = UIDropDownMenu_CreateInfo();
local dropDownChatFrame = FCF_GetCurrentChatFrame(dropDown);
if ( dropDownChatFrame and dropDownChatFrame ~= DEFAULT_CHAT_FRAME and dropDownChatFrame.isDocked ) then
info.text = UNDOCK_WINDOW;
elseif ( dropDownChatFrame and dropDownChatFrame.isLocked ) then
info.text = UNLOCK_WINDOW;
else
info.text = LOCK_WINDOW;
end
info.func = FCF_ToggleLock;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
--Add Uninteractable button
info = UIDropDownMenu_CreateInfo();
if ( FCF_GetCurrentChatFrame(dropDown) and FCF_GetCurrentChatFrame(dropDown).isUninteractable) then
info.text = MAKE_INTERACTABLE;
else
info.text = MAKE_UNINTERACTABLE;
end
info.func = FCF_ToggleUninteractable;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
if ( not isTemporary ) then
-- Add name button
info = UIDropDownMenu_CreateInfo();
info.text = RENAME_CHAT_WINDOW;
info.func = FCF_RenameChatWindow_Popup;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
end
if ( chatFrame == DEFAULT_CHAT_FRAME ) then
-- Create new chat window
info = UIDropDownMenu_CreateInfo();
info.text = NEW_CHAT_WINDOW;
info.func = FCF_NewChatWindow;
info.notCheckable = 1;
if (FCF_GetNumActiveChatFrames() == NUM_CHAT_WINDOWS ) then
info.disabled = 1;
end
UIDropDownMenu_AddButton(info);
-- Reset Chat windows to default
info = UIDropDownMenu_CreateInfo();
info.text = RESET_ALL_WINDOWS;
info.func = FCF_ResetAllWindows;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
end
-- Close current chat window
if ( chatFrame and (chatFrame ~= DEFAULT_CHAT_FRAME and not IsCombatLog(chatFrame)) ) then
if ( not chatFrame.isTemporary ) then
info = UIDropDownMenu_CreateInfo();
info.text = CLOSE_CHAT_WINDOW;
info.func = FCF_PopInWindow;
info.arg1 = FCF_GetCurrentChatFrame(dropDown);
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
elseif ( chatFrame.isTemporary and (chatFrame.chatType == "WHISPER" or chatFrame.chatType == "BN_WHISPER") ) then
info = UIDropDownMenu_CreateInfo();
info.text = CLOSE_CHAT_WHISPER_WINDOW;
info.func = FCF_PopInWindow;
info.arg1 = FCF_GetCurrentChatFrame(dropDown);
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
elseif ( chatFrame.isTemporary and (chatFrame.chatType == "BN_CONVERSATION" ) ) then
if ( GetCVar("conversationMode") == "popout" or GetCVar("conversationMode") == "popout_and_inline" ) then
info = UIDropDownMenu_CreateInfo();
info.text = CLOSE_AND_LEAVE_CHAT_CONVERSATION_WINDOW;
info.func = FCF_LeaveConversation;
info.arg1 = FCF_GetCurrentChatFrame(dropDown);
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
else
info = UIDropDownMenu_CreateInfo();
info.text = CLOSE_CHAT_CONVERSATION_WINDOW;
info.func = FCF_PopInWindow;
info.arg1 = FCF_GetCurrentChatFrame(dropDown);
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
end
elseif ( chatFrame.isTemporary ) then
info = UIDropDownMenu_CreateInfo();
info.text = CLOSE_CHAT_WINDOW;
info.func = FCF_Close;
info.arg1 = FCF_GetCurrentChatFrame(dropDown);
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
else
error(format("Unhandled temporary window type. chatType: %s, chatTarget %s", tostring(chatFrame.chatType), tostring(chatFrame.chatTarget)));
end
end
-- Display header
info = UIDropDownMenu_CreateInfo();
info.text = DISPLAY;
info.notClickable = 1;
info.isTitle = 1;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
-- Font size
info = UIDropDownMenu_CreateInfo();
info.text = FONT_SIZE;
--info.notClickable = 1;
info.hasArrow = 1;
info.func = nil;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
-- Set Background color
info = UIDropDownMenu_CreateInfo();
info.text = BACKGROUND;
info.hasColorSwatch = 1;
info.notCheckable = 1;
info.r = r;
info.g = g;
info.b = b;
-- Done because the slider is reversed
if ( a ) then
a = 1- a;
end
info.opacity = a;
info.swatchFunc = FCF_SetChatWindowBackGroundColor;
info.func = UIDropDownMenuButton_OpenColorPicker;
--info.notCheckable = 1;
info.hasOpacity = 1;
info.opacityFunc = FCF_SetChatWindowOpacity;
info.cancelFunc = FCF_CancelWindowColorSettings;
UIDropDownMenu_AddButton(info);
if ( not isTemporary ) then
-- Filter header
info = UIDropDownMenu_CreateInfo();
info.text = FILTERS;
--info.notClickable = 1;
info.isTitle = 1;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
-- Configure settings
info = UIDropDownMenu_CreateInfo();
info.text = CHAT_CONFIGURATION;
info.func = function() ShowUIPanel(ChatConfigFrame); end;
info.notCheckable = 1;
UIDropDownMenu_AddButton(info);
end
end
--[[
function FCFDropDown_LoadServerChannels(...)
local checked;
local channelList = FCF_GetCurrentChatFrame().channelList;
local zoneChannelList = FCF_GetCurrentChatFrame().zoneChannelList;
local info, channel;
-- Server Channels header
info = UIDropDownMenu_CreateInfo();
info.text = SERVER_CHANNELS;
info.notClickable = 1;
info.isTitle = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);
info = UIDropDownMenu_CreateInfo();
for i=1, select("#", ...) do
checked = nil;
channel = select(i, ...);
if ( channelList ) then
for index, value in pairs(channelList) do
if ( value == channel ) then
checked = 1;
end
end
end
if ( zoneChannelList ) then
for index, value in pairs(zoneChannelList) do
if ( value == channel ) then
checked = 1;
end
end
end
info.text = channel;
info.value = channel;
info.func = FCFServerChannelsDropDown_OnClick;
info.checked = checked;
info.keepShownOnClick = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);
end
end
function FCFServerChannelsDropDown_OnClick()
if ( UIDropDownMenuButton_GetChecked() ) then
ChatFrame_RemoveChannel(FCF_GetCurrentChatFrame(), UIDropDownMenuButton_GetName());
else
JoinPermanentChannel(UIDropDownMenuButton_GetName(), nil, FCF_GetCurrentChatFrameID(), 1);
ChatFrame_AddChannel(FCF_GetCurrentChatFrame(), UIDropDownMenuButton_GetName());
end
end
]]
function FCFDropDown_LoadChannels(...)
local checked;
local channelList = FCF_GetCurrentChatFrame().channelList;
local zoneChannelList = FCF_GetCurrentChatFrame().zoneChannelList;
local info = UIDropDownMenu_CreateInfo();
local channel, tag;
for i=1, select("#", ...), 2 do
checked = nil;
tag = "CHANNEL"..select(i, ...);
channel = select(i+1, ...);
if ( channelList ) then
for index, value in pairs(channelList) do
if ( value == channel ) then
checked = 1;
end
end
end
if ( zoneChannelList ) then
for index, value in pairs(zoneChannelList) do
if ( value == channel ) then
checked = 1;
end
end
end
info.text = channel;
info.value = tag;
info.func = FCFChannelDropDown_OnClick;
info.checked = checked;
info.keepShownOnClick = 1;
-- Color the chat channel
local color = ChatTypeInfo[tag];
info.hasColorSwatch = 1;
info.r = color.r;
info.g = color.g;
info.b = color.b;
-- Set the function the color picker calls
info.swatchFunc = FCF_SetChatTypeColor;
info.cancelFunc = FCF_CancelFontColorSettings;
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);
end
end
function FCFChannelDropDown_OnClick()
if ( UIDropDownMenuButton_GetChecked() ) then
ChatFrame_RemoveChannel(FCF_GetCurrentChatFrame(), UIDropDownMenuButton_GetName());
else
ChatFrame_AddChannel(FCF_GetCurrentChatFrame(), UIDropDownMenuButton_GetName());
end
end
-- Used to display chattypegroups
function FCFDropDown_LoadChatTypes(menuChatTypeGroups)
local checked, chatTypeInfo;
local messageTypeList = FCF_GetCurrentChatFrame().messageTypeList;
local info, group;
for index, value in pairs(menuChatTypeGroups) do
checked = nil;
if ( messageTypeList ) then
for joinedIndex, joinedValue in pairs(messageTypeList) do
if ( value == joinedValue ) then
checked = 1;
end
end
end
info = UIDropDownMenu_CreateInfo();
info.value = value;
info.func = FCFMessageTypeDropDown_OnClick;
info.checked = checked;
-- Set to keep shown on button click
info.keepShownOnClick = 1;
-- If more than one message type in a Chat Type Group need to show an expand arrow
group = ChatTypeGroup[value];
if ( getn(group) > 1 ) then
info.text = _G[value];
info.hasArrow = 1;
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);
else
info.text = _G[group[1]];
chatTypeInfo = ChatTypeInfo[FCF_StripChatMsg(group[1])];
-- If no chatTypeInfo then don't display
if ( chatTypeInfo ) then
-- Set the function to be called when a color is set
info.swatchFunc = FCF_SetChatTypeColor;
-- Set the swatch color info
info.hasColorSwatch = 1;
info.r = chatTypeInfo.r;
info.g = chatTypeInfo.g;
info.b = chatTypeInfo.b;
info.cancelFunc = FCF_CancelFontColorSettings;
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);
end
end
end
end
-- Used to display chatsubtypes
function FCF_LoadChatSubTypes(chatGroup)
if ( chatGroup ) then
chatGroup = ChatTypeGroup[chatGroup];
else
chatGroup = ChatTypeGroup[UIDROPDOWNMENU_MENU_VALUE];
end
if ( chatGroup ) then
local info = UIDropDownMenu_CreateInfo();
local chatTypeInfo
for index, value in pairs(chatGroup) do
chatTypeInfo = ChatTypeInfo[FCF_StripChatMsg(value)];
if ( chatTypeInfo ) then
info.text = _G[value];
info.value = FCF_StripChatMsg(value);
-- Disable the button and color the text white
info.notClickable = 1;
-- Set to be notcheckable
info.notCheckable = 1;
-- Set the function to be called when a color is set
info.swatchFunc = FCF_SetChatTypeColor;
-- Set the swatch color info
info.hasColorSwatch = 1;
info.r = chatTypeInfo.r;
info.g = chatTypeInfo.g;
info.b = chatTypeInfo.b;
-- Set function called when cancel is clicked in the colorpicker
info.cancelFunc = FCF_CancelFontColorSettings;
UIDropDownMenu_AddButton(info, UIDROPDOWNMENU_MENU_LEVEL);
end
end
end
end
function FCFMessageTypeDropDown_OnClick(self)
if ( UIDropDownMenuButton_GetChecked() ) then
ChatFrame_RemoveMessageGroup(FCF_GetCurrentChatFrame(), self.value);
else
ChatFrame_AddMessageGroup(FCF_GetCurrentChatFrame(), self.value);
end
end
function FCF_OpenNewWindow(name)
local count = 1;
local chatFrame, chatTab;
for i=1, NUM_CHAT_WINDOWS do
local _, _, _, _, _, _, shown = FCF_GetChatWindowInfo(i);
chatFrame = _G["ChatFrame"..i];
chatTab = _G["ChatFrame"..i.."Tab"];
if ( (not shown and not chatFrame.isDocked) or (count == NUM_CHAT_WINDOWS) ) then
if ( not name or name == "" ) then
name = format(CHAT_NAME_TEMPLATE, i);
end
-- initialize the frame
FCF_SetWindowName(chatFrame, name);
FCF_SetWindowColor(chatFrame, DEFAULT_CHATFRAME_COLOR.r, DEFAULT_CHATFRAME_COLOR.g, DEFAULT_CHATFRAME_COLOR.b);
FCF_SetWindowAlpha(chatFrame, DEFAULT_CHATFRAME_ALPHA);
SetChatWindowLocked(i, nil);
-- clear stale messages
chatFrame:Clear();
-- Listen to the standard messages
ChatFrame_RemoveAllMessageGroups(chatFrame);
ChatFrame_RemoveAllChannels(chatFrame);
ChatFrame_ReceiveAllPrivateMessages(chatFrame);
ChatFrame_ReceiveAllBNConversations(chatFrame);
ChatFrame_AddMessageGroup(chatFrame, "SAY");
ChatFrame_AddMessageGroup(chatFrame, "YELL");
ChatFrame_AddMessageGroup(chatFrame, "GUILD");
ChatFrame_AddMessageGroup(chatFrame, "WHISPER");
ChatFrame_AddMessageGroup(chatFrame, "BN_WHISPER");
ChatFrame_AddMessageGroup(chatFrame, "PARTY");
ChatFrame_AddMessageGroup(chatFrame, "PARTY_LEADER");
ChatFrame_AddMessageGroup(chatFrame, "CHANNEL");
--Clear the edit box history.
chatFrame.editBox:ClearHistory();
-- Show the frame and tab
chatFrame:Show();
chatTab:Show();
SetChatWindowShown(i, 1);
-- Dock the frame by default
FCF_DockFrame(chatFrame, (#FCFDock_GetChatFrames(GENERAL_CHAT_DOCK)+1), true);
FCF_FadeInChatFrame(FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK));
return chatFrame;
end
count = count + 1;
end
end
function FCF_SetTemporaryWindowType(chatFrame, chatType, chatTarget)
local chatTab = _G[chatFrame:GetName().."Tab"];
--If the frame was already registered, unregister it.
if ( chatFrame.isRegistered ) then
FCFManager_UnregisterDedicatedFrame(chatFrame, chatFrame.chatType, chatFrame.chatTarget);
chatFrame.isRegistered = false;
end
--Set the title text
local name;
if ( chatType == "WHISPER" or chatType == "BN_WHISPER" ) then
name = chatTarget;
elseif ( chatType == "BN_CONVERSATION" ) then
name = format(CONVERSATION_NAME, tonumber(chatTarget) + MAX_WOW_CHAT_CHANNELS);
elseif ( chatType == "PET_BATTLE_COMBAT_LOG" ) then
name = PET_BATTLE_COMBAT_LOG;
end
FCF_SetWindowName(chatFrame, name);
--Set up the window to receive the message types we want.
chatFrame.chatType = chatType;
chatFrame.chatTarget = chatTarget;
ChatFrame_RemoveAllMessageGroups(chatFrame);
ChatFrame_RemoveAllChannels(chatFrame);
ChatFrame_ReceiveAllPrivateMessages(chatFrame);
ChatFrame_ReceiveAllBNConversations(chatFrame);
ChatFrame_AddMessageGroup(chatFrame, chatType);
-- This is to display "friend is online"/"friend is offline" messages
if ( chatType == "BN_WHISPER" ) then
ChatFrame_AddSingleMessageType(chatFrame, "CHAT_MSG_BN_INLINE_TOAST_ALERT");
ChatFrame_AddSingleMessageType(chatFrame, "CHAT_MSG_BN_WHISPER_PLAYER_OFFLINE");
elseif ( chatType == "WHISPER" ) then
ChatFrame_AddSingleMessageType(chatFrame, "CHAT_MSG_SYSTEM");
elseif ( chatType == "PET_BATTLE_COMBAT_LOG" ) then
ChatFrame_AddMessageGroup(chatFrame, "PET_BATTLE_INFO");
end
chatFrame.editBox:SetAttribute("chatType", chatType);
chatFrame.editBox:SetAttribute("stickyType", chatType);
if ( chatType == "WHISPER" or chatType == "BN_WHISPER" ) then
chatFrame.editBox:SetAttribute("tellTarget", chatTarget);
ChatFrame_AddPrivateMessageTarget(chatFrame, chatTarget);
elseif ( chatType == "BN_CONVERSATION" ) then
chatFrame.editBox:SetAttribute("channelTarget", chatTarget);
ChatFrame_AddBNConversationTarget(chatFrame, chatTarget);
elseif ( chatType == "PET_BATTLE_COMBAT_LOG" ) then
chatFrame.editBox:SetAttribute("chatType", "SAY");
chatFrame.editBox:SetAttribute("stickyType", "SAY");
end
-- Set up the colors
local info = ChatTypeInfo[chatType];
chatTab.selectedColorTable = { r = info.r, g = info.g, b = info.b };
FCFTab_UpdateColors(chatTab, not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK));
--If it's a conversation, create the conversation button
if ( chatType == "BN_CONVERSATION" or chatType == "BN_WHISPER" ) then
if ( chatFrame.conversationButton ) then
BNConversationButton_UpdateTarget(chatFrame.conversationButton);
chatFrame.conversationButton:Show();
else
CreateFrame("Button", chatFrame:GetName().."ConversationButton", chatFrame.buttonFrame, "BNConversationRosterButtonTemplate", chatFrame:GetID());
end
if ( chatFrame:GetHeight() < CHAT_FRAME_BIGGER_MIN_HEIGHT ) then
chatFrame:SetHeight(CHAT_FRAME_BIGGER_MIN_HEIGHT);
end
chatFrame:SetMinResize(CHAT_FRAME_MIN_WIDTH, CHAT_FRAME_BIGGER_MIN_HEIGHT);
else
if ( chatFrame.conversationButton ) then
chatFrame.conversationButton:Hide();
end
chatFrame:SetMinResize(CHAT_FRAME_MIN_WIDTH, CHAT_FRAME_NORMAL_MIN_HEIGHT);
end
--If it's a conversation, get it ready to convert to a whisper if needed.
if ( chatType == "BN_CONVERSATION" ) then
chatFrame:RegisterEvent("BN_CHAT_CHANNEL_CLOSED");
else
chatFrame:UnregisterEvent("BN_CHAT_CHANNEL_CLOSED");
end
--Set the icon
local conversationIcon;
if ( chatType == "WHISPER" or chatType == "BN_WHISPER" ) then
conversationIcon = "Interface\\ChatFrame\\UI-ChatWhisperIcon";
elseif ( chatType == "PET_BATTLE_COMBAT_LOG" ) then
conversationIcon = "Interface\\Icons\\Tracking_WildPet";
else
conversationIcon = "Interface\\ChatFrame\\UI-ChatConversationIcon";
end
chatTab.conversationIcon:SetTexture(conversationIcon);
if ( chatFrame.minFrame ) then
chatFrame.minFrame.conversationIcon:SetTexture(conversationIcon);
end
--Register this frame
FCFManager_RegisterDedicatedFrame(chatFrame, chatType, chatTarget);
chatFrame.isRegistered = true;
--The window name may have been updated, so update the dock and tabs.
FCF_DockUpdate();
end
local maxTempIndex = NUM_CHAT_WINDOWS + 1;
function FCF_OpenTemporaryWindow(chatType, chatTarget, sourceChatFrame, selectWindow)
local chatFrame, chatTab, conversationIcon;
for _, chatFrameName in pairs(CHAT_FRAMES) do
local frame = _G[chatFrameName];
if ( frame.isTemporary ) then
if ( not frame.inUse and not frame.isDocked ) then
chatFrame = frame;
chatTab = _G[chatFrame:GetName().."Tab"];
break;
end
end
end
if ( not chatFrame ) then
chatTab = CreateFrame("Button", "ChatFrame"..maxTempIndex.."Tab", UIParent, "ChatTabTemplate", maxTempIndex);
conversationIcon = chatTab:CreateTexture(chatTab:GetName().."ConversationIcon", "ARTWORK", "ChatTabConversationIconTemplate");
conversationIcon:ClearAllPoints();
conversationIcon:SetPoint("RIGHT", chatTab:GetFontString(), "LEFT", 0, -2);
chatTab.conversationIcon = conversationIcon;
local tabText = _G[chatTab:GetName().."Text"];
tabText:SetPoint("LEFT", chatTab.leftTexture, "RIGHT", 10, -6);
tabText:SetJustifyH("LEFT");
chatTab.sizePadding = 10;
chatFrame = CreateFrame("ScrollingMessageFrame", "ChatFrame"..maxTempIndex, UIParent, "FloatingChatFrameTemplate", maxTempIndex);
if ( GetCVarBool("chatMouseScroll") ) then
chatFrame:SetScript("OnMouseWheel", FloatingChatFrame_OnMouseScroll);
chatFrame:EnableMouseWheel(true);
end
maxTempIndex = maxTempIndex + 1;
end
--Copy chat settings from the source frame.
FCF_CopyChatSettings(chatFrame, sourceChatFrame or DEFAULT_CHAT_FRAME);
-- clear stale messages
chatFrame:Clear();
chatFrame.inUse = true;
chatFrame.isTemporary = true;
FCF_SetTemporaryWindowType(chatFrame, chatType, chatTarget);
--Clear the edit box history.
chatFrame.editBox:ClearHistory();
if ( sourceChatFrame ) then
--Copy over messages
local accessID = ChatHistory_GetAccessID(chatType, chatTarget);
for i = 1, sourceChatFrame:GetNumMessages(accessID) do
local text, accessID, lineID, extraData = sourceChatFrame:GetMessageInfo(i, accessID);
local cType, cTarget = ChatHistory_GetChatType(extraData);
local info = ChatTypeInfo[cType];
chatFrame:AddMessage(text, info.r, info.g, info.b, lineID, false, accessID, extraData);
end
--Stop displaying this type of chat in the old chat frame.
--Remove the messages from the old frame.
if (not (chatType == "WHISPER" and GetCVar("whisperMode") == "popout_and_inline")
and not (chatType == "BN_WHISPER" and GetCVar("bnWhisperMode") == "popout_and_inline")
and not (chatType == "BN_CONVERSATION" and GetCVar("conversationMode") == "popout_and_inline") ) then
if ( chatType == "WHISPER" or chatType == "BN_WHISPER" ) then
ChatFrame_ExcludePrivateMessageTarget(sourceChatFrame, chatTarget);
elseif ( chatType == "BN_CONVERSATION" ) then
ChatFrame_ExcludeBNConversationTarget(sourceChatFrame, chatTarget);
end
sourceChatFrame:RemoveMessagesByAccessID(accessID);
end
end
--Close the Editbox
ChatEdit_DeactivateChat(chatFrame.editBox);
-- Show the frame and tab
chatFrame:Show();
chatTab:Show();
-- Dock the frame by default
FCF_DockFrame(chatFrame, (#FCFDock_GetChatFrames(GENERAL_CHAT_DOCK)+1), selectWindow);
return chatFrame;
end
function FCF_RemoveAllMessagesFromChanSender(chatFrame, chanSender)
local ids = ChatHistory_GetAllAccessIDsByChanSender(chanSender);
for i=1, #ids do
chatFrame:RemoveMessagesByExtraData(ids[i]);
end
end
function FCF_GetNumActiveChatFrames()
local count = 0;
local chatFrame;
for i=1, NUM_CHAT_WINDOWS do
local _, _, _, _, _, _, shown = FCF_GetChatWindowInfo(i);
chatFrame = _G["ChatFrame"..i];
if ( chatFrame ) then
if ( shown or chatFrame.isDocked ) then
count = count + 1;
end
end
end
return count;
end
function FCF_RenameChatWindow_Popup()
local dialog = StaticPopup_Show("NAME_CHAT");
dialog.data = FCF_GetCurrentChatFrameID();
end
function FCF_NewChatWindow()
StaticPopup_Show("NAME_CHAT");
end
function FCF_ResetAllWindows()
StaticPopup_Show("RESET_CHAT");
end
--[[function FCF_ChatChannels()
ToggleFriendsFrame(3);
end]]--
function FCF_SetWindowName(frame, name, doNotSave)
if ( not name or name == "") then
-- Hack to initialize the chat window names, since globalstrings are not available on init
if ( frame:GetID() == 1 ) then
name = GENERAL;
doNotSave = nil;
elseif ( frame:GetID() == 2 ) then
name = COMBAT_LOG;
doNotSave = nil;
else
name = format(CHAT_NAME_TEMPLATE, frame:GetID());
end
else
FCFDock_SetDirty(GENERAL_CHAT_DOCK);
end
frame.name = name;
local tab = _G[frame:GetName().."Tab"];
tab:SetText(name);
PanelTemplates_TabResize(tab, tab.sizePadding or 0);
-- Save this off so we know how big the tab should always be, even if it gets shrunken on the dock.
tab.textWidth = _G[tab:GetName().."Text"]:GetWidth();
if ( not doNotSave ) then
SetChatWindowName(frame:GetID(), name);
end
if ( frame.minFrame ) then
frame.minFrame:SetText(name);
end
end
function FCF_SetWindowColor(frame, r, g, b, doNotSave)
local name = frame:GetName();
for index, value in pairs(CHAT_FRAME_TEXTURES) do
--NOTE - If this is changed, please change the equivalent code in GMChatFrame_OnLoad.
local object = _G[name..value];
local objectType = object:GetObjectType();
if ( objectType == "Button" ) then
object:GetNormalTexture():SetVertexColor(r, g, b);
object:GetHighlightTexture():SetVertexColor(r, g, b);
object:GetPushedTexture():SetVertexColor(r, g, b);
elseif ( objectType == "Texture" ) then
_G[name..value]:SetVertexColor(r,g,b);
else
--error("Unhandled frame type...");
end
end
if ( not doNotSave ) then
SetChatWindowColor(frame:GetID(), r, g, b);
end
end
function FCF_SetWindowAlpha(frame, alpha, doNotSave)
local name = frame:GetName();
for index, value in pairs(CHAT_FRAME_TEXTURES) do
_G[name..value]:SetAlpha(alpha);
end
if ( not doNotSave ) then
SetChatWindowAlpha(frame:GetID(), alpha);
end
-- Remember the alpha
frame.oldAlpha = alpha;
end
function FCF_GetCurrentChatFrameID()
return CURRENT_CHAT_FRAME_ID;
end
function FCF_GetCurrentChatFrame(child)
local currentChatFrame = nil;
if ( CURRENT_CHAT_FRAME_ID ) then
currentChatFrame = _G["ChatFrame"..CURRENT_CHAT_FRAME_ID];
end
if ( not currentChatFrame and child ) then
currentChatFrame = _G["ChatFrame"..child:GetParent():GetID()];
end
return currentChatFrame;
end
function FCF_SetChatTypeColor()
local r,g,b = ColorPickerFrame:GetColorRGB();
ChangeChatColor(UIDROPDOWNMENU_MENU_VALUE, r, g, b);
end
function FCF_SetChatWindowBackGroundColor()
local r,g,b = ColorPickerFrame:GetColorRGB();
FCF_SetWindowColor(FCF_GetCurrentChatFrame(), r, g, b)
SetChatWindowColor(FCF_GetCurrentChatFrameID(), r, g, b);
end
function FCF_SetChatWindowOpacity()
local alpha = 1.0 - OpacitySliderFrame:GetValue();
FCF_SetWindowAlpha(FCF_GetCurrentChatFrame(), alpha);
end
function FCF_SetChatWindowFontSize(self, chatFrame, fontSize)
if ( not chatFrame ) then
chatFrame = FCF_GetCurrentChatFrame();
end
if ( not fontSize ) then
fontSize = self.value;
end
local fontFile, unused, fontFlags = chatFrame:GetFont();
chatFrame:SetFont(fontFile, fontSize, fontFlags);
if ( GMChatFrame and chatFrame == DEFAULT_CHAT_FRAME ) then
GMChatFrame:SetFont(fontFile, fontSize, fontFlags);
end
SetChatWindowSize(chatFrame:GetID(), fontSize);
end
function FCF_CancelFontColorSettings(previousValues)
if ( previousValues.r ) then
ChangeChatColor(UIDROPDOWNMENU_MENU_VALUE, previousValues.r, previousValues.g, previousValues.b);
end
end
function FCF_CancelWindowColorSettings(previousValues)
if ( previousValues.r ) then
FCF_SetWindowColor(FCF_GetCurrentChatFrame(), previousValues.r, previousValues.g, previousValues.b)
SetChatWindowColor(FCF_GetCurrentChatFrameID(), previousValues.r, previousValues.g, previousValues.b);
end
if ( previousValues.opacity ) then
FCF_SetWindowAlpha(FCF_GetCurrentChatFrame(), 1 - previousValues.opacity);
end
end
function FCF_StripChatMsg(string)
if ( strsub(string,1,8) == "CHAT_MSG" ) then
return strsub(string,10);
else
return string;
end
end
function FCF_ToggleLock()
local chatFrame = FCF_GetCurrentChatFrame();
if ( chatFrame.isLocked ) then
-- If unlocking a docked frame then undock it and center it on the screen
if ( chatFrame.isDocked and chatFrame ~= DEFAULT_CHAT_FRAME ) then
FCF_UnDockFrame(chatFrame);
chatFrame:ClearAllPoints();
chatFrame:SetPoint("CENTER", "UIParent", "CENTER", 0, 0);
FCF_SetTabPosition(chatFrame, 0);
chatFrame:Show();
end
FCF_SetLocked(chatFrame, nil);
else
FCF_SetLocked(chatFrame, 1);
end
end
function FCF_SetLocked(chatFrame, isLocked)
chatFrame.isLocked = isLocked;
if ( chatFrame.isUninteractable or isLocked ) then
chatFrame.resizeButton:Hide();
else
chatFrame.resizeButton:Show();
--chatFrame.resizeButton:SetAlpha(_G[chatFrame:GetName().."Background"]:GetAlpha());
end
SetChatWindowLocked(chatFrame:GetID(), isLocked);
end
function FCF_ToggleUninteractable()
local chatFrame = FCF_GetCurrentChatFrame();
if ( chatFrame.isUninteractable ) then
FCF_SetExpandedUninteractable(chatFrame, false)
else
FCF_SetExpandedUninteractable(chatFrame, true)
end
end
function FCF_SetExpandedUninteractable(chatFrame, isUninteractable)
if ( chatFrame.isDocked ) then
for _, frame in pairs(GENERAL_CHAT_DOCK.DOCKED_CHAT_FRAMES) do
FCF_SetUninteractable(frame, isUninteractable);
end
else
FCF_SetUninteractable(chatFrame, isUninteractable);
end
end
function FCF_SetUninteractable(chatFrame, isUninteractable) --No, uninteractable is not really a word.
chatFrame.isUninteractable = isUninteractable;
SetChatWindowUninteractable(chatFrame:GetID(), isUninteractable);
if ( not chatFrame.overrideHyperlinksEnabled ) then
chatFrame:SetHyperlinksEnabled(not isUninteractable);
end
local chatFrameName = chatFrame:GetName();
if ( isUninteractable or chatFrame.isLocked ) then
_G[chatFrameName.."ResizeButton"]:Hide();
else
_G[chatFrameName.."ResizeButton"]:Show();
end
end
function FCF_FadeInChatFrame(chatFrame)
local frameName = chatFrame:GetName();
chatFrame.hasBeenFaded = true;
for index, value in pairs(CHAT_FRAME_TEXTURES) do
local object = _G[frameName..value];
if ( object:IsShown() ) then
UIFrameFadeIn(object, CHAT_FRAME_FADE_TIME, object:GetAlpha(), max(chatFrame.oldAlpha, DEFAULT_CHATFRAME_ALPHA));
end
end
if ( chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) ) then
for _, frame in pairs(FCFDock_GetChatFrames(GENERAL_CHAT_DOCK)) do
if ( frame ~= chatFrame ) then
FCF_FadeInChatFrame(frame);
end
end
if ( GENERAL_CHAT_DOCK.overflowButton:IsShown() ) then
UIFrameFadeIn(GENERAL_CHAT_DOCK.overflowButton, CHAT_FRAME_FADE_TIME, GENERAL_CHAT_DOCK.overflowButton:GetAlpha(), CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA);
end
end
local chatTab = _G[frameName.."Tab"];
UIFrameFadeIn(chatTab, CHAT_FRAME_FADE_TIME, chatTab:GetAlpha(), chatTab.mouseOverAlpha);
--Fade in the button frame
if ( not chatFrame.isDocked ) then
UIFrameFadeIn(chatFrame.buttonFrame, CHAT_FRAME_FADE_TIME, chatFrame.buttonFrame:GetAlpha(), 1);
end
end
function FCF_FadeOutChatFrame(chatFrame)
local frameName = chatFrame:GetName();
chatFrame.hasBeenFaded = nil;
for index, value in pairs(CHAT_FRAME_TEXTURES) do
-- Fade out chat frame
local object = _G[frameName..value];
if ( object:IsShown() ) then
UIFrameFadeOut(object, CHAT_FRAME_FADE_OUT_TIME, max(object:GetAlpha(), chatFrame.oldAlpha), chatFrame.oldAlpha);
end
end
if ( chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) ) then
for _, frame in pairs(FCFDock_GetChatFrames(GENERAL_CHAT_DOCK)) do
if ( frame ~= chatFrame ) then
FCF_FadeOutChatFrame(frame);
end
end
if ( GENERAL_CHAT_DOCK.overflowButton:IsShown() ) then
UIFrameFadeOut(GENERAL_CHAT_DOCK.overflowButton, CHAT_FRAME_FADE_OUT_TIME, GENERAL_CHAT_DOCK.overflowButton:GetAlpha(), CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA);
end
end
local chatTab = _G[frameName.."Tab"];
UIFrameFadeOut(chatTab, CHAT_FRAME_FADE_OUT_TIME, chatTab:GetAlpha(), chatTab.noMouseAlpha);
--Fade out the ButtonFrame
if ( not chatFrame.isDocked ) then
UIFrameFadeOut(chatFrame.buttonFrame, CHAT_FRAME_FADE_OUT_TIME, chatFrame.buttonFrame:GetAlpha(), CHAT_FRAME_BUTTON_FRAME_MIN_ALPHA);
end
end
local LAST_CURSOR_X, LAST_CURSOR_Y;
function FCF_OnUpdate(elapsed)
local cursorX, cursorY = GetCursorPosition();
local overSomething = false;
for _, frameName in pairs(CHAT_FRAMES) do
local chatFrame = _G[frameName];
if ( chatFrame:IsShown() ) then
local topOffset = 28;
if ( IsCombatLog(chatFrame) ) then
topOffset = topOffset + CombatLogQuickButtonFrame_Custom:GetHeight();
end
--Items that will always cause the frame to fade in.
if ( MOVING_CHATFRAME or chatFrame.resizeButton:GetButtonState() == "PUSHED" or (chatFrame.isDocked and GENERAL_CHAT_DOCK.overflowButton.list:IsShown())) then
overSomething = true;
chatFrame.mouseOutTime = 0;
if ( not chatFrame.hasBeenFaded ) then
overSomething = true;
FCF_FadeInChatFrame(chatFrame);
end
--Things that will cause the frame to fade in if the mouse is stationary.
elseif ( chatFrame:IsMouseOver(topOffset, -2, -2, 2) or --This should be slightly larger than the hit rect insets to give us some wiggle room.
(chatFrame.isDocked and FriendsMicroButton:IsMouseOver()) or
(chatFrame.buttonFrame:IsMouseOver())) then
overSomething = true;
chatFrame.mouseOutTime = 0;
if ( cursorX == LAST_CURSOR_X and cursorY == LAST_CURSOR_Y and not chatFrame.hasBeenFaded ) then
chatFrame.mouseInTime = (chatFrame.mouseInTime or 0) + elapsed;
if ( chatFrame.mouseInTime > CHAT_TAB_SHOW_DELAY ) then
FCF_FadeInChatFrame(chatFrame);
end
else
chatFrame.mouseInTime = 0;
end
elseif ( chatFrame:IsShown() and chatFrame.hasBeenFaded ) then
chatFrame.mouseInTime = 0;
chatFrame.mouseOutTime = (chatFrame.mouseOutTime or 0) + elapsed;
if ( chatFrame.mouseOutTime > CHAT_TAB_HIDE_DELAY ) then
FCF_FadeOutChatFrame(chatFrame);
end
end
end
end
LAST_CURSOR_X, LAST_CURSOR_Y = cursorX, cursorY;
end
function FCF_SavePositionAndDimensions(chatFrame)
local centerX = chatFrame:GetLeft() + chatFrame:GetWidth() / 2;
local centerY = chatFrame:GetBottom() + chatFrame:GetHeight() / 2;
local horizPoint, vertPoint;
local screenWidth, screenHeight = GetScreenWidth(), GetScreenHeight();
local xOffset, yOffset;
if ( centerX > screenWidth / 2 ) then
horizPoint = "RIGHT";
xOffset = (chatFrame:GetRight() - screenWidth)/screenWidth;
else
horizPoint = "LEFT";
xOffset = chatFrame:GetLeft()/screenWidth;
end
if ( centerY > screenHeight / 2 ) then
vertPoint = "TOP";
yOffset = (chatFrame:GetTop() - screenHeight)/screenHeight;
else
vertPoint = "BOTTOM";
yOffset = chatFrame:GetBottom()/screenHeight;
end
SetChatWindowSavedPosition(chatFrame:GetID(), vertPoint..horizPoint, xOffset, yOffset);
SetChatWindowSavedDimensions(chatFrame:GetID(), chatFrame:GetWidth(), chatFrame:GetHeight());
end
function FCF_RestorePositionAndDimensions(chatFrame)
local width, height = GetChatWindowSavedDimensions(chatFrame:GetID());
if ( width and height ) then
chatFrame:SetSize(width, height);
end
local point, xOffset, yOffset = GetChatWindowSavedPosition(chatFrame:GetID());
if ( point ) then
chatFrame:ClearAllPoints();
chatFrame:SetPoint(point, xOffset * GetScreenWidth(), yOffset * GetScreenHeight());
chatFrame:SetUserPlaced(true);
else
chatFrame:SetUserPlaced(false);
end
end
-- Docking handling functions
function FCF_StopDragging(chatFrame)
chatFrame:StopMovingOrSizing();
_G[chatFrame:GetName().."Tab"]:UnlockHighlight();
FCFDock_HideInsertHighlight(GENERAL_CHAT_DOCK);
if ( GENERAL_CHAT_DOCK:IsMouseOver(10, -10, 0, 10) ) then
local mouseX, mouseY = GetCursorPosition();
mouseX, mouseY = mouseX / UIParent:GetScale(), mouseY / UIParent:GetScale();
FCF_DockFrame(chatFrame, FCFDock_GetInsertIndex(GENERAL_CHAT_DOCK, chatFrame, mouseX, mouseY), true);
else
FCF_SetTabPosition(chatFrame, 0);
end
FCF_SavePositionAndDimensions(chatFrame);
MOVING_CHATFRAME = nil;
end
function FCFTab_OnUpdate(self, elapsed)
local cursorX, cursorY = GetCursorPosition();
cursorX, cursorY = cursorX / UIParent:GetScale(), cursorY / UIParent:GetScale();
local chatFrame = _G["ChatFrame"..self:GetID()];
if ( chatFrame ~= GENERAL_CHAT_DOCK.primary and GENERAL_CHAT_DOCK:IsMouseOver(10, -10, 0, 10) ) then
FCFDock_PlaceInsertHighlight(GENERAL_CHAT_DOCK, chatFrame, cursorX, cursorY);
else
FCFDock_HideInsertHighlight(GENERAL_CHAT_DOCK);
end
FCF_UpdateButtonSide(chatFrame);
if ( chatFrame == GENERAL_CHAT_DOCK.primary ) then
for _, frame in pairs(FCFDock_GetChatFrames(GENERAL_CHAT_DOCK)) do
FCF_SetButtonSide(frame, FCF_GetButtonSide(GENERAL_CHAT_DOCK.primary));
end
end
if ( not IsMouseButtonDown(self.dragButton) ) then
FCFTab_OnDragStop(self, self.dragButton);
self.dragButton = nil;
self:SetScript("OnUpdate", nil);
end
if ( BNToastFrame and BNToastFrame:IsShown() ) then
BNToastFrame_UpdateAnchor();
end
end
function FCFTab_OnDragStop(self, button)
FCF_StopDragging(_G["ChatFrame"..self:GetID()]);
end
DEFAULT_TAB_SELECTED_COLOR_TABLE = { r = 1, g = 0.5, b = 0.25 };
function FCFTab_UpdateColors(self, selected)
if ( selected ) then
self.leftSelectedTexture:Show();
self.middleSelectedTexture:Show();
self.rightSelectedTexture:Show();
else
self.leftSelectedTexture:Hide();
self.middleSelectedTexture:Hide();
self.rightSelectedTexture:Hide();
end
local colorTable = self.selectedColorTable or DEFAULT_TAB_SELECTED_COLOR_TABLE;
if ( self.selectedColorTable ) then
self:GetFontString():SetTextColor(colorTable.r, colorTable.g, colorTable.b);
else
self:GetFontString():SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
end
self.leftSelectedTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
self.middleSelectedTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
self.rightSelectedTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
self.leftHighlightTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
self.middleHighlightTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
self.rightHighlightTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
self.glow:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
if ( self.conversationIcon ) then
self.conversationIcon:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
end
local minimizedFrame = _G["ChatFrame"..self:GetID().."Minimized"];
if ( minimizedFrame ) then
minimizedFrame.selectedColorTable = self.selectedColorTable;
FCFMin_UpdateColors(minimizedFrame);
end
end
function FCFTab_UpdateAlpha(chatFrame)
local chatTab = _G[chatFrame:GetName().."Tab"];
if ( not chatFrame.isDocked or chatFrame == FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) ) then
chatTab.mouseOverAlpha = CHAT_FRAME_TAB_SELECTED_MOUSEOVER_ALPHA;
chatTab.noMouseAlpha = CHAT_FRAME_TAB_SELECTED_NOMOUSE_ALPHA;
else
if ( chatTab.alerting ) then
chatTab.mouseOverAlpha = CHAT_FRAME_TAB_ALERTING_MOUSEOVER_ALPHA;
chatTab.noMouseAlpha = CHAT_FRAME_TAB_ALERTING_NOMOUSE_ALPHA;
else
chatTab.mouseOverAlpha = CHAT_FRAME_TAB_NORMAL_MOUSEOVER_ALPHA;
chatTab.noMouseAlpha = CHAT_FRAME_TAB_NORMAL_NOMOUSE_ALPHA;
end
end
-- If this is in the middle of fading, stop it, since we're about to set the alpha
UIFrameFadeRemoveFrame(chatTab);
if ( chatFrame.hasBeenFaded ) then
chatTab:SetAlpha(chatTab.mouseOverAlpha);
else
chatTab:SetAlpha(chatTab.noMouseAlpha);
end
end
function FCF_HideOnFadeFinished(frame)
frame:Hide();
end
function FCF_IsValidChatFrame(chatFrame)
-- Break out all the cases individually because the logic gets convoluted
if ( chatFrame == MOVING_CHATFRAME ) then
return nil;
end
if ( not chatFrame:IsShown() and not chatFrame.isDocked ) then
return nil;
end
return 1;
end
function FCF_UpdateButtonSide(chatFrame)
local leftDist = chatFrame:GetLeft();
local rightDist = GetScreenWidth() - chatFrame:GetRight();
local changed = nil;
if (( leftDist > 0 and leftDist <= rightDist ) or rightDist < 0 ) then
if ( chatFrame.buttonSide ~= "left" ) then
FCF_SetButtonSide(chatFrame, "left");
changed = 1;
end
else
if ( chatFrame.buttonSide ~= "right" or leftDist < 0 ) then
FCF_SetButtonSide(chatFrame, "right");
changed = 1;
end
end
return changed;
end
function FCF_SetButtonSide(chatFrame, buttonSide, forceUpdate)
if ( not forceUpdate and chatFrame.buttonSide == buttonSide ) then
return;
end
chatFrame.buttonFrame:ClearAllPoints();
local topY = 0;
if ( IsCombatLog(chatFrame) ) then
topY = topY + CombatLogQuickButtonFrame_Custom:GetHeight();
end
if ( buttonSide == "left" ) then
chatFrame.buttonFrame:SetPoint("TOPRIGHT", chatFrame, "TOPLEFT", -4, topY);
chatFrame.buttonFrame:SetPoint("BOTTOMRIGHT", chatFrame, "BOTTOMLEFT", -4, 0);
elseif ( buttonSide == "right" ) then
chatFrame.buttonFrame:SetPoint("TOPLEFT", chatFrame, "TOPRIGHT", 4, topY);
chatFrame.buttonFrame:SetPoint("BOTTOMLEFT", chatFrame, "BOTTOMRIGHT", 4, 0);
end
chatFrame.buttonSide = buttonSide;
if ( chatFrame == DEFAULT_CHAT_FRAME ) then
ChatFrameMenu_UpdateAnchorPoint();
end
end
function FCF_StartAlertFlash(chatFrame)
if ( chatFrame.minFrame ) then
UIFrameFlash(chatFrame.minFrame.glow, 1.0, 1.0, -1, false, 0, 0, "chat");
chatFrame.minFrame.alerting = true;
end
local chatTab = _G[chatFrame:GetName().."Tab"];
UIFrameFlash(chatTab.glow, 1.0, 1.0, -1, false, 0, 0, "chat");
chatTab.alerting = true;
FCFTab_UpdateAlpha(chatFrame);
FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton);
end
function FCF_StopAlertFlash(chatFrame)
if ( chatFrame.minFrame ) then
UIFrameFlashStop(chatFrame.minFrame.glow);
chatFrame.minFrame.alerting = false;
end
local chatTab = _G[chatFrame:GetName().."Tab"];
UIFrameFlashStop(chatTab.glow);
chatTab.alerting = false;
FCFTab_UpdateAlpha(chatFrame);
FCFDockOverflowButton_UpdatePulseState(GENERAL_CHAT_DOCK.overflowButton);
end
function FCF_GetButtonSide(chatFrame)
return chatFrame.buttonSide;
end
function FCF_DockUpdate()
FCFDock_UpdateTabs(GENERAL_CHAT_DOCK, true);
end
--[[
local numDockedFrames = getn(DOCKED_CHAT_FRAMES);
local dockRegion, chatTab, previousDockedFrame;
local dockWidth = 0;
local previousDockRegion;
local name;
for index, value in pairs(DOCKED_CHAT_FRAMES) do
-- If not the initial chatframe then anchor the frame to the base chatframe
name = value:GetName();
if ( index ~= 1 ) then
value:ClearAllPoints();
value:SetPoint("TOPLEFT", DEFAULT_CHAT_FRAME, "TOPLEFT", 0, 0);
value:SetPoint("BOTTOMLEFT", DEFAULT_CHAT_FRAME, "BOTTOMLEFT", 0, 0);
value:SetPoint("BOTTOMRIGHT", DEFAULT_CHAT_FRAME, "BOTTOMRIGHT", 0, 0);
end
-- Select or deselect the frame
chatTab = _G[value:GetName().."Tab"];
-- chatTab.textWidth is the original width of the text name of the tab
-- We need to use this as an absolute measure of the text's width is altered when the chat dock gets too small
-- If the text is shrunken the original width is lost, unless we save it and use it in the following manner
-- This is a fix for Bug ID: 71180
PanelTemplates_TabResize(chatTab, 5, nil, nil, nil, chatTab.textWidth);
if ( value == SELECTED_DOCK_FRAME ) then
value:Show();
if ( chatTab:IsShown() ) then
chatTab:SetAlpha(1.0);
end
else
value:Hide();
if ( chatTab:IsShown() ) then
chatTab:SetAlpha(0.5);
end
end
-- If there was a frame before this frame then anchor the tab
if ( previousDockedFrame ) then
chatTab:ClearAllPoints();
FCF_SetTabPosition(value, dockWidth);
_G[previousDockedFrame:GetName().."TabDockRegion"]:SetPoint("RIGHT", value:GetName().."Tab", "CENTER", 0, 0);
end
-- If this is the last frame in the dock then extend the dockRegion, otherwise shrink it to the default width
dockRegion = _G[chatTab:GetName().."DockRegion"];
dockRegion:SetPoint("LEFT", chatTab, "CENTER", 0 , 0);
if ( numDockedFrames == index ) then
dockRegion:SetPoint("RIGHT", "ChatFrame"..chatTab:GetID(), "RIGHT", 0, 0);
end
dockRegion:Hide();
-- Keep track of the width of the dock for anchoring purposes
dockWidth = dockWidth + chatTab:GetWidth();
previousDockedFrame = value;
end
-- Intelligently resize the chat tabs if dockwidth is greater than the window width
if ( dockWidth > DEFAULT_CHAT_FRAME:GetWidth() ) then
DOCK_COPY = {};
-- Copy the array
for index, value in pairs(DOCKED_CHAT_FRAMES) do
DOCK_COPY[index] = DOCKED_CHAT_FRAMES[index];
end
sort(DOCK_COPY, FCF_TabCompare);
local totalWidth = DEFAULT_CHAT_FRAME:GetWidth();
local avgWidth = totalWidth / numDockedFrames;
local chatTabWidth;
-- Resize the tabs
for index, value in pairs(DOCK_COPY) do
chatTab = _G[value:GetName().."Tab"];
chatTabWidth = chatTab:GetWidth();
if ( chatTabWidth < avgWidth ) then
-- If tab is smaller than the average then remove it from the list and recalc the average
totalWidth = totalWidth - chatTabWidth;
numDockedFrames = numDockedFrames - 1;
avgWidth = totalWidth / numDockedFrames;
else
-- Set the tab to the average width
PanelTemplates_TabResize(chatTab, 0, avgWidth);
end
end
-- Reanchor the tabs
previousDockedFrame = nil;
dockWidth = 0;
for index, value in pairs(DOCKED_CHAT_FRAMES) do
-- If there was a frame before this frame then anchor the tab
if ( previousDockedFrame ) then
FCF_SetTabPosition(value, dockWidth);
end
chatTab = _G[value:GetName().."Tab"];
dockWidth = dockWidth + chatTab:GetWidth();
previousDockedFrame = value;
end
end
end]]
function FCF_TabCompare(chatFrame1, chatFrame2)
local tab1 = _G[chatFrame1:GetName().."Tab"];
local tab2 = _G[chatFrame2:GetName().."Tab"];
return tab1:GetWidth() < tab2:GetWidth();
end
function FCF_DockFrame(frame, index, selected)
-- Return if already docked
if ( frame.isDocked ) then
return;
end
FCFDock_AddChatFrame(GENERAL_CHAT_DOCK, frame, index);
-- Save docked state
FCF_SaveDock();
if ( selected ) then
--FCF_SelectDockFrame(frame);
FCFDock_SelectWindow(GENERAL_CHAT_DOCK, frame);
end
-- Set scroll button side
if ( frame == DEFAULT_CHAT_FRAME ) then
FCF_UpdateButtonSide(frame);
else
FCF_SetButtonSide(frame, FCF_GetButtonSide(DEFAULT_CHAT_FRAME));
end
-- Lock frame
FCF_SetLocked(frame, 1);
--If the frame that is being docked and the frame it is docking to have different interactable settings, make them both interactable.
if ( frame.isUninteractable ~= DEFAULT_CHAT_FRAME.isUninteractable ) then
FCF_SetExpandedUninteractable(frame, false)
end
if ( frame == COMBATLOG ) then
Blizzard_CombatLog_Update_QuickButtons();
end
FCF_DockUpdate();
end
function FCF_UnDockFrame(frame)
if ( frame == DEFAULT_CHAT_FRAME or not frame.isDocked ) then
return;
end
-- Undock frame regardless of whether its docked or not
SetChatWindowDocked(frame:GetID(), nil);
FCFDock_RemoveChatFrame(GENERAL_CHAT_DOCK, frame);
FCF_SaveDock();
-- Set tab to full alpha
local chatTab = _G[frame:GetName().."Tab"];
chatTab:SetAlpha(1.0);
end
function FCF_SelectDockFrame(frame)
SELECTED_DOCK_FRAME = frame;
-- Stop tab flashing
local tabFlash;
if ( frame ) then
tabFlash = _G["ChatFrame"..frame:GetID().."TabFlash"];
end
if ( tabFlash ) then
UIFrameFlashStop(tabFlash);
tabFlash:Hide();
end
FCFDock_SelectWindow(GENERAL_CHAT_DOCK, frame);
FCF_DockUpdate();
end
function FCF_Tab_OnClick(self, button)
local chatFrame = _G["ChatFrame"..self:GetID()];
-- If Rightclick bring up the options menu
if ( button == "RightButton" ) then
chatFrame:StopMovingOrSizing();
CURRENT_CHAT_FRAME_ID = self:GetID();
ToggleDropDownMenu(1, nil, _G[self:GetName().."DropDown"], self:GetName(), 0, 0);
return;
end
if (button == "MiddleButton") then
if ( chatFrame and (chatFrame ~= DEFAULT_CHAT_FRAME and not IsCombatLog(chatFrame)) ) then
if ( not chatFrame.isTemporary ) then
FCF_PopInWindow(self, chatFrame);
return;
elseif ( chatFrame.isTemporary and (chatFrame.chatType == "WHISPER" or chatFrame.chatType == "BN_WHISPER") ) then
FCF_PopInWindow(self, chatFrame);
return;
elseif ( chatFrame.isTemporary and ( chatFrame.chatType == "BN_CONVERSATION" ) ) then
if ( GetCVar("conversationMode") == "popout" or GetCVar("conversationMode") == "popout_and_inline" ) then
FCF_LeaveConversation(self, chatFrame);
return;
else
FCF_PopInWindow(self, chatFrame);
return;
end
elseif ( chatFrame.isTemporary and ( chatFrame.chatType == "PET_BATTLE_COMBAT_LOG" ) ) then
FCF_Close(chatFrame);
else
GMError(format("Unhandled temporary window type. chatType: %s, chatTarget %s", tostring(chatFrame.chatType), tostring(chatFrame.chatTarget)));
end
end
return;
end
-- Close all dropdowns
CloseDropDownMenus();
-- If frame is docked assume that a click is to select a chat window, not drag it
SELECTED_CHAT_FRAME = chatFrame;
if ( chatFrame.isDocked and FCFDock_GetSelectedWindow(GENERAL_CHAT_DOCK) ~= chatFrame ) then
FCF_SelectDockFrame(chatFrame);
FCF_FadeInChatFrame(chatFrame);
return;
else
if ( GetCVar("chatStyle") ~= "classic" ) then
ChatEdit_SetLastActiveWindow(chatFrame.editBox);
end
FCF_FadeInChatFrame(chatFrame);
end
end
function FCF_SetTabPosition(chatFrame, x)
local chatTab = _G[chatFrame:GetName().."Tab"];
chatTab:ClearAllPoints();
chatTab:SetPoint("BOTTOMLEFT", chatFrame:GetName().."Background", "TOPLEFT", x+2, 0);
end
function FCF_SaveDock()
for index, value in pairs(FCFDock_GetChatFrames(GENERAL_CHAT_DOCK)) do
SetChatWindowDocked(value:GetID(), index);
end
end
function FCF_LeaveConversation(frame, fallback)
if ( fallback ) then
frame=fallback
end
if ( not frame ) then
frame = FCF_GetCurrentChatFrame();
end
assert(frame.chatType == "BN_CONVERSATION");
BNLeaveConversation(tonumber(frame.chatTarget));
FCF_Close(frame);
end
function FCF_PopInWindow(frame, fallback)
if ( fallback ) then
frame=fallback
end
if ( not frame ) then
frame = FCF_GetCurrentChatFrame();
end
if ( frame == DEFAULT_CHAT_FRAME ) then
return;
end
--Restore any chats this frame had to the DEFAULT_CHAT_FRAME
FCF_RestoreChatsToFrame(DEFAULT_CHAT_FRAME, frame);
FCF_Close(frame);
end
function FCF_Close(frame, fallback)
if ( fallback ) then
frame=fallback
end
if ( not frame ) then
frame = FCF_GetCurrentChatFrame();
end
if ( frame == DEFAULT_CHAT_FRAME ) then
return;
end
FCF_UnDockFrame(frame);
HideUIPanel(frame);
_G[frame:GetName().."Tab"]:Hide();
FCF_FlagMinimizedPositionReset(frame);
if ( frame.minFrame and frame.minFrame:IsShown() ) then
frame.minFrame:Hide();
end
if ( frame.isTemporary ) then
FCFManager_UnregisterDedicatedFrame(frame, frame.chatType, frame.chatTarget);
frame.isRegistered = false;
frame.inUse = false;
end
if ( PENDING_BN_WHISPER_TO_CONVERSATION_FRAME == frame ) then
PENDING_BN_WHISPER_TO_CONVERSATION_FRAME = nil;
end
--Reset what this window receives.
ChatFrame_RemoveAllMessageGroups(frame);
ChatFrame_RemoveAllChannels(frame);
ChatFrame_ReceiveAllPrivateMessages(frame);
ChatFrame_ReceiveAllBNConversations(frame);
end
function FCF_RestoreChatsToFrame(targetFrame, sourceFrame)
--Restore chat types
for _, messageType in pairs(sourceFrame.messageTypeList) do
ChatFrame_AddMessageGroup(targetFrame, messageType);
end
--Restore channels
for _, channel in pairs(sourceFrame.channelList) do
ChatFrame_AddChannel(targetFrame, channel);
end
--Restore whispers
if ( sourceFrame.privateMessageList ) then
for name, value in pairs(sourceFrame.privateMessageList) do
if ( value ) then
ChatFrame_RemoveExcludePrivateMessageTarget(targetFrame, name);
end
end
end
if ( sourceFrame.bnConversationList ) then
for name, value in pairs(sourceFrame.bnConversationList) do
if ( value ) then
ChatFrame_RemoveExcludeBNConversationTarget(targetFrame, name);
end
end
end
end
-- Tab flashing functions
function FCF_FlashTab(self)
local tabFlash = _G[self:GetName().."TabFlash"];
if ( not self.isDocked or (self == SELECTED_DOCK_FRAME) or UIFrameIsFlashing(tabFlash) ) then
return;
end
tabFlash:Show();
UIFrameFlash(tabFlash, 0.25, 0.25, 60, nil, 0.5, 0.5);
end
-- Function for repositioning the chat dock depending on if there's a shapeshift bar/stance bar, etc...
function FCF_UpdateDockPosition()
if ( DEFAULT_CHAT_FRAME:IsUserPlaced() ) then
return;
end
local chatOffset = 85;
if ( GetNumShapeshiftForms() > 0 or HasPetUI() or PetHasActionBar() ) then
if ( MultiBarBottomLeft:IsShown() ) then
chatOffset = chatOffset + 55;
else
chatOffset = chatOffset + 15;
end
elseif ( MultiBarBottomLeft:IsShown() ) then
chatOffset = chatOffset + 15;
end
DEFAULT_CHAT_FRAME:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 32, chatOffset);
FCF_DockUpdate();
end
function FCF_Set_NormalChat()
ChatFrame2:StartMoving();
ChatFrame2:StopMovingOrSizing();
FCF_SetLocked(ChatFrame2, nil);
-- to fix a bug with the combat log not repositioning its tab properly when coming out of
-- simple chat, we need to update now
FCF_DockUpdate();
end
-- Functions to set and remove the chat window show delay on mouseover
function SetChatMouseOverDelay(noDelay)
if ( noDelay == "1" ) then
CHAT_TAB_SHOW_DELAY = 0;
CHAT_FRAME_FADE_TIME = 0;
else
CHAT_TAB_SHOW_DELAY = 0.2;
CHAT_FRAME_FADE_TIME = 0.15;
end
end
-- Reset the chat windows to default
function FCF_ResetChatWindows()
ChatFrame1:ClearAllPoints();
ChatFrame1:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 32, 95);
ChatFrame1:SetWidth(430);
ChatFrame1:SetHeight(120);
ChatFrame1.isInitialized = 0;
FCF_SetButtonSide(ChatFrame1, "left")
FCF_SetChatWindowFontSize(nil, ChatFrame1, 14);
FCF_SetWindowName(ChatFrame1, GENERAL);
FCF_SetWindowColor(ChatFrame1, DEFAULT_CHATFRAME_COLOR.r, DEFAULT_CHATFRAME_COLOR.g, DEFAULT_CHATFRAME_COLOR.b);
FCF_SetWindowAlpha(ChatFrame1, DEFAULT_CHATFRAME_ALPHA);
FCF_UnDockFrame(ChatFrame1);
ChatFrame_RemoveAllMessageGroups(ChatFrame1);
ChatFrame_RemoveAllChannels(ChatFrame1);
ChatFrame_ReceiveAllPrivateMessages(ChatFrame1);
ChatFrame_ReceiveAllBNConversations(ChatFrame1);
SELECTED_CHAT_FRAME = ChatFrame1;
DEFAULT_CHAT_FRAME.chatframe = DEFAULT_CHAT_FRAME;
FCF_SetChatWindowFontSize(nil, ChatFrame2, 14);
FCF_SetWindowName(ChatFrame2, COMBAT_LOG);
FCF_SetWindowColor(ChatFrame2, DEFAULT_CHATFRAME_COLOR.r, DEFAULT_CHATFRAME_COLOR.g, DEFAULT_CHATFRAME_COLOR.b);
FCF_SetWindowAlpha(ChatFrame2, DEFAULT_CHATFRAME_ALPHA);
ChatFrame_RemoveAllMessageGroups(ChatFrame2);
ChatFrame_RemoveAllChannels(ChatFrame2);
ChatFrame_ReceiveAllPrivateMessages(ChatFrame2);
ChatFrame_ReceiveAllBNConversations(ChatFrame2);
FCF_UnDockFrame(ChatFrame2);
ChatFrame2.isInitialized = 0;
for _, chatFrameName in ipairs(CHAT_FRAMES) do
if ( chatFrameName ~= "ChatFrame1" ) then
local chatFrame = _G[chatFrameName];
if ( chatFrame.isTemporary and chatFrame.chatType == "BN_CONVERSATION" and
BNGetConversationInfo(tonumber(chatFrame.chatTarget)) and (GetCVar("conversationMode") == "popout" or GetCVar("conversationMode") == "popout_and_inline") ) then
--We're still in this conversation, so we just want to reset the position, not remove the frame.
FCF_DockFrame(chatFrame, 3); --Put it after General and Combat Log
else
chatFrame.isInitialized = 0;
FCF_SetTabPosition(chatFrame, 0);
FCF_Close(chatFrame);
FCF_UnDockFrame(chatFrame);
FCF_SetWindowName(chatFrame, "");
ChatFrame_RemoveAllMessageGroups(chatFrame);
ChatFrame_RemoveAllChannels(chatFrame);
ChatFrame_ReceiveAllPrivateMessages(chatFrame);
ChatFrame_ReceiveAllBNConversations(chatFrame);
end
FCF_SetChatWindowFontSize(nil, chatFrame, 14);
FCF_SetWindowColor(chatFrame, DEFAULT_CHATFRAME_COLOR.r, DEFAULT_CHATFRAME_COLOR.g, DEFAULT_CHATFRAME_COLOR.b);
FCF_SetWindowAlpha(chatFrame, DEFAULT_CHATFRAME_ALPHA);
end
end
ChatFrame1.init = 0;
FCF_DockFrame(ChatFrame1, 1, true);
FCF_DockFrame(ChatFrame2, 2);
-- resets to hard coded defaults
ResetChatWindows();
UIParent_ManageFramePositions();
FCFDock_SelectWindow(GENERAL_CHAT_DOCK, ChatFrame1);
end
function IsCombatLog(frame)
if ( frame == ChatFrame2 and IsAddOnLoaded("Blizzard_CombatLog") ) then
return true;
else
return false;
end
end
function FCFClickAnywhereButton_OnLoad(self)
self:SetFrameLevel(self:GetParent():GetFrameLevel() - 1);
self:RegisterEvent("VARIABLES_LOADED");
self:RegisterEvent("CVAR_UPDATE");
self:RegisterForClicks("LeftButtonDown", "RightButtonDown");
FCFClickAnywhereButton_UpdateState(self);
end
function FCFClickAnywhereButton_OnEvent(self, event, ...)
local arg1 = ...;
if ( event == "VARIABLES_LOADED" or
(event == "CVAR_UPDATE" and (arg1 == "chatStyle" or arg1 == "CHAT_WHOLE_WINDOW_CLICKABLE")) ) then
FCFClickAnywhereButton_UpdateState(self);
end
end
function FCFClickAnywhereButton_UpdateState(self)
if ( GetCVar("chatStyle") == "im" and GetCVarBool("wholeChatWindowClickable") and
LAST_ACTIVE_CHAT_EDIT_BOX ~= self:GetParent().editBox ) then
self:Show();
else
self:Hide();
end
end
function FCF_MinimizeFrame(chatFrame, side)
local chatTab = _G[chatFrame:GetName().."Tab"];
local createdFrame = false;
if ( not chatFrame.minFrame ) then
chatFrame.minFrame = FCF_CreateMinimizedFrame(chatFrame);
end
if ( chatFrame.minFrame.resetPosition ) then
chatFrame.minFrame:ClearAllPoints();
chatFrame.minFrame:SetPoint("TOP"..side, chatFrame, "TOP"..side, 0, 0);
chatFrame.minFrame.resetPosition = false;
end
chatFrame.minimized = true;
chatFrame.minFrame:Show();
chatFrame:Hide();
chatTab:Hide();
end
function FCF_MaximizeFrame(chatFrame)
local minFrame = chatFrame.minFrame;
local chatTab = _G[chatFrame:GetName().."Tab"];
chatFrame.minimized = false;
minFrame:UnlockHighlight();
minFrame:Hide();
chatFrame:Show();
chatTab:Show();
FCF_FadeInChatFrame(chatFrame);
if ( GetCVar("chatStyle") == "im" ) then
ChatEdit_SetLastActiveWindow(chatFrame.editBox);
end
end
function FCF_CreateMinimizedFrame(chatFrame)
local chatTab = _G[chatFrame:GetName().."Tab"];
local minFrame = CreateFrame("Button", chatFrame:GetName().."Minimized", UIParent, "FloatingChatFrameMinimizedTemplate");
minFrame.maxFrame = chatFrame;
minFrame:SetText(chatFrame.name);
--Copy the colors from the minimized frame.
minFrame.selectedColorTable = chatTab.selectedColorTable;
FCFMin_UpdateColors(minFrame);
if ( not chatFrame.isTemporary ) then
minFrame.conversationIcon:Hide();
else
local conversationIcon;
if ( chatFrame.chatType == "WHISPER" or chatFrame.chatType == "BN_WHISPER" ) then
conversationIcon = "Interface\\ChatFrame\\UI-ChatWhisperIcon";
elseif ( chatFrame.chatType == "PET_BATTLE_COMBAT_LOG" ) then
conversationIcon = "Interface\\Icons\\Tracking_WildPet";
else
conversationIcon = "Interface\\ChatFrame\\UI-ChatConversationIcon";
end
minFrame.conversationIcon:SetTexture(conversationIcon);
end
if (chatFrame.isTemporary) then
minFrame.Text:SetJustifyH("LEFT");
minFrame.Text:SetPoint("LEFT", minFrame, "LEFT", 30, 0);
end
--Make sure the position is reset.
minFrame.resetPosition = true;
return minFrame;
end
function FCFMin_UpdateColors(minFrame)
--Color it.
local colorTable = minFrame.selectedColorTable or DEFAULT_TAB_SELECTED_COLOR_TABLE;
if ( minFrame.selectedColorTable ) then
minFrame:GetFontString():SetTextColor(colorTable.r, colorTable.g, colorTable.b);
else
minFrame:GetFontString():SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
end
minFrame.leftHighlightTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
minFrame.middleHighlightTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
minFrame.rightHighlightTexture:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
minFrame.glow:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
minFrame.conversationIcon:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
end
--This function just makes the position be reset the next time the minimize frame is shown.
function FCF_FlagMinimizedPositionReset(chatFrame)
if ( chatFrame.minFrame ) then
chatFrame.minFrame.resetPosition = true;
end
end
------Docking related functions for the new docking system
--[[
Since we've been discussing allowing multiple docks, this code is designed to be mostly-OO. Please try not to use global variables.
(Theoretically, all of these functions may be put in a metatable to allow, e.g., "Dock:SelectWindow(chatWindow)".
To keep with this, please ensure that "dock" is the first argument of every function.)
]]
function FCFDock_OnLoad(dock)
dock.DOCKED_CHAT_FRAMES = {};
dock.isDirty = true; --You dirty, dirty frame
end
function FCFDock_OnEvent(dock, event, ...)
if ( event == "UPDATE_CHAT_WINDOWS" ) then
--FCFDock_ForceTabSort(dock);
--FCFDock_ForceReanchoring(dock);
end
end
function FCFDock_GetChatFrames(dock)
return dock.DOCKED_CHAT_FRAMES;
end
function FCFDock_SetPrimary(dock, chatFrame)
dock.primary = chatFrame;
dock:SetPoint("BOTTOMLEFT", chatFrame, "TOPLEFT", 0, 6);
dock:SetPoint("BOTTOMRIGHT", chatFrame, "TOPRIGHT", 0, 6);
chatFrame:SetScript("OnSizeChanged", function(self) FCFDock_OnPrimarySizeChanged(dock) end);
if ( not FCFDock_GetSelectedWindow(dock) ) then
FCFDock_SelectWindow(dock, chatFrame);
end
FCFDock_ForceReanchoring(dock);
FCFDock_AddChatFrame(dock, chatFrame, 1);
end
function FCFDock_OnPrimarySizeChanged(dock)
dock.isDirty = true;
--We have to save off the current leftmost-tab before we resize the tabs.
dock.leftTab = FCFDockScrollFrame_GetLeftmostTab(dock.scrollFrame);
--We have to do it on the next frame to deal with issues caused by resizing the WoW client (frame positions may not be valid)
dock:SetScript("OnUpdate", FCFDock_OnUpdate);
end
function FCFDock_OnUpdate(self)
--These may fail if we're resizing the WoW client
if ( FCFDock_UpdateTabs(self) and FCFDockScrollFrame_JumpToTab(self.scrollFrame, self.leftTab) ) then
self.leftTab = nil;
self:SetScript("OnUpdate", nil);
end
end
function FCFDock_ForceReanchoring(dock)
for index, chatFrame in pairs(dock.DOCKED_CHAT_FRAMES) do
if ( dock.primary ~= chatFrame ) then
chatFrame:ClearAllPoints();
chatFrame:SetAllPoints(dock.primary);
end
end
end
function FCFDock_AddChatFrame(dock, chatFrame, position)
if ( not dock.primary ) then
error("Need a primary window before another can be added.");
end
if ( FCFDock_HasDockedChatFrame(dock, chatFrame) ) then
return; --We're already docked...
end
dock.isDirty = true;
chatFrame.isDocked = 1;
if ( position and position <= #dock.DOCKED_CHAT_FRAMES + 1 ) then
assert(position ~= 1 or chatFrame == dock.primary);
tinsert(dock.DOCKED_CHAT_FRAMES, position, chatFrame);
else
tinsert(dock.DOCKED_CHAT_FRAMES, chatFrame);
end
FCFDock_HideInsertHighlight(dock);
if ( dock.primary ~= chatFrame ) then
chatFrame:ClearAllPoints();
chatFrame:SetAllPoints(dock.primary);
chatFrame:SetMovable(false);
chatFrame:SetResizable(false);
end
if ( chatFrame.conversationButton ) then
BNConversationButton_UpdateAttachmentPoint(chatFrame.conversationButton);
end
chatFrame.buttonFrame.minimizeButton:Hide();
chatFrame.buttonFrame:SetAlpha(1.0);
dock.overflowButton.list:Hide();
FCFDock_UpdateTabs(dock);
end
function FCFDock_RemoveChatFrame(dock, chatFrame)
assert(chatFrame ~= dock.primary or #dock.DOCKED_CHAT_FRAMES == 1);
dock.isDirty = true;
tDeleteItem(dock.DOCKED_CHAT_FRAMES, chatFrame);
local chatTab = _G[chatFrame:GetName().."Tab"];
chatFrame.isDocked = nil;
chatTab:SetParent(UIParent);
chatTab:SetFrameStrata("LOW");
chatFrame:SetMovable(true);
chatFrame:SetResizable(true);
FCFTab_UpdateColors(chatTab, true);
PanelTemplates_TabResize(chatTab, chatTab.sizePadding or 0, nil, nil, nil, chatTab.textWidth);
if ( FCFDock_GetSelectedWindow(dock) == chatFrame ) then
FCFDock_SelectWindow(dock, dock.DOCKED_CHAT_FRAMES[1]);
end
if ( chatFrame.conversationButton ) then
BNConversationButton_UpdateAttachmentPoint(chatFrame.conversationButton);
end
chatFrame.buttonFrame.minimizeButton:Show();
dock.overflowButton.list:Hide();
chatFrame:Show();
FCFDock_UpdateTabs(dock);
end
function FCFDock_HasDockedChatFrame(dock, chatFrame)
return tContains(dock.DOCKED_CHAT_FRAMES, chatFrame);
end
function FCFDock_SelectWindow(dock, chatFrame)
assert(chatFrame)
dock.isDirty = true;
dock.selected = chatFrame;
dock.overflowButton.list:Hide();
FCFDock_UpdateTabs(dock);
if ( ChatFrameMenuButton ) then
if ( chatFrame.conversationButton and chatFrame.conversationButton:IsShown() ) then
ChatFrameMenuButton:Hide();
else
ChatFrameMenuButton:Show();
end
end
end
function FCFDock_GetSelectedWindow(dock)
return dock.selected;
end
function FCFDock_UpdateTabs(dock, forceUpdate)
if ( not dock.isDirty and not forceUpdate ) then --No changes have been made since the last update.
return;
end
local scrollChild = dock.scrollFrame:GetScrollChild();
local lastDockedStaticTab = nil;
local lastDockedDynamicTab = nil;
local numDynFrames = 0; --Number of dynamicly sized frames.
local selectedDynIndex = nil;
for index, chatFrame in ipairs(dock.DOCKED_CHAT_FRAMES) do
local chatTab = _G[chatFrame:GetName().."Tab"];
if ( chatFrame == FCFDock_GetSelectedWindow(dock) ) then
chatFrame:Show();
else
chatFrame:Hide();
end
FCFTab_UpdateAlpha(chatFrame);
chatTab:ClearAllPoints();
chatTab:Show();
FCFTab_UpdateColors(chatTab, chatFrame == FCFDock_GetSelectedWindow(dock));
if ( chatFrame.isStaticDocked ) then
chatTab:SetParent(dock);
PanelTemplates_TabResize(chatTab, chatTab.sizePadding or 0);
if ( lastDockedStaticTab ) then
chatTab:SetPoint("LEFT", lastDockedStaticTab, "RIGHT", 0, 0);
else
chatTab:SetPoint("LEFT", dock, "LEFT", 0, 0);
end
lastDockedStaticTab = chatTab;
else
chatTab:SetParent(scrollChild);
numDynFrames = numDynFrames + 1;
if ( FCFDock_GetSelectedWindow(dock) == chatFrame ) then
selectedDynIndex = numDynFrames;
end
if ( lastDockedDynamicTab ) then
chatTab:SetPoint("LEFT", lastDockedDynamicTab, "RIGHT", 0, 0);
else
chatTab:SetPoint("LEFT", scrollChild, "LEFT", 0, 0);
end
lastDockedDynamicTab = chatTab;
end
end
local dynTabSize, hasOverflow = FCFDock_CalculateTabSize(dock, numDynFrames);
for index, chatFrame in ipairs(dock.DOCKED_CHAT_FRAMES) do
if ( not chatFrame.isStaticDocked ) then
local chatTab = _G[chatFrame:GetName().."Tab"];
PanelTemplates_TabResize(chatTab, chatTab.sizePadding or 0, dynTabSize);
end
end
dock.scrollFrame:SetPoint("LEFT", lastDockedStaticTab, "RIGHT", 0, 0);
if ( hasOverflow ) then
dock.overflowButton:Show();
dock.scrollFrame:SetPoint("BOTTOMRIGHT", dock.overflowButton, "BOTTOMLEFT", 0, 0);
else
dock.overflowButton:Hide();
dock.scrollFrame:SetPoint("BOTTOMRIGHT", dock, "BOTTOMRIGHT", 0, -5);
end
--Cache some of this data on the scroll frame for animating to the selected tab.
dock.scrollFrame.dynTabSize = dynTabSize;
dock.scrollFrame.numDynFrames = numDynFrames;
dock.scrollFrame.selectedDynIndex = selectedDynIndex;
dock.isDirty = false;
return FCFDock_ScrollToSelectedTab(dock);
end
--Returns dynTabSize, hasOverflow
function FCFDock_CalculateTabSize(dock, numDynFrames)
local MIN_SIZE, MAX_SIZE = 60, 90;
local scrollSize = dock.scrollFrame:GetWidth() + (dock.overflowButton:IsShown() and dock.overflowButton.width or 0); --We want the total width assuming no overflow button.
--First, see if we can fit all the tabs at the maximum size
if ( numDynFrames * MAX_SIZE < scrollSize ) then
return MAX_SIZE, false;
end
if ( scrollSize / MIN_SIZE < numDynFrames ) then
--Not everything fits, so we'll need room for the overflow button.
scrollSize = scrollSize - dock.overflowButton.width;
end
--Figure out how many tabs we're going to be able to fit at the minimum size
local numWholeTabs = min(floor(scrollSize / MIN_SIZE), numDynFrames)
if ( numWholeTabs == 0 ) then
return scrollSize, true;
end
--How big each tab should be.
local tabSize = scrollSize / numWholeTabs;
return tabSize, (numDynFrames > numWholeTabs);
end
function FCFDock_ScrollToSelectedTab(dock)
if ( FCFDockScrollFrame_GetScrollDistanceNeeded(dock.scrollFrame, dock.scrollFrame.selectedDynIndex) ~= 0) then
dock.scrollFrame:SetScript("OnUpdate", FCFDockScrollFrame_OnUpdate);
return true;
else
return FCFDockScrollFrame_JumpToTab(dock.scrollFrame, FCFDockScrollFrame_GetLeftmostTab(dock.scrollFrame)); --Make sure we're exactly aligned with the tab.
end
end
---These functions deal with the scroll frame handling dynamic tabs.
function FCFDockScrollFrame_OnUpdate(self, elapsed)
local MOVEMENT_SPEED = 10;
local totalDistanceNeeded = FCFDockScrollFrame_GetScrollDistanceNeeded(self, self.selectedDynIndex);
if ( abs(totalDistanceNeeded) < 1.0 ) then --Delta chosen through experimentation
self:SetScript("OnUpdate", nil);
FCFDockScrollFrame_JumpToTab(self, FCFDockScrollFrame_GetLeftmostTab(self)); --Make sure we're exactly aligned with the tab.
return;
end
local currentPosition = self:GetHorizontalScroll();
local distanceNoCap = totalDistanceNeeded * MOVEMENT_SPEED * elapsed;
local distanceToMove = (totalDistanceNeeded > 0) and min(totalDistanceNeeded, distanceNoCap) or max(totalDistanceNeeded, distanceNoCap);
self:SetHorizontalScroll(max(currentPosition + distanceToMove, 0));
end
function FCFDock_GetInsertIndex(dock, chatFrame, mouseX, mouseY)
if ( chatFrame.isStaticDocked ) then
local maxPosition = 0;
for index, value in ipairs(dock.DOCKED_CHAT_FRAMES) do
if ( value.isStaticDocked ) then
local tab = _G[value:GetName().."Tab"];
if ( mouseX < (tab:GetLeft() + tab:GetRight()) / 2 and --Find the first tab we're on the left of. (Being on top of the tab, but left of the center counts)
tab:GetID() ~= dock.primary:GetID()) then --We never count as being to the left of the primary tab.
return index;
end
maxPosition = index;
end
end
--We aren't to the left of anything, so we're going into the far-right position.
return maxPosition + 1;
else
--Find the dynamic insertion spot
local maxPosition = 9^9;
local leftTab = FCFDockScrollFrame_GetLeftmostTab(dock.scrollFrame);
local numDynTabsDisplayed = dock.scrollFrame:GetWidth() / dock.scrollFrame.dynTabSize;
local currTabNum = 0;
for index, value in ipairs(dock.DOCKED_CHAT_FRAMES) do
if ( not value.isStaticDocked ) then
currTabNum = currTabNum + 1;
if ( currTabNum >= leftTab and currTabNum < leftTab + numDynTabsDisplayed ) then
local tab = _G[value:GetName().."Tab"];
if ( mouseX < (tab:GetLeft() + tab:GetRight())/2 ) then
return index;
end
maxPosition = index;
end
end
end
return min(#dock.DOCKED_CHAT_FRAMES + 1, maxPosition + 1);
end
end
function FCFDock_PlaceInsertHighlight(dock, chatFrame, mouseX, mouseY)
local insert = FCFDock_GetInsertIndex(dock, chatFrame, mouseX, mouseY);
local attachFrame = dock.primary;
local leftDynTab = FCFDockScrollFrame_GetLeftmostTab(dock.scrollFrame);
local numDynTabsDisplayed = dock.scrollFrame:GetWidth() / dock.scrollFrame.dynTabSize;
local dynamicIndex = 0;
for index, value in ipairs(dock.DOCKED_CHAT_FRAMES) do
if ( index < insert ) then
if ( value.isStaticDocked ) then
attachFrame = value;
else
dynamicIndex = dynamicIndex + 1;
if ( dynamicIndex >= leftDynTab and dynamicIndex < leftDynTab + numDynTabsDisplayed ) then
attachFrame = value;
end
end
end
end
dock.insertHighlight:ClearAllPoints();
dock.insertHighlight:SetPoint("BOTTOMLEFT", _G[attachFrame:GetName().."Tab"], "BOTTOMRIGHT", -15, -4);
dock.insertHighlight:Show();
end
function FCFDock_HideInsertHighlight(dock)
dock.insertHighlight:Hide();
end
function FCFDock_SetDirty(dock)
dock.isDirty = true;
end
function FCFDockScrollFrame_GetScrollDistanceNeeded(scrollFrame, dynFrameIndex)
local firstIndex = (scrollFrame:GetHorizontalScroll() / scrollFrame.dynTabSize) + 1;
local numDisplayedFrames = scrollFrame:GetWidth() / scrollFrame.dynTabSize;
local lastIndex = firstIndex + numDisplayedFrames - 1;
if ( dynFrameIndex and dynFrameIndex < firstIndex ) then --Need to scroll left to get to the selected button
return (dynFrameIndex - firstIndex) * scrollFrame.dynTabSize;
elseif ( dynFrameIndex and dynFrameIndex > lastIndex ) then --Need to scroll right to get to the selected button
return (dynFrameIndex - lastIndex) * scrollFrame.dynTabSize;
elseif ( firstIndex > 1 and scrollFrame.numDynFrames < lastIndex ) then --Need to scroll left to fill in empty space at the end.
return (scrollFrame.numDynFrames - lastIndex) * scrollFrame.dynTabSize;
else
return 0;
end
end
function FCFDockScrollFrame_GetLeftmostTab(scrollFrame)
return floor((scrollFrame:GetHorizontalScroll() / scrollFrame.dynTabSize) + 0.5) + 1;
end
function FCFDockScrollFrame_JumpToTab(scrollFrame, leftTab)
--If we have a selected frame, make sure it's still in view.
local numTabsDisplayed = scrollFrame:GetWidth() / scrollFrame.dynTabSize;
if ( scrollFrame.selectedDynIndex ) then
if ( scrollFrame.selectedDynIndex >= leftTab + numTabsDisplayed ) then
leftTab = scrollFrame.selectedDynIndex - numTabsDisplayed + 1;
elseif ( scrollFrame.selectedDynIndex < leftTab ) then
leftTab = scrollFrame.selectedDynIndex;
end
end
--Make sure, if we can show more frames, we do.
leftTab = min(leftTab, scrollFrame.numDynFrames - numTabsDisplayed + 1);
--And make sure we never go to the left of 1 (for example, if we have extra space)
leftTab = max(leftTab, 1);
scrollFrame:SetHorizontalScroll(scrollFrame.dynTabSize * (leftTab - 1));
return FCFDockOverflowButton_UpdatePulseState(scrollFrame:GetParent().overflowButton);
end
--Dock list related functions
function FCFDockOverflow_CloseLists()
local list = GENERAL_CHAT_DOCK.overflowButton.list;
if ( list:IsShown() ) then
list:Hide();
return true;
else
return false;
end
end
function FCFDockOverflowButton_UpdatePulseState(self)
local dock = self:GetParent();
local shouldPulse = false;
for _, chatFrame in pairs(FCFDock_GetChatFrames(dock)) do
local chatTab = _G[chatFrame:GetName().."Tab"];
if ( not chatFrame.isStaticDocked and chatTab.alerting) then
--Make sure the rects are valid. (Not always the case when resizing the WoW client
if ( not chatTab:GetRight() or not dock.scrollFrame:GetRight() ) then
return false;
end
--Check if it's off the screen.
local DELTA = 3; --Chosen through experimentation
if ( chatTab:GetRight() < (dock.scrollFrame:GetLeft() + DELTA) or chatTab:GetLeft() > (dock.scrollFrame:GetRight() - DELTA) ) then
shouldPulse = true;
break;
end
end
end
if ( shouldPulse ) then
UIFrameFlash(self:GetHighlightTexture(), 1.0, 1.0, -1, true, 0, 0, "chat");
self:LockHighlight();
self.alerting = true;
else
UIFrameFlashStop(self:GetHighlightTexture());
self:UnlockHighlight();
self:GetHighlightTexture():Show();
self.alerting = false;
end
if ( self.list:IsShown() ) then
FCFDockOverflowList_Update(self.list, dock);
end
return true;
end
function FCFDockOverflowButton_OnClick(self, button)
PlaySound("UChatScrollButton");
if ( self.list:IsShown() ) then
self.list:Hide();
else
FCFDockOverflowList_Update(self.list, self:GetParent());
self.list:Show();
end
end
function FCFDockOverflowButton_OnEvent(self, event, ...)
if ( event == "UPDATE_CHAT_COLOR" and self.list:IsShown() ) then
FCFDockOverflowList_Update(self.list, self:GetParent());
end
end
function FCFDockOverflowList_Update(list, dock)
local dockedFrames = FCFDock_GetChatFrames(dock);
list:SetHeight(#dockedFrames *15 + 35);
list.numTabs:SetFormattedText(CHAT_WINDOWS_COUNT, #dockedFrames);
for i = 1, #dockedFrames do
local button = list.buttons[i];
if ( not button ) then
list.buttons[i] = CreateFrame("Button", list:GetName().."Button"..i, list, "DockManagerOverflowListButtonTemplate");
button = list.buttons[i];
if ( not list.buttons[i-1] ) then
button:SetPoint("TOPLEFT", list, "TOPLEFT", 5, -19);
else
button:SetPoint("TOPLEFT", list.buttons[i-1], "BOTTOMLEFT", 0, -3);
end
button:SetWidth(list:GetWidth() - 10); -- buttons are 5 pixels in on both sides
end
FCFDockOverflowListButton_SetValue(button, dockedFrames[i]);
end
for i = #dockedFrames + 1, #list.buttons do
list.buttons[i]:Hide();
end
end
function FCFDockOverflowListButton_SetValue(button, chatFrame)
local chatTab = _G[chatFrame:GetName().."Tab"];
button.chatFrame = chatFrame;
button:SetText(chatFrame.name);
local colorTable = chatTab.selectedColorTable or DEFAULT_TAB_SELECTED_COLOR_TABLE;
if ( chatTab.selectedColorTable ) then
button:GetFontString():SetTextColor(colorTable.r, colorTable.g, colorTable.b);
else
button:GetFontString():SetTextColor(NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b);
end
button.glow:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
if ( chatTab.conversationIcon ) then
button.conversationIcon:SetVertexColor(colorTable.r, colorTable.g, colorTable.b);
button.conversationIcon:Show();
else
button.conversationIcon:Hide();
end
if ( chatTab.alerting ) then
button.alerting = true;
UIFrameFlash(button.glow, 1.0, 1.0, -1, false, 0, 0, "chat");
else
button.alerting = false;
UIFrameFlashStop(button.glow);
end
button:Show();
end
function FCFDockOverflowListButton_OnClick(self, button)
FCFDock_SelectWindow(self:GetParent():GetParent():GetParent(), self.chatFrame);
end
---------------------------------------------------
-----------Temp Window Manager-------------
----------------------------------------------------
local dedicatedWindows = {};
local function FCFManager_GetToken(chatType, chatTarget)
return strlower(chatType)..(chatTarget and ";;"..strlower(chatTarget) or "");
end
function FCFManager_RegisterDedicatedFrame(chatFrame, chatType, chatTarget)
local token = FCFManager_GetToken(chatType, chatTarget);
if ( not dedicatedWindows[token] ) then
dedicatedWindows[token] = {};
end
if ( not tContains(dedicatedWindows[token], chatFrame) ) then
tinsert(dedicatedWindows[token], chatFrame);
end
end
function FCFManager_UnregisterDedicatedFrame(chatFrame, chatType, chatTarget)
local token = FCFManager_GetToken(chatType, chatTarget);
local windowList = dedicatedWindows[token];
if ( windowList ) then
tDeleteItem(windowList, chatFrame);
end
end
function FCFManager_GetNumDedicatedFrames(chatType, chatTarget)
local token = FCFManager_GetToken(chatType, chatTarget);
local windowList = dedicatedWindows[token];
return (windowList and #windowList or 0);
end
function FCFManager_ShouldSuppressMessage(chatFrame, chatType, chatTarget)
--Using GetToken probably isn't the best way to do this due to the string concatenation, but it's the easiest to get in quickly.
if ( chatFrame.chatType and FCFManager_GetToken(chatType, chatTarget) == FCFManager_GetToken(chatFrame.chatType, chatFrame.chatTarget) ) then
--This frame is a dedicated frame of this type, so we should always display.
return false;
end
if ( (chatType == "BN_CONVERSATION" and GetCVar("conversationMode") == "popout")
or (chatType == "BN_WHISPER" and GetCVar("bnWhisperMode") == "popout")
or (chatType == "WHISPER" and GetCVar("whisperMode") == "popout") ) then
return true;
end
return false;
end
function FCFManager_ShouldSuppressMessageFlash(chatFrame, chatType, chatTarget)
--Using GetToken probably isn't the best way to do this due to the string concatenation, but it's the easiest to get in quickly.
if ( chatFrame.chatType and FCFManager_GetToken(chatType, chatTarget) == FCFManager_GetToken(chatFrame.chatType, chatFrame.chatTarget) ) then
--This frame is a dedicated frame of this type, so we should always display.
return false;
end
if ( (chatType == "BN_CONVERSATION" and GetCVar("conversationMode") == "popout_and_inline")
or (chatType == "BN_WHISPER" and GetCVar("bnWhisperMode") == "popout_and_inline")
or (chatType == "WHISPER" and GetCVar("whisperMode") == "popout_and_inline") ) then
return true;
end
return false;
end
function FCFManager_StopFlashOnDedicatedWindows(chatType, chatTarget)
local token = FCFManager_GetToken(chatType, chatTarget);
local windowList = dedicatedWindows[token];
if (windowList) then
for i, frame in pairs(windowList) do
FCF_StopAlertFlash(frame);
end
end
end
function FloatingChatFrameManager_OnLoad(self)
--Register for BN_CONVERSATION related messages to be able to spawn off new windows as needed
for _, event in pairs(ChatTypeGroup["BN_CONVERSATION"]) do
self:RegisterEvent(event);
end
for _, event in pairs(ChatTypeGroup["BN_WHISPER"]) do
self:RegisterEvent(event);
end
for _, event in pairs(ChatTypeGroup["WHISPER"]) do
self:RegisterEvent(event);
end
end
function FloatingChatFrameManager_OnEvent(self, event, ...)
local arg1 = ...;
if ( strsub(event, 1, 9) == "CHAT_MSG_" ) then
local chatType = strsub(event, 10);
local chatGroup = Chat_GetChatCategory(chatType);
if ( chatGroup == "BN_CONVERSATION" ) then
if ( GetCVar("conversationMode") == "popout" or GetCVar("conversationMode") == "popout_and_inline" ) then
if( not (event == "CHAT_MSG_BN_CONVERSATION_NOTICE" and arg1 == "YOU_LEFT_CONVERSATION") ) then
local chatTarget = tostring(select(8, ...));
if ( FCFManager_GetNumDedicatedFrames(chatGroup, chatTarget) == 0 ) then
local chatFrame = FCF_OpenTemporaryWindow(chatGroup, chatTarget);
chatFrame:GetScript("OnEvent")(chatFrame, event, ...); --Re-fire the event for the frame.
elseif (GetCVar("conversationMode") == "popout_and_inline" and BNIsSelf(select(13, ...))) then
FCFManager_StopFlashOnDedicatedWindows(chatGroup, chatTarget);
end
end
end
end
if ( (chatGroup == "BN_WHISPER" and (GetCVar("bnWhisperMode") == "popout" or GetCVar("bnWhisperMode") == "popout_and_inline"))
or (chatGroup == "WHISPER" and (GetCVar("whisperMode") == "popout" or GetCVar("whisperMode") == "popout_and_inline"))) then
local chatTarget = tostring(select(2, ...));
if ( FCFManager_GetNumDedicatedFrames(chatGroup, chatTarget) == 0 ) then
local chatFrame = FCF_OpenTemporaryWindow(chatGroup, chatTarget);
chatFrame:GetScript("OnEvent")(chatFrame, event, ...); --Re-fire the event for the frame.
-- If you started the whisper, immediately select the tab
if ((event == "CHAT_MSG_WHISPER_INFORM" and GetCVar("whisperMode") == "popout")
or (event == "CHAT_MSG_BN_WHISPER_INFORM" and GetCVar("bnWhisperMode") == "popout") ) then
FCF_SelectDockFrame(chatFrame);
FCF_FadeInChatFrame(chatFrame);
end
else
-- While in "Both" mode, if you reply to a whisper, stop the flash on that dedicated whisper tab
if ( (chatType == "WHISPER_INFORM" and GetCVar("whisperMode") == "popout_and_inline")
or (chatType == "BN_WHISPER_INFORM" and GetCVar("bnWhisperMode") == "popout_and_inline")) then
FCFManager_StopFlashOnDedicatedWindows(chatGroup, chatTarget);
end
end
end
end
end