2518 lines
78 KiB
Lua
2518 lines
78 KiB
Lua
-- 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;
|
|
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
|
|
else
|
|
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();
|
|
if ( FCF_GetCurrentChatFrame(dropDown) and FCF_GetCurrentChatFrame(dropDown).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 shown 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" ) 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
|
|
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.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);
|
|
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);
|
|
|
|
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);
|
|
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";
|
|
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
|
|
--Stop displaying this type of chat in the old chat frame.
|
|
if ( chatType == "WHISPER" or chatType == "BN_WHISPER" ) then
|
|
ChatFrame_ExcludePrivateMessageTarget(sourceChatFrame, chatTarget);
|
|
elseif ( chatType == "BN_CONVERSATION" ) then
|
|
ChatFrame_ExcludeBNConversationTarget(sourceChatFrame, chatTarget);
|
|
end
|
|
|
|
--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
|
|
--Remove the messages from the old frame.
|
|
sourceChatFrame:RemoveMessagesByAccessID(accessID);
|
|
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_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(4);
|
|
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, 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
|
|
UIFrameFlashRemoveFrame(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
|
|
|
|
-- 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" ) 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);
|
|
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";
|
|
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, 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" ) then
|
|
return true;
|
|
end
|
|
|
|
return false;
|
|
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
|
|
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" ) 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.
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end |